springmvc-学习总结-注解
2017-03-30 11:30
507 查看
我是参考这里:http://jinnianshilongnian.iteye.com/blog/1752171 很好的文章。自己总结一下,以便日后查找。
@Controller
@Controller 用于标注处理器类
对于处理器类中的处理方法,可以有哪些返回值?
(a)、ModelAndView 添加数据并知道view
(b)、void
在controller方法形参上可以定义request和response,使用request或response指定响应结果:
1、使用request转向页面,如下:
request.getRequestDispatcher("页面路径").forward(request, response);
2、也可以通过response页面重定向:
response.sendRedirect("url")
3、也可以通过response指定响应结果,例如响应json数据如下:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");
(c)、String字符串
返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址
(d)、Redirect重定向
由于新发起一个request原来的参数在转发时就不能传递到下一个url,如果要传参数可以test5?...&...
(e)、Forward转发
@RequestMapping
@RequestMapping(value={"/student/query","/item/query"})多个url映射到同一个处理器
@RequestMapping("/get") 单个url映射到处理器,value可以默认不写
@RequestMapping("/getById/{id}") {xxxxxx}占位符,从url中获取参数,需要配合@PathVariable获取参数
@RequestMapping("/getStudent/{abc}/Id") 等等其他方式
记录一下这个:
?匹配一个字符
*匹配0个或多个字符
** 匹配0个或多个字符或路径
带正则表达式的url(从spring3.0开始)
格式为:{变量名:正则表达式}
如:@RequestMapping(value="/products/{categoryCode:\\d+}-{pageNumber:\\d+}")
请求方法的限定
在进行表单操作时,涉及到post和get方法提交,可以通过注解方式解决。
还有get和post同时支持的方式(默认不写既支持post也支持get)
DispatcherServlet默认支持GET、POST、PUT、DELETE、HEAD。
如果需要支持OPTIONS、TRACE,请添加DispatcherServlet在web.xml的初始化参数:dispatchOptionsRequest 和 dispatchTraceRequest 为true
请求参数限定
1、请求路径中含有指定参数名
请求路径:http://localhost:8080/springMVC-anon/classes?create=123
即请求参数中有"create"的参数名并且是get请求。post同理,只需要把请求方式改一下就可以。
2、请求路径中不含有指定参数名
即请求参数中没有“create”的参数名并且是get请求。
原博中说的特别好,可以用到一下CRUD场景:
(create请求参数名 且 GET请求方法) 新增页面展示、(create请求参数名 且 POST请求方法)新增提交;
(update请求参数名 且 GET请求方法) 新增页面展示、(update请求参数名 且 POST请求方法)新增提交;
(delete请求参数名 且 GET请求方法) 新增页面展示、(delete请求参数名 且 POST请求方法)新增提交;
(query请求参数名 且 GET请求方法) 新增页面展示、(query请求参数名 且 POST请求方法) 新增提交;
(list请求参数名 且 GET请求方法) 列表页面展示;
(view请求参数名 且 GET请求方法) 查看单条记录页面展示。
3、请求路径中指定参数名和值
即请求参数中有“flag=abc”的请求参数。
(flag=create请求参数名 且 GET请求方法) 新增页面展示、(create请求参数名 且 POST请求方法)新增提交;
(flag=update请求参数名 且 GET请求方法) 新增页面展示、(update请求参数名 且 POST请求方法)新增提交;
(flag=delete请求参数名 且 GET请求方法) 新增页面展示、(delete请求参数名 且 POST请求方法)新增提交;
(flag=query请求参数名 且 GET请求方法) 新增页面展示、(query请求参数名 且 POST请求方法) 新增提交;
(flag=list请求参数名 且 GET请求方法) 列表页面展示;
(flag=view请求参数名 且 GET请求方法) 查看单条记录页面展示。
4、请求路径中指定参数名!=值
5、组合使用表示且的意思
即表示请求路径中有“flag=create&stuNo=123”的参数
注意:params多个值是且的意思!!method、value多个值是或的意思!!
Content-Type
内容类型,即表示请求/响应时内容区的内容格式。
1、Content-Type=application/x-www-form-urlencoded表示请求的内容为key/value形式
获取编码:request.getCharacterEncoding() 如“Content-Type:application/json;charset=GBK”,则得到的编码为“GBK”,否则如果你设置过滤器(CharacterEncodingFilter)则得到它设置的编码,否则返回null。
2、Content-Type=application/json表示请求的内容区数据为json类型数据
3、通过response.setContentType(""),表示发送到客户端的数据内容类型,如response.setContentType("text/html;charset=utf-8")
①客户端—发送请求—服务器:客户端通过请求头Content-Type指定内容体的媒体类型(即客户端此时是生产者),服务器根据Content-Type消费内容体数据(即服务器此时是消费者);
②服务器—发送请求—客户端:服务器生产响应头Content-Type指定的响应体数据(即服务器此时是生产者),客户端根据Content-Type消费内容体数据(即客户端此时是消费者)。
问:服务器可以根据Content-Type指定可以处理的数据类型,客户端如何告诉服务器自己可以处理的数据类型?
Accept
用来指定什么媒体类型的响应是可接受的,即告诉服务器我需要什么媒体类型的数据,此时服务器应该根据Accept请求头生产指定媒体类型的数据
1、Accept=application/json表示客户端只处理json格式数据
测试:
2、Accept=application/xml表示客户端只处理xml格式数据
同上...
总结:
请求阶段:客户端是生产者【生产Content-Type媒体类型的请求内容区数据】,服务器是消费者【消费客户端生产的Content-Type媒体类型的请求内容区数据】;
响应阶段:服务器是生产者【生产客户端请求头参数Accept指定的响应体数据】,客户端是消费者【消费服务器根据Accept请求头生产的响应体数据】。
spring3.1开始支持这种生产者,消费者模式。并且使用如下的映射器,适配器
consumes
用来表示action中的某方法可以处理的请求内容数据类型,通过请求头中的Content-Type来进行判断。如:可以处理json数据类型
produces
用来表示action中的某方法可以产生什么类型的数据,通过请求头中的Accept进行匹配。如:可以生成xml格式的数据类型
注意:如果类级别为produces="application/xml" 而方法级别为 produces="application/json" 则方法级别的将覆盖类级别的。即请求头中"Accetp:application/json"将请求成功。
consumes、produces可以配置多个值,表示或的意思。
上面内容可以保证将请求发送到对应的处理器,下面为springmvc绑定数据(常用)
@RequestParam:处理器方法参数注解
如果请求的参数和请求方法中的参数,名称不对应时,可以使用此注解
该注解中存在其他属性,value:参数名称 required:是否必须,默认true defaultValue:默认值
其中属性value:参数名字,即请求的参数名字,如value="username"表示请求的参数名字为username的参数的值将传入。方法区中可以定义参数String abc与之对应。即方法区中的对应的参数名可以任意
1、绑定单个请求参数值
注意:基本类型必须有值,否则抛出异常。要想允许为空,用它的包装类。引用类型默认为null
2、多个请求参数场景
(a)、数组:
或者
jsp页面所选框
(b)、list
批量做什么,比如jsp:
controller:
controller方法中Vo定义如下,直接写List<Student> 报错
(c)Map
jsp:
controller:
@PathVariable:处理器方法参数注解
截取url中变量到方法的请求参数中
@CookieValue:处理器方法参数注解
@RequestHeader:处理器方法参数注解
将请求头中的信息映射到处理器请求参数上
@ModelAttribute:处理器方法参数注解
①绑定请求参数到命令对象:放在功能处理方法的入参上时,用于将多个请求参数绑定到一个命令对象,从而简化绑定流程,而且自动暴露为模型数据用于视图页面展示时使用;
②暴露表单引用对象为模型数据:放在处理器的一般方法(非功能处理方法)上时,是为表单准备要展示的表单引用对象,如注册时需要选择的所在城市等,而且在执行功能处理方法(@RequestMapping注解的方法)之前,自动添加到模型对象中,用于视图页面展示时使用;
③暴露@RequestMapping方法返回值为模型数据:放在功能处理方法的返回值上时,是暴露功能处理方法的返回值为模型数据,用于视图页面展示时使用。
①
绑定请求参数对象到命令对象
注:此时也可以省略@ModelAttribute注解
url方式传值
http://localhost:8080/springmvc-06-Verification/user2?username=1&password=2
如果UserModel中包含WorkInfoModel对象,而WorkInfoModel中包含city属性。可以用此方式给city赋值
举个例子:比如用户修改页面,如果修改失败后,页面上还想继续显示用户信息,jsp页面的el表达式取值如果是${userModel.xxx}没有问题,上面的写法可以取到值,如果页面上是${user.xxx},那么我们需要将上面方法中的参数注解修改一下:
@RequestMapping("/user2")
public String test03(@ModelAttribute("user") UserModel user){
System.out.println(user);
return null;
}原因是:springmvc自动将pojo数据放到request域,key等于pojo类型(首字母小写),此处使用@ModelAttribute指定pojo回显到页面在request中的key为user
②暴露表单引用对象为模型数据
此时断点调试,查看model中的内容为:
jsp页面显示:
pageEncoding="UTF-8" isELIgnored="false"%>
③、
test1()方法参数中的stu即是getStudent()方法的返回值。
(1、首先执行@ModelAttribute注解的方法,准备视图展示时所需要的模型数据;@ModelAttribute注解方法形式参数规则和@RequestMapping规则一样,如可以有@RequestParam等;
(2、执行@RequestMapping注解方法,进行模型绑定时首先查找模型数据中是否含有同名对象,如果有直接使用,如果没有通过反射创建一个,因此②处的user将使用①处返回的命令对象。即②处的user等于①处的user。
④、如果我们没有提供暴露到页面中的对象名
对于集合类型(Collection接口的实现者们,包括数组),生成的模型对象属性名为“简单类名(首字母小写)”+“List”,如List<String>生成的模型对象属性名为“stringList”,List<UserModel>生成的模型对象属性名为“userModelList”。
其他情况一律都是使用简单类名(首字母小写)作为模型对象属性名,如Map<String, UserModel>类型的模型对象属性名为“map”。
test1()方法页面中取值:
自定义参数绑定
pojo代码:
首先写自己定义的转换器:
所有操作都是在springmvc-servlet.xml即springmvc配置文件中进行
方法一:
在适配器中,注入我们自定义的转换器
方法二:
@Controller
@Controller 用于标注处理器类
对于处理器类中的处理方法,可以有哪些返回值?
(a)、ModelAndView 添加数据并知道view
@RequestMapping("test1") public ModelAndView test1(){ ModelAndView mv = new ModelAndView(); mv.addObject("params", "中国"); mv.setViewName("controller7-1"); return mv; }
(b)、void
在controller方法形参上可以定义request和response,使用request或response指定响应结果:
1、使用request转向页面,如下:
request.getRequestDispatcher("页面路径").forward(request, response);
@RequestMapping("test2") public void test2(HttpServletRequest request,HttpServletResponse response){ try { request.setAttribute("params", "test2"); request.getRequestDispatcher("/WEB-INF/jsp/controller7-2.jsp").forward(request, response); } catch (Exception e) { e.printStackTrace(); } }
2、也可以通过response页面重定向:
response.sendRedirect("url")
@RequestMapping("test3") public void test3(HttpServletRequest request,HttpServletResponse response){ try { response.sendRedirect("test4"); } catch (IOException e) { e.printStackTrace(); } }
3、也可以通过response指定响应结果,例如响应json数据如下:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");
@RequestMapping("test4") public void test4(HttpServletRequest request,HttpServletResponse response) throws IOException{ response.setCharacterEncoding("utf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().write("{'params':'bb'}"); }
(c)、String字符串
返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址
@RequestMapping("test5") public String test5(HttpServletRequest request,HttpServletResponse response) throws IOException{ return "controller7-5"; }
(d)、Redirect重定向
@RequestMapping("test6") public String test6(HttpServletRequest request,HttpServletResponse response) throws IOException{ return "redirect:test5"; }redirect方式相当于“response.sendRedirect()”,转发后浏览器的地址栏变为转发后的地址,因为转发即执行了一个新的request和response。
由于新发起一个request原来的参数在转发时就不能传递到下一个url,如果要传参数可以test5?...&...
(e)、Forward转发
@RequestMapping("test7") public String test7(HttpServletRequest request,HttpServletResponse response) throws IOException{ return "forward:test1"; }forward方式相当于“request.getRequestDispatcher().forward(request,response)”,转发后浏览器地址栏还是原来的地址。转发并没有执行新的request和response,而是和转发前的请求共用一个request和response。所以转发前请求的参数在转发后仍然可以读取到
@RequestMapping
@RequestMapping(value={"/student/query","/item/query"})多个url映射到同一个处理器
@RequestMapping(value={"/student/query","/item/query"}) public ModelAndView query() throws Exception{ ModelAndView mv = new ModelAndView(); mv.addObject("message", "query"); mv.setViewName("hello"); return mv; }
@RequestMapping("/get") 单个url映射到处理器,value可以默认不写
@RequestMapping("/get") public ModelAndView get() throws Exception{ ModelAndView mv = new ModelAndView(); mv.addObject("message", "get"); mv.setViewName("hello"); return mv; }
@RequestMapping("/getById/{id}") {xxxxxx}占位符,从url中获取参数,需要配合@PathVariable获取参数
@RequestMapping("/getStudent/{abc}/Id") 等等其他方式
@RequestMapping("/getById/{id}") public ModelAndView getById(@PathVariable String id) throws Exception{ System.out.println(id); ModelAndView mv = new ModelAndView(); mv.addObject("message", "get"); mv.setViewName("hello"); return mv; }
@RequestMapping("/getStudent/{abc}/Id") public ModelAndView getStudent(@PathVariable String abc) throws Exception{ System.out.println(abc); ModelAndView mv = new ModelAndView(); mv.addObject("message", "get"); mv.setViewName("hello"); return mv; }
记录一下这个:
@RequestMapping("/student/{id}")//http://localhost:8080/springMVC-anon/student/1 public ModelAndView query5(@PathVariable String id) throws Exception{ ModelAndView mv = new ModelAndView(); mv.addObject("message", "query5"); mv.setViewName("hello"); return mv; } @RequestMapping("/student?")//http://localhost:8080/springMVC-anon/student1 public ModelAndView query4() throws Exception{ ModelAndView mv = new ModelAndView(); mv.addObject("message", "query4"); mv.setViewName("hello"); return mv; } @RequestMapping("/student*")//http://localhost:8080/springMVC-anon/student11 public ModelAndView query3() throws Exception{ ModelAndView mv = new ModelAndView(); mv.addObject("message", "query3"); mv.setViewName("hello"); return mv; } @RequestMapping("/student/*") public ModelAndView query2() throws Exception{ ModelAndView mv = new ModelAndView(); mv.addObject("message", "query2"); mv.setViewName("hello"); return mv; } @RequestMapping("/student/**")//http://localhost:8080/springMVC-anon/student/abc/1 public ModelAndView query1() throws Exception{ ModelAndView mv = new ModelAndView(); mv.addObject("message", "query1"); mv.setViewName("hello"); return mv; } @RequestMapping("/student/**/{id}") public ModelAndView query0(@PathVariable String id) throws Exception{ ModelAndView mv = new ModelAndView(); mv.addObject("message", "query0"); mv.setViewName("hello"); return mv; }
?匹配一个字符
*匹配0个或多个字符
** 匹配0个或多个字符或路径
带正则表达式的url(从spring3.0开始)
格式为:{变量名:正则表达式}
如:@RequestMapping(value="/products/{categoryCode:\\d+}-{pageNumber:\\d+}")
@RequestMapping(value="/products/{categoryCode:\\d+}-{pageNumber:\\d+}") public ModelAndView create(@PathVariable String pageNumber) throws Exception{//参数也可以写成@PathVariable String categoryCode ModelAndView mv = new ModelAndView(); mv.addObject("message", "create"); mv.setViewName("hello"); return mv; }
请求方法的限定
在进行表单操作时,涉及到post和get方法提交,可以通过注解方式解决。
@Controller @RequestMapping("student") public class Controller4 { @RequestMapping(value="toCreate",method=RequestMethod.GET) public String createStu1(){ System.out.println("===get==="); return "student/stu1"; } @RequestMapping(value="toCreate",method=RequestMethod.POST) public String createStu2(){ System.out.println("===post==="); return "student/stu2"; } }
<html> <body> <form action="student/toCreate" method="get"> <input type="submit" value="提交1"><!-- 请求到后台的get方法 --> </form> <form action="student/toCreate" method="post"> <input type="submit" value="提交2"><!-- 请求到后台的post方法 --> </form> </body> </html>
还有get和post同时支持的方式(默认不写既支持post也支持get)
@RequestMapping(value="toNew",method={RequestMethod.GET,RequestMethod.POST}) public String createStu3(){ System.out.println("===getAndPost==="); return "student/stu3"; }除了get和post以外还,还有下面的请求方式:
DispatcherServlet默认支持GET、POST、PUT、DELETE、HEAD。
如果需要支持OPTIONS、TRACE,请添加DispatcherServlet在web.xml的初始化参数:dispatchOptionsRequest 和 dispatchTraceRequest 为true
请求参数限定
1、请求路径中含有指定参数名
@Controller @RequestMapping("classes") public class Controller4 { @RequestMapping(params="create",method=RequestMethod.GET) public String createStu3(){ System.out.println("===params==="); return "student/stu3"; } }
请求路径:http://localhost:8080/springMVC-anon/classes?create=123
即请求参数中有"create"的参数名并且是get请求。post同理,只需要把请求方式改一下就可以。
2、请求路径中不含有指定参数名
@Controller @RequestMapping("classes") public class Controller4 { @RequestMapping(params="!create",method=RequestMethod.GET) public String createStu4(){ System.out.println("===params==="); return "student/stu4"; } }请求路径:http://localhost:8080/springMVC-anon/classes?abcd=123
即请求参数中没有“create”的参数名并且是get请求。
原博中说的特别好,可以用到一下CRUD场景:
(create请求参数名 且 GET请求方法) 新增页面展示、(create请求参数名 且 POST请求方法)新增提交;
(update请求参数名 且 GET请求方法) 新增页面展示、(update请求参数名 且 POST请求方法)新增提交;
(delete请求参数名 且 GET请求方法) 新增页面展示、(delete请求参数名 且 POST请求方法)新增提交;
(query请求参数名 且 GET请求方法) 新增页面展示、(query请求参数名 且 POST请求方法) 新增提交;
(list请求参数名 且 GET请求方法) 列表页面展示;
(view请求参数名 且 GET请求方法) 查看单条记录页面展示。
3、请求路径中指定参数名和值
@Controller @RequestMapping("classes") public class Controller4 { @RequestMapping(params="flag=abc") public String createStu5(){ System.out.println("===stu5==="); return "student/stu5"; } }请求路径:http://localhost:8080/springMVC-anon/classes?flag=abc
即请求参数中有“flag=abc”的请求参数。
(flag=create请求参数名 且 GET请求方法) 新增页面展示、(create请求参数名 且 POST请求方法)新增提交;
(flag=update请求参数名 且 GET请求方法) 新增页面展示、(update请求参数名 且 POST请求方法)新增提交;
(flag=delete请求参数名 且 GET请求方法) 新增页面展示、(delete请求参数名 且 POST请求方法)新增提交;
(flag=query请求参数名 且 GET请求方法) 新增页面展示、(query请求参数名 且 POST请求方法) 新增提交;
(flag=list请求参数名 且 GET请求方法) 列表页面展示;
(flag=view请求参数名 且 GET请求方法) 查看单条记录页面展示。
4、请求路径中指定参数名!=值
@Controller @RequestMapping("classes") public class Controller4 { @RequestMapping(params="flag!=abc") public String createStu5(){ System.out.println("===stu5==="); return "student/stu5"; } }
5、组合使用表示且的意思
@Controller @RequestMapping("classes") public class Controller4 { @RequestMapping(params={"flag=create","stuNo=123"}) public String createStu6(){ System.out.println("===stu6==="); return "student/stu6"; } }请求路径:http://localhost:8080/springMVC-anon/classes?flag=create&stuNo=123
即表示请求路径中有“flag=create&stuNo=123”的参数
注意:params多个值是且的意思!!method、value多个值是或的意思!!
Content-Type
内容类型,即表示请求/响应时内容区的内容格式。
1、Content-Type=application/x-www-form-urlencoded表示请求的内容为key/value形式
@RequestMapping(value="/contentType",method=RequestMethod.POST,headers="Content-Type=application/x-www-form-urlencoded") public String request(HttpServletRequest request){ System.out.println(request.getContentType()); System.out.println(request.getCharacterEncoding()); System.out.println(request.getParameter("realname")); System.out.println(request.getParameter("username")); return "success"; }上面的方法表示只对请求头为application/x-www-form-urlencoded的请求进行处理。
获取编码:request.getCharacterEncoding() 如“Content-Type:application/json;charset=GBK”,则得到的编码为“GBK”,否则如果你设置过滤器(CharacterEncodingFilter)则得到它设置的编码,否则返回null。
2、Content-Type=application/json表示请求的内容区数据为json类型数据
@RequestMapping(value = "/request/ContentType", method = RequestMethod.POST,headers = "Content-Type=application/json") public String request2(HttpServletRequest request) throws IOException { InputStream is = request.getInputStream(); byte bytes[] = new byte[request.getContentLength()]; is.read(bytes); String jsonStr = new String(bytes, request.getCharacterEncoding()); System.out.println("json data:" + jsonStr); return "success"; }这样可以将前端传过来的json字符串转换为我们需要的指定对象。
3、通过response.setContentType(""),表示发送到客户端的数据内容类型,如response.setContentType("text/html;charset=utf-8")
@RequestMapping(value = "/request/ContentType", method = RequestMethod.POST) public void request3(HttpServletRequest request,HttpServletResponse response) throws IOException { //①表示响应的内容区数据的媒体类型为html格式,且编码为utf-8(客户端应该以utf-8解码) response.setContentType("text/html;charset=utf-8"); //②写出响应体内容 response.getWriter().write("<font style='color:red'>hello</font>"); }总结:
①客户端—发送请求—服务器:客户端通过请求头Content-Type指定内容体的媒体类型(即客户端此时是生产者),服务器根据Content-Type消费内容体数据(即服务器此时是消费者);
②服务器—发送请求—客户端:服务器生产响应头Content-Type指定的响应体数据(即服务器此时是生产者),客户端根据Content-Type消费内容体数据(即客户端此时是消费者)。
问:服务器可以根据Content-Type指定可以处理的数据类型,客户端如何告诉服务器自己可以处理的数据类型?
Accept
用来指定什么媒体类型的响应是可接受的,即告诉服务器我需要什么媒体类型的数据,此时服务器应该根据Accept请求头生产指定媒体类型的数据
1、Accept=application/json表示客户端只处理json格式数据
@RequestMapping(value = "/request/ContentType", method = RequestMethod.POST,headers = "Accept=application/json") public void request4(HttpServletRequest request,HttpServletResponse response) throws IOException { //①表示响应的内容区数据的媒体类型为json格式,且编码为utf-8(客户端应该以utf-8解码) response.setContentType("application/json;charset=utf-8"); //②写出响应体内容 String jsonData = "{\"username\":\"zhang\", \"password\":\"123\"}"; response.getWriter().write(jsonData); }
测试:
public static void main(String[] args) throws IOException, URISyntaxException { //请求的地址 String url = "http://localhost:8080/springMVC-anon/emp/request/ContentType"; //①创建Http Request(内部使用HttpURLConnection) ClientHttpRequest request = new SimpleClientHttpRequestFactory().createRequest(new URI(url), HttpMethod.POST); //②设置客户端可接受的媒体类型(即需要什么类型的响应体数据) request.getHeaders().set("Accept", "application/json"); //③发送请求并得到响应 ClientHttpResponse response = request.execute(); //④得到响应体的编码方式 Charset charset = response.getHeaders().getContentType().getCharSet(); //⑤得到响应体的内容 InputStream is = response.getBody(); byte bytes[] = new byte[(int)response.getHeaders().getContentLength()]; is.read(bytes); String jsonData = new String(bytes, charset); System.out.println("charset : " + charset + ", json data : " + jsonData); }
2、Accept=application/xml表示客户端只处理xml格式数据
同上...
总结:
请求阶段:客户端是生产者【生产Content-Type媒体类型的请求内容区数据】,服务器是消费者【消费客户端生产的Content-Type媒体类型的请求内容区数据】;
响应阶段:服务器是生产者【生产客户端请求头参数Accept指定的响应体数据】,客户端是消费者【消费服务器根据Accept请求头生产的响应体数据】。
spring3.1开始支持这种生产者,消费者模式。并且使用如下的映射器,适配器
<!--Spring3.1开始的注解 HandlerMapping --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <!--Spring3.1开始的注解 HandlerAdapter --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
consumes
用来表示action中的某方法可以处理的请求内容数据类型,通过请求头中的Content-Type来进行判断。如:可以处理json数据类型
@RequestMapping(value="/deal/json",consumes="application/json") public void deal1(){ }
produces
用来表示action中的某方法可以产生什么类型的数据,通过请求头中的Accept进行匹配。如:可以生成xml格式的数据类型
@RequestMapping(value="/deal/json",produces="application/xml") public void deal2(){ }
注意:如果类级别为produces="application/xml" 而方法级别为 produces="application/json" 则方法级别的将覆盖类级别的。即请求头中"Accetp:application/json"将请求成功。
consumes、produces可以配置多个值,表示或的意思。
上面内容可以保证将请求发送到对应的处理器,下面为springmvc绑定数据(常用)
@RequestParam:处理器方法参数注解
如果请求的参数和请求方法中的参数,名称不对应时,可以使用此注解
该注解中存在其他属性,value:参数名称 required:是否必须,默认true defaultValue:默认值
其中属性value:参数名字,即请求的参数名字,如value="username"表示请求的参数名字为username的参数的值将传入。方法区中可以定义参数String abc与之对应。即方法区中的对应的参数名可以任意
1、绑定单个请求参数值
@Controller @RequestMapping("/anno") public class RequestParamAnn { /** * 鼠标右键项目-->properties-->java compiler-->add variable ...(取消勾选) * 否则以此方式注入username值,不会报Name for argument...的异常 * 取消勾选后,requestParam1写法会报错,requestParam2方法正常 * @param username * @return */ @RequestMapping(value="/requestParam1") public String requestParam1(@RequestParam String username){ System.out.println(username); return "hello"; } @RequestMapping(value="/requestParam2") public String requestParam2(@RequestParam(value="username") String username){ System.out.println(username); return "hello"; } }
@RequestMapping(value="/requestParam4") public String requestParam4(@RequestParam(value="username",required=false,defaultValue="lee") String username){ System.out.println(username); return "hello"; }
注意:基本类型必须有值,否则抛出异常。要想允许为空,用它的包装类。引用类型默认为null
2、多个请求参数场景
(a)、数组:
/** * 多个参数,如授权 * 请求:http://localhost:8080/springmvc-05-anno2/anno/requestParam5?role=123&role=456 * @param username * @return */ @RequestMapping(value="/requestParam5") public String requestParam5(@RequestParam(value="role") String[] roleList){ System.out.println(roleList.length); return "hello"; } /** * 多个参数,如授权 * 请求:url?role=admin&role=user * @param username * @return */ @RequestMapping(value="/requestParam6") public String requestParam6(@RequestParam(value="role") List<String> roleList){ System.out.println(roleList.size()); return "hello"; }
或者
jsp页面所选框
<form action="controller7/test8" method="post"> <input type="checkbox" value="1" name="id">1<br> <input type="checkbox" value="2" name="id">2<br> <input type="checkbox" value="3" name="id">3<br> <input type="checkbox" value="4" name="id">4<br> <input type="submit" value="提交"> </form>
@RequestMapping("test8") public String test8(String[] id) throws IOException{ return "forward:test1"; }
(b)、list
批量做什么,比如jsp:
<form action="controller7/test9"> <table> <tr> <td> <input type="text" name="stuList[0].sid" value="${stu.sid}"/> </td> <td> <input type="text" name="stuList[0].sname" value="${stu.sname }"/> </td> <td> <input type="text" name="stuList[0].createtime" value="${stu.createtime}"/> </td> </tr> <tr> <td> <input type="text" name="stuList[1].sid" value="${stu.sid}"/> </td> <td> <input type="text" name="stuList[1].sname" value="${stu.sname }"/> </td> <td> <input type="text" name="stuList[1].createtime" value="${stu.createtime}"/> </td> </tr> </table> <input type="submit" value="提交"> </form>
controller:
@RequestMapping("test9") public String test9(Vo vo) throws IOException{ return "forward:test1"; }
controller方法中Vo定义如下,直接写List<Student> 报错
public class Vo { private List<Student> stuList; public List<Student> getStuList() { return stuList; } public void setStuList(List<Student> stuList) { this.stuList = stuList; } }
(c)Map
jsp:
<form action="controller7/test10" method="post"> <input type="text" name="stuMap['sid']" > <input type="text" name="stuMap['sname']" > <input type="text" name="stuMap['createtime']" > <input type="submit" value="保存"> </form>
controller:
@RequestMapping("test10") public String test10(Vo vo) throws IOException{ return "forward:test1"; }
public class Vo { private List<Student> stuList; private Map<String,Object> stuMap = new HashMap<String,Object>(); public List<Student> getStuList() { return stuList; } public void setStuList(List<Student> stuList) { this.stuList = stuList; } public Map<String, Object> getStuMap() { return stuMap; } public void setStuMap(Map<String, Object> stuMap) { this.stuMap = stuMap; } }
@PathVariable:处理器方法参数注解
截取url中变量到方法的请求参数中
/** * http://localhost:8080/springmvc-05-anno2/users/123/topics/456 * @param userId * @param topicId * @return */ @RequestMapping(value="/users/{userId}/topics/{topicId}") public String test(@PathVariable(value="userId") int userId, @PathVariable(value="topicId") int topicId) { System.out.println(userId+"========"+topicId);//123========456 return "hello"; }
@CookieValue:处理器方法参数注解
@RequestMapping(value="/cookies1") public String test2(@CookieValue(value="JSESSIONID",defaultValue="")Cookie sessionid) { System.out.println(sessionid); return "hello"; } @RequestMapping(value="/cookies2") public String test3(@CookieValue(value="JSESSIONID",defaultValue="")String sessionid) { System.out.println(sessionid); return "hello"; }结果:javax.servlet.http.Cookie@ba3e79 B145EF89447E4B2FEBA2B6F143D275BA
@RequestHeader:处理器方法参数注解
将请求头中的信息映射到处理器请求参数上
@RequestMapping("/header") public String test01(@RequestHeader("User-Agent")String userAgent,@RequestHeader("Accept")String[] accepts){ System.out.println(userAgent); System.out.println(accepts.toString()); return null; }
@ModelAttribute:处理器方法参数注解
①绑定请求参数到命令对象:放在功能处理方法的入参上时,用于将多个请求参数绑定到一个命令对象,从而简化绑定流程,而且自动暴露为模型数据用于视图页面展示时使用;
②暴露表单引用对象为模型数据:放在处理器的一般方法(非功能处理方法)上时,是为表单准备要展示的表单引用对象,如注册时需要选择的所在城市等,而且在执行功能处理方法(@RequestMapping注解的方法)之前,自动添加到模型对象中,用于视图页面展示时使用;
③暴露@RequestMapping方法返回值为模型数据:放在功能处理方法的返回值上时,是暴露功能处理方法的返回值为模型数据,用于视图页面展示时使用。
①
绑定请求参数对象到命令对象
注:此时也可以省略@ModelAttribute注解
@RequestMapping("/user") public String test02(@ModelAttribute UserModel user){ System.out.println(user); return null; }form表单
<form action="${pageContext.request.contextPath }/user" method="post"> <input name="username" type="text"><br> <input name="password" type="text"><br> <input name="realname" type="text"><br> <input type="submit" value="注册"> </form>
url方式传值
http://localhost:8080/springmvc-06-Verification/user2?username=1&password=2
如果UserModel中包含WorkInfoModel对象,而WorkInfoModel中包含city属性。可以用此方式给city赋值
@RequestMapping("/user2") public String test03(@ModelAttribute UserModel user){ System.out.println(user); return null; }form表单
<form action="${pageContext.request.contextPath }/user2" method="post"> <input name="username" type="text"><br> <input name="password" type="text"><br> <input name="realname" type="text"><br> <input name="workInfo.city" type="text"><br> <input type="submit" value="注册"> </form>url方式传值 http://localhost:8080/springmvc-06-Verification/user2?username=1&password=2&workInfo.city=北京
举个例子:比如用户修改页面,如果修改失败后,页面上还想继续显示用户信息,jsp页面的el表达式取值如果是${userModel.xxx}没有问题,上面的写法可以取到值,如果页面上是${user.xxx},那么我们需要将上面方法中的参数注解修改一下:
@RequestMapping("/user2")
public String test03(@ModelAttribute("user") UserModel user){
System.out.println(user);
return null;
}原因是:springmvc自动将pojo数据放到request域,key等于pojo类型(首字母小写),此处使用@ModelAttribute指定pojo回显到页面在request中的key为user
②暴露表单引用对象为模型数据
@ModelAttribute("city") public List<String> cityList() { return Arrays.asList("北京", "山东"); } @RequestMapping(value="/getStudent") //② public String test1(@ModelAttribute("student") Student stu, Model model){ System.out.println(model.containsAttribute("city"));//true return "student/stu6"; }
此时断点调试,查看model中的内容为:
jsp页面显示:
<body> <c:forEach items="${city }" var="ct"> ${ct }<!--北京 山东--> </c:forEach> </body>注:如果el表达式被当作字符串处理,加上标红的那句话:<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
③、
@RequestMapping(value="/getStudent") public String test1(@ModelAttribute("student") Student stu){ return "student/stu6"; } @ModelAttribute("student") public Student getStudent(@RequestParam(value="sname", defaultValue="") String sname) { //TODO 去数据库根据用户名查找用户对象 Student stu = new Student(); stu.setSname("zhang"); return stu; }
test1()方法参数中的stu即是getStudent()方法的返回值。
(1、首先执行@ModelAttribute注解的方法,准备视图展示时所需要的模型数据;@ModelAttribute注解方法形式参数规则和@RequestMapping规则一样,如可以有@RequestParam等;
(2、执行@RequestMapping注解方法,进行模型绑定时首先查找模型数据中是否含有同名对象,如果有直接使用,如果没有通过反射创建一个,因此②处的user将使用①处返回的命令对象。即②处的user等于①处的user。
④、如果我们没有提供暴露到页面中的对象名
对于集合类型(Collection接口的实现者们,包括数组),生成的模型对象属性名为“简单类名(首字母小写)”+“List”,如List<String>生成的模型对象属性名为“stringList”,List<UserModel>生成的模型对象属性名为“userModelList”。
其他情况一律都是使用简单类名(首字母小写)作为模型对象属性名,如Map<String, UserModel>类型的模型对象属性名为“map”。
@RequestMapping("test1") public String test1(@ModelAttribute UserModel user, Model model){ System.out.println(model); //{userModel=UserModel [username=1, password=2, realname=3, //workInfo=WorkInfoModel [city=4, job=null, year=null], schoolInfo=null], //org.springframework.validation.BindingResult.userModel=org.springframework.validation.BeanPropertyBindingResult: 0 errors} return null; } @RequestMapping("test2") public String test2(@ModelAttribute("user") UserModel user, Model model){ System.out.println(model); //{user=UserModel [username=aaa, password=bbb, realname=ccc, //workInfo=WorkInfoModel [city=ddd, job=null, year=null], schoolInfo=null], //org.springframework.validation.BindingResult.user=org.springframework.validation.BeanPropertyBindingResult: 0 errors} return null; } @RequestMapping("test3") public String test3(UserModel user, Model model){ System.out.println(model); //{userModel=UserModel [username=!, password=@, realname=#, //workInfo=WorkInfoModel [city=$, job=null, year=null], schoolInfo=null], //org.springframework.validation.BindingResult.userModel=org.springframework.validation.BeanPropertyBindingResult: 0 errors} return null; }方法test1()和test3()一样,表单中的模型对象为userModel,test2()中表单模型对象为user。
test1()方法页面中取值:
userModel:${userModel.username }<br> <!--值为:1--> user:${user.username }<!--没值-->test2()方法页面中取值:
userModel:${userModel.username }<br><!--没值--> user:${user.username }<!--值为:aaa-->
自定义参数绑定
pojo代码:
public class Student { private String sid; private String sname; private Date createtime;//注意这里的类型是java.util.Date //其他省略 }jsp代码:
<form action="controller6/save" method="post"> <input type="text" name="sid" value="${student.sid }"> <input type="text" name="sname" value="${student.sname }" > <input type="text" name="createtime" value='<fmt:formatDate value="${student.createtime }" pattern="yyyy-MM-dd HH:mm:ss"/>' > <input type="submit" value="保存"> </form>controller:
@RequestMapping(value="/save") //② public String test2(Student stu){ return "student/stu6"; //return "redirect:save3"; }页面点击保存后,报400,需要加一个自定义类型绑定:即将页面输入的字符串类型,转换成date类型
首先写自己定义的转换器:
public class DateConversion implements Converter<String, Date> { public Date convert(String source) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { return sdf.parse(source); } catch (ParseException e) { e.printStackTrace(); } return null; } }
所有操作都是在springmvc-servlet.xml即springmvc配置文件中进行
方法一:
在适配器中,注入我们自定义的转换器
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="webBindingInitializer" ref="webBindingInitializer"></property> </bean>
<bean id="webBindingInitializer" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"> <property name="conversionService" ref="conversionService"></property> </bean>
<!-- 自定义转换器 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <list> <bean class="lee.conversions.DateConversion"></bean> </list> </property> </bean>
方法二:
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<!-- 自定义转换器 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <list> <bean class="lee.conversions.DateConversion"></bean> </list> </property> </bean>
相关文章推荐
- 【SpringMVC学习03】SpringMVC中注解和非注解方式下的映射器和适配器总结
- 【SpringMVC学习03】SpringMVC中注解和非注解方式下的映射器和适配器总结
- SpringMVC学习总结(四)——基于注解的SpringMVC简单介绍
- 【SpringMVC学习03】SpringMVC中注解和非注解方式下的映射器和适配器总结
- 【springmvc学习】常用注解总结
- 【SpringMVC学习03】SpringMVC中注解和非注解方式下的映射器和适配器总结
- SpringMVC学习总结(二).SpringMVC常用注解及视图
- 【SpringMVC学习03】SpringMVC中注解和非注解方式下的映射器和适配器总结
- Spring MVC学习总结(18)——SpringMVC事务Transactional注解使用总结
- SpringMVC学习总结(七)——SpringMVC注解@..详解
- springMVC学习笔记六(注解方式实现控制器)
- 黑马程序员----------------------反射reflect和注解学习总结
- Java反射学习总结终(使用反射和注解模拟JUnit单元测试框架)
- SpringMVC学习笔记(2) 框架配置+HelloWorld(注解版)
- SpringMVC入门学习(二)应用注解方式+注解优化
- SpringMVC学习总结(五)——SpringMVC文件上传例子
- android学习日记-4 JAVA注解总结
- SpringMVC学习总结(三)——Controller接口详解(1)