SpringMVC注解驱动的控制器详解

 林炳文Evankaka原创作品。转自https://blog.csdn.net/Evankaka/article/details/45562951

        Spring2.5引入注解式处理器支持,通过@Controller和@RequestMapping注解定义我们的处理器类。并且提供了一组强大的注解需要通过处理器映射DefaultAnnotationHandlerMapping和处理器适配器AnnotationMethodHandlerAdapter来开启支持@Controller和@RequestMapping注解的处理器。


@Controller:用于标识是处理器类;

@RequestMapping:请求到处理器功能方法的映射规则;

@RequestParam:请求参数到处理器功能处理方法的方法参数上的绑定;

@ModelAttribute:请求参数到命令对象的绑定;

@InitBinder:自定义数据绑定注册支持,用于将请求参数转换到命令对象属性的对应类型;

本文使用工程免费下载

一、视图返回

1、返回String对象


    
    
  1. @RequestMapping(value = "/index") //相对于根目录的路径
  2. public String test(ModelMap model) {
  3. model.addAttribute( "message", "调用FirstController的test方法");
  4. return "index"; //指定页面要跳转的view视图路径
  5. }
直接返回视图的名称,结果:


2、返回ModelAndView对象


    
    
  1. @RequestMapping( "/index1")
  2. public ModelAndView test2() {
  3. ModelAndView modelAndView = new ModelAndView();
  4. ///modelAndView.setView(new RedirectView("index1"));
  5. modelAndView.setViewName( "index1"); //指定页面要跳转的view视图路径
  6. modelAndView.addObject( "message", "调用FirstController的test1方法"); //第二个参数:指定了要项前台传递的参数,在前台可以这样取值 ${sp_ids }
  7. return modelAndView;
  8. }
结果:

其中

modelAndView.setViewName("index1");
    
    
也可以写成:

modelAndView.setView(new RedirectView("index1"));
    
    

ModelAndView()

这个构造方法构造出来的ModelAndView
不能直接使用,应为它没有指定view,也没有绑定对应的model对象。当然,model对象不是必须的,但是view确实必须的。
用这个构造方法构造的实例主要用来在以后往其中加view设置和model对象。
给ModelAndView
实例设置view的方法有两
个:setViewName(String viewName) 和 setView(View view)。前者是使用view
name,后者是使用预先构造好的View对象。其中前者比较常用。事实上View是一个接口,而不是一个可以构造的具体类,我们只能通过其他途径来获取
View的实例。对于view
name,它既可以是jsp的名字,也可以是tiles定义的名字,取决于使用的ViewNameResolver如何理解这个view name。
如何获取View的实例以后再研究。
而对应如何给ModelAndView
实例设置model则比较复杂。有三个方法可以使用:

    
    
  1. addObject(Object modelObject)
  2. addObject(String modelName, Object modelObject)
  3. addAllObjects(Map modelMap)

二、@RequestMapping

         对于各种注解而言,排第一的当然是“@Controller”,表明某类是一个controller。“@RequestMapping”请求路径映射,如果标注在某个controller的类级别上,则表明访问此类路径下的方法都要加上其配置的路径;最常用是标注在方法上,表明哪个具体的方法来接受处理某次请求。 

@RequestMapping 参数说明


    
    
  1. value
  2. 定义处理方法的请求的 URL 地址。
  3. method
  4. 定义处理方法的 http method 类型,如 GET、POST 等。
  5. params
  6. 定义请求的 URL 中必须包含的参数。
  7. headers
  8. 定义请求中 Request Headers 必须包含的参数

2.1 拦截路径设置

(1) 方法上的拦截


    
    
  1. @Controller
  2. public class FirstController {
  3. @RequestMapping(value = "/index") //相对于根目录的路径
  4. public String test(ModelMap model) {
  5. model.addAttribute( "message", "调用FirstController的test方法");
  6. return "index"; //指定页面要跳转的view视图路径
  7. }
  8. }
表示拦截:http://localhost:8080/SpringMVCLearningChapter2 /index1


(2)类上的拦截


    
    
  1. @Controller
  2. @RequestMapping( "/user")
  3. public class SecondController {
  4. @RequestMapping(value = "/index")
  5. public String test(ModelMap model) {
  6. model.addAttribute( "message", "调用SecondController 的test方法");
  7. return "index"; //指定页面要跳转的view视图路径
  8. }
  9. @RequestMapping( "/index1")
  10. public ModelAndView test2() {
  11. ModelAndView modelAndView = new ModelAndView();
  12. ///modelAndView.setView(new RedirectView("index1"));
  13. modelAndView.setViewName( "index1"); //指定页面要跳转的view视图路径
  14. modelAndView.addObject( "message", "调用SecondController 的test1方法"); //第二个参数:指定了要项前台传递的参数,在前台可以这样取值 ${sp_ids }
  15. return modelAndView;
  16. }
  17. }
表示拦截:http://localhost:8080/SpringMVCLearningChapter2/ user/index

和http://localhost:8080/SpringMVCLearningChapter2/user/index1

即拦截:根目录/user/index根目录/user/index1


请求映射
  • 普通URL路径映射

@RequestMapping(value={"/login.do","/user/login.do"}):多个URL路径可以映射到同一个处理器的功能处理方法。

  • URL模板模式映射

@RequestMapping(value="/users/{userId}"):{xxx}占位符,请求的URL可以是"/users/123456"或"/users/abcd"。

@RequestMapping(value="/users/{userId}/login.do"):这样也是可以的,请求的URL可以是"/users/123/login.do"。

@RequestMapping(value="/users/{userId}/channel/{channelId}"):这样也是可以的,请求的URL可以是"/users/123/channel/456"。

  • Ant风格的URL路径映射

@RequestMapping(value="/users/**"):可以匹配"/users/abc/abc"。

@RequestMapping(value="/model?"):可匹配"/model1"或"/modela" ,但不匹配"/model"或"/modelaa";

@RequestMapping(value="/model*"):可匹配"/modelabc"或"/model",但不匹配"/modelabc/abc";

@RequestMapping(value="/model/*"):可匹配"/model/abc",但不匹配"/modelabc";

@RequestMapping(value="/model/**/{modelId}"):可匹配"/model/abc/abc/123”或"/model/123",

也就是Ant风格和URI模板变量风格可混用;

  • 正则表达式风格的URL路径映射

从Spring3.0开始支持正则表达式风格的URL路径映射,格式为{变量名:正则表达式}

@RequestMapping(value="/login/{userId://d+}.do"):可以匹配

"/login/123.do",但不能匹配"/login/abc.do",这样可以设计加严格的规则。

  • 组合使用是"或"的关系

如@RequestMapping(value={"/login.do","/user/login.do"})组合使用是或的关系,即"/login.do"或

"/user/login.do"请求URL路径都可以映射到@RequestMapping指定的功能处理方法。


2、param参数

如果想给一个页面设置传递的参数,可以写成如下:


    
    
  1. @Controller
  2. @RequestMapping( "/third")
  3. public class ThirdController {
  4. @RequestMapping(value = "/index",params= "name") //要求传递参数name,浏览器中输入name后,控制器会自动把参数传递给test中的name
  5. public String test(ModelMap model,String name) {
  6. model.addAttribute( "message", name);
  7. return "index";
  8. }
  9. }

这时输入http://localhost:8080/SpringMVCLearningChapter2/third/index是无法访问的:

因为它要求你一定要传递一个name参数,所以得这样写:

当然,这里也可以把需要的参数注解到方法的参数上去


    
    
  1. @RequestMapping(value = "/index") //要求传递参数name,浏览器中输入name后,控制器会自动把参数传递给test中的name
  2. public String test(ModelMap model,@RequestParam("name")String name) {
  3. model.addAttribute( "message", name);
  4. return "index";
  5. }

效果和上面和一样的。这时如果还是想访问http://localhost:8080/SpringMVCLearningChapter2/third/index,把required=false加上


    
    
  1. @RequestMapping(value = "/index")
  2. public String test(ModelMap model,@RequestParam(value="name",required=false)String name) {
  3. model.addAttribute( "message", name);
  4. return "index";
  5. }

3、method


    
    
  1. @RequestMapping(value = "/index1",method = RequestMethod.GET,params= "name")
  2. public ModelAndView test2() {
  3. ModelAndView modelAndView = new ModelAndView();
  4. ///modelAndView.setView(new RedirectView("index1"));
  5. modelAndView.setViewName( "index1"); //指定页面要跳转的view视图路径
  6. modelAndView.addObject( "message", "调用SecondController 的test1方法"); //第二个参数:指定了要项前台传递的参数,在前台可以这样取值 ${sp_ids }
  7. return modelAndView;
  8. }
表明只能通过GET来访问,或要POST,改成

method = RequestMethod.POST
    
    

4、head

@RequestMapping(headers)
headers 的作用也是用于细化映射。只有当请求的 Request Headers 中包含与 heanders 值相匹配的参数,处理方法才会被调用。
@RequestMapping(value = "/specify", headers = "accept=text/*")
public String specify(){
return "example_specify_page";
}
请求的 Request Headers 中 Accept 的值必须匹配 text/* ( 如 text/html ),方法才会被调用。


三、其它常用注解

handler method 参数绑定常用的注解,我们根据他们处理的Request的不同内容部分分为四类:(主要讲解常用类型)

A、处理requet uri 部分(这里指uri template中variable,不含queryString部分)的注解:   @PathVariable;

B、处理request header部分的注解:   @RequestHeader, @CookieValue;

C、处理request body部分的注解:@RequestParam,  @RequestBody;

D、处理attribute类型是注解: @SessionAttributes, @ModelAttribute;

1、 @PathVariable 

当使用@RequestMapping URI template 样式映射时, 即 /fourth/{num}, 这时的num可通过 @Pathvariable注解绑定它传过来的值到方法的参数上。

示例代码:


    
    
  1. @Controller
  2. @RequestMapping( "/fourth/{num}")
  3. public class FourthController {
  4. @RequestMapping(value = "/index/{string}")
  5. public String test(ModelMap model,@PathVariable("num") int num,@PathVariable("string") String string) {
  6. model.addAttribute( "message", "num="+String.valueOf(num)+ " string="+string);
  7. return "index";
  8. }
  9. }
浏览器输入:http://localhost:8080/SpringMVCLearningChapter2/fourth/1234/index/linbingwen


上面代码把URI template 中变量num的值和string的值,绑定到方法的参数上。若方法参数名称和需要绑定的uri template中变量名称不一致,需要在@PathVariable("num")指定uri template中的名称。

2、 @RequestHeader、@CookieValue

@RequestHeader 注解,可以把Request请求header部分的值绑定到方法的参数上。


    
    
  1. @RequestMapping(value = "six/index4")
  2. public String getHello(@RequestHeader ("host") String hostName,
  3. @RequestHeader ("Accept") String acceptType,
  4. @RequestHeader ("Accept-Language") String acceptLang,
  5. @RequestHeader ("Accept-Encoding") String acceptEnc,
  6. @RequestHeader ("Cookie") String cookie,
  7. @RequestHeader ("User-Agent") String userAgent)
  8. {
  9. System.out.println( "Host : " + hostName);
  10. System.out.println( "Accept : " + acceptType);
  11. System.out.println( "Accept Language : " + acceptLang);
  12. System.out.println( "Accept Encoding : " + acceptEnc);
  13. System.out.println( "Cookie : " + cookie);
  14. System.out.println( "User-Agent : " + userAgent);
  15. return "index4";
  16. }
运行后输入:http://localhost:8080/SpringMVCLearningChapter2/six/index4

运行结果:


注:@RequestHeader 与@RequestParam 一样也有3个参数,其含义与的@RequestParam 参数含义相同。

@CookieValue 可以把Request header中关于cookie的值绑定到方法的参数上。

参数绑定的代码:


    
    
  1. @RequestMapping( "six/index3")
  2. public String test3(Model model,@CookieValue(value="JSESSIONID", defaultValue="") String jsessionId) {
  3. model.addAttribute( "jsessionId", jsessionId);
  4. return "index3";
  5. }

JSP中获取:


    
    
  1. <%@ page language="java" contentType="text/html; charset=gb2312"
  2. pageEncoding= "gb2312"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
  7. <title>Insert title here </title>
  8. </head>
  9. <body>
  10. 采用String返回视图jsessionId=:${jsessionId}
  11. </body>
  12. </html>
结果:


即把JSESSIONID的值绑定到参数cookie上

注:@CookieValue 与@RequestParam 一样也有3个参数,其含义与的@RequestParam 参数含义相同

3、@RequestParam, @RequestBody

@RequestParam

A) 常用来处理简单类型的绑定,通过Request.getParameter() 获取的String可直接转换为简单类型的情况( String--> 简单类型的转换操作由ConversionService配置的转换器来完成);因为使用request.getParameter()方式获取参数,所以可以处理get 方式中queryString的值,也可以处理post方式中 body data的值;

B)用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容,提交方式GET、POST;

C) 该注解有两个属性: value、required; value用来指定要传入值的id名称,required用来指示参数是否必须绑定;

@RequestBody

该注解常用来处理Content-Type: 不是application/x-www-form-urlencoded编码的内容,例如application/json, application/xml等;

它是通过使用HandlerAdapter 配置的HttpMessageConverters来解析post data body,然后绑定到相应的bean上的。

因为配置有FormHttpMessageConverter,所以也可以用来处理 application/x-www-form-urlencoded的内容,处理完的结果放在一个MultiValueMap<String, String>里,这种情况在某些特殊需求下使用,详情查看FormHttpMessageConverter api;

示例代码:


    
    
  1. @RequestMapping(value = "/something", method = RequestMethod.PUT)
  2. public void handle(@RequestBody String body, Writer writer) throws IOException {
  3. writer.write(body);
  4. }

4、@SessionAttributes, @ModelAttribute

@SessionAttributes:

该注解用来绑定HttpSession中的attribute对象的值,便于在方法中的参数里使用。

该注解有value、types两个属性,可以通过名字和类型指定要使用的attribute 对象;

示例代码:


    
    
  1. @Controller
  2. @RequestMapping( "/editPet.do")
  3. @SessionAttributes( "pet")
  4. public class EditPetForm {
  5. // ...
  6. }

@ModelAttribute

该注解有两个用法,一个是用于方法上,一个是用于参数上;

用于方法上时:  通常用来在处理@RequestMapping之前,为请求绑定需要从后台查询的model;

用于参数上时: 用来通过名称对应,把相应名称的值绑定到注解的参数bean上;要绑定的值来源于:

A) @SessionAttributes 启用的attribute 对象上;

B) @ModelAttribute 用于方法上时指定的model对象;

C) 上述两种情况都没有时,new一个需要绑定的bean对象,然后把request中按名称对应的方式把值绑定到bean中。

用到方法上@ModelAttribute的示例代码:


    
    
  1. @ModelAttribute( "string1")
  2. public String preRun() {
  3. System.out.println( "Test Pre-Run");
  4. String string= "linbingwen";
  5. return string;
  6. }

这种方式实际的效果就是在调用@RequestMapping的方法之前,为request对象的model里put(“string1”, string);

JSP中可以这样来获取


    
    
  1. <%@ page language="java" contentType="text/html; charset=gb2312"
  2. pageEncoding= "gb2312"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
  7. <title>Insert title here </title>
  8. </head>
  9. <body>
  10. < 通过@ModelAttribute类方法传递参数:<br/>
  11. 方法一取出"{string1}":${string1} <br/>
  12. <%String string1=(String)request.getAttribute("string1");%>
  13. 方法二取出"request.getAttribute": <%=string1 %> <br/>
  14. </body>
  15. </html>

它会在每次访问网页前调用:

输入http://localhost:8080/SpringMVCLearningChapter2/six/index2,总共刷新了4次



用在参数上的@ModelAttribute示例代码:


    
    
  1. @RequestMapping(value = "six/index2") //相对于根目录的路径
  2. public String test(@ModelAttribute("str") String str) {
  3. return "index2"; //指定页面要跳转的view视图路径
  4. }
其实就是相相当于把参数传递到request中去,所以JSP中可以这样获取参数


    
    
  1. <%@ page language="java" contentType="text/html; charset=gb2312"
  2. pageEncoding= "gb2312"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
  7. <title>Insert title here </title>
  8. </head>
  9. <body>
  10. ========================================================== <br/>
  11. 通过@ModelAttribute方法上参数传递参数:
  12. <%String str=(String)request.getParameter("str");%>
  13. "request.getAttribute": <%=str%> <br/>
  14. </body>
  15. </html>
运行结果:



5、ResponseBody

用来输出响应,如


    
    
  1. @ResponseBody
  2. @RequestMapping(value= "/index/{imageld}") //相对于根目录的路径
  3. public byte[] test2( @PathVariable( "imageld") String str) {
  4. System.out.println(str);
  5. Resource resource= new ClassPathResource( "/image.jpg");
  6. byte[] data = null;
  7. try {
  8. data = FileCopyUtils.copyToByteArray(resource.getInputStream());
  9. } catch (IOException e) {
  10. e.printStackTrace();
  11. }
  12. return data; //指定页面要跳转的view视图路径
  13. }

输入:http://localhost:8080/SpringMVCLearningChapter2_1/index/imgd


四、补充讲解

问题: 在不给定注解的情况下,参数是怎样绑定的?

通过分析AnnotationMethodHandlerAdapter和RequestMappingHandlerAdapter的源代码发现,方法的参数在不给定参数的情况下:

若要绑定的对象时简单类型:  调用@RequestParam来处理的。 

若要绑定的对象时复杂类型:  调用@ModelAttribute来处理的。

这里的简单类型指java的原始类型(boolean, int 等)、原始类型对象(Boolean, Int等)、String、Date等ConversionService里可以直接String转换成目标对象的类型;

本文使用工程免费下载


 林炳文Evankaka原创作品。转自https://blog.csdn.net/Evankaka/article/details/45562951

        Spring2.5引入注解式处理器支持,通过@Controller和@RequestMapping注解定义我们的处理器类。并且提供了一组强大的注解需要通过处理器映射DefaultAnnotationHandlerMapping和处理器适配器AnnotationMethodHandlerAdapter来开启支持@Controller和@RequestMapping注解的处理器。


@Controller:用于标识是处理器类;

@RequestMapping:请求到处理器功能方法的映射规则;

@RequestParam:请求参数到处理器功能处理方法的方法参数上的绑定;

@ModelAttribute:请求参数到命令对象的绑定;

@InitBinder:自定义数据绑定注册支持,用于将请求参数转换到命令对象属性的对应类型;

本文使用工程免费下载

一、视图返回

1、返回String对象


  
  
  1. @RequestMapping(value = "/index") //相对于根目录的路径
  2. public String test(ModelMap model) {
  3. model.addAttribute( "message", "调用FirstController的test方法");
  4. return "index"; //指定页面要跳转的view视图路径
  5. }
直接返回视图的名称,结果:


2、返回ModelAndView对象


  
  
  1. @RequestMapping( "/index1")
  2. public ModelAndView test2() {
  3. ModelAndView modelAndView = new ModelAndView();
  4. ///modelAndView.setView(new RedirectView("index1"));
  5. modelAndView.setViewName( "index1"); //指定页面要跳转的view视图路径
  6. modelAndView.addObject( "message", "调用FirstController的test1方法"); //第二个参数:指定了要项前台传递的参数,在前台可以这样取值 ${sp_ids }
  7. return modelAndView;
  8. }
结果:

其中

modelAndView.setViewName("index1");
  
  
也可以写成:

modelAndView.setView(new RedirectView("index1"));
  
  

ModelAndView()

这个构造方法构造出来的ModelAndView
不能直接使用,应为它没有指定view,也没有绑定对应的model对象。当然,model对象不是必须的,但是view确实必须的。
用这个构造方法构造的实例主要用来在以后往其中加view设置和model对象。
给ModelAndView
实例设置view的方法有两
个:setViewName(String viewName) 和 setView(View view)。前者是使用view
name,后者是使用预先构造好的View对象。其中前者比较常用。事实上View是一个接口,而不是一个可以构造的具体类,我们只能通过其他途径来获取
View的实例。对于view
name,它既可以是jsp的名字,也可以是tiles定义的名字,取决于使用的ViewNameResolver如何理解这个view name。
如何获取View的实例以后再研究。
而对应如何给ModelAndView
实例设置model则比较复杂。有三个方法可以使用:

  
  
  1. addObject(Object modelObject)
  2. addObject(String modelName, Object modelObject)
  3. addAllObjects(Map modelMap)

二、@RequestMapping

         对于各种注解而言,排第一的当然是“@Controller”,表明某类是一个controller。“@RequestMapping”请求路径映射,如果标注在某个controller的类级别上,则表明访问此类路径下的方法都要加上其配置的路径;最常用是标注在方法上,表明哪个具体的方法来接受处理某次请求。 

@RequestMapping 参数说明


  
  
  1. value
  2. 定义处理方法的请求的 URL 地址。
  3. method
  4. 定义处理方法的 http method 类型,如 GET、POST 等。
  5. params
  6. 定义请求的 URL 中必须包含的参数。
  7. headers
  8. 定义请求中 Request Headers 必须包含的参数

2.1 拦截路径设置

(1) 方法上的拦截


  
  
  1. @Controller
  2. public class FirstController {
  3. @RequestMapping(value = "/index") //相对于根目录的路径
  4. public String test(ModelMap model) {
  5. model.addAttribute( "message", "调用FirstController的test方法");
  6. return "index"; //指定页面要跳转的view视图路径
  7. }
  8. }
表示拦截:http://localhost:8080/SpringMVCLearningChapter2 /index1


(2)类上的拦截


  
  
  1. @Controller
  2. @RequestMapping( "/user")
  3. public class SecondController {
  4. @RequestMapping(value = "/index")
  5. public String test(ModelMap model) {
  6. model.addAttribute( "message", "调用SecondController 的test方法");
  7. return "index"; //指定页面要跳转的view视图路径
  8. }
  9. @RequestMapping( "/index1")
  10. public ModelAndView test2() {
  11. ModelAndView modelAndView = new ModelAndView();
  12. ///modelAndView.setView(new RedirectView("index1"));
  13. modelAndView.setViewName( "index1"); //指定页面要跳转的view视图路径
  14. modelAndView.addObject( "message", "调用SecondController 的test1方法"); //第二个参数:指定了要项前台传递的参数,在前台可以这样取值 ${sp_ids }
  15. return modelAndView;
  16. }
  17. }
表示拦截:http://localhost:8080/SpringMVCLearningChapter2/ user/index

和http://localhost:8080/SpringMVCLearningChapter2/user/index1

即拦截:根目录/user/index根目录/user/index1


请求映射
  • 普通URL路径映射

@RequestMapping(value={"/login.do","/user/login.do"}):多个URL路径可以映射到同一个处理器的功能处理方法。

  • URL模板模式映射

@RequestMapping(value="/users/{userId}"):{xxx}占位符,请求的URL可以是"/users/123456"或"/users/abcd"。

@RequestMapping(value="/users/{userId}/login.do"):这样也是可以的,请求的URL可以是"/users/123/login.do"。

@RequestMapping(value="/users/{userId}/channel/{channelId}"):这样也是可以的,请求的URL可以是"/users/123/channel/456"。

  • Ant风格的URL路径映射

@RequestMapping(value="/users/**"):可以匹配"/users/abc/abc"。

@RequestMapping(value="/model?"):可匹配"/model1"或"/modela" ,但不匹配"/model"或"/modelaa";

@RequestMapping(value="/model*"):可匹配"/modelabc"或"/model",但不匹配"/modelabc/abc";

@RequestMapping(value="/model/*"):可匹配"/model/abc",但不匹配"/modelabc";

@RequestMapping(value="/model/**/{modelId}"):可匹配"/model/abc/abc/123”或"/model/123",

也就是Ant风格和URI模板变量风格可混用;

  • 正则表达式风格的URL路径映射

从Spring3.0开始支持正则表达式风格的URL路径映射,格式为{变量名:正则表达式}

@RequestMapping(value="/login/{userId://d+}.do"):可以匹配

"/login/123.do",但不能匹配"/login/abc.do",这样可以设计加严格的规则。

  • 组合使用是"或"的关系

如@RequestMapping(value={"/login.do","/user/login.do"})组合使用是或的关系,即"/login.do"或

"/user/login.do"请求URL路径都可以映射到@RequestMapping指定的功能处理方法。


2、param参数

如果想给一个页面设置传递的参数,可以写成如下:


  
  
  1. @Controller
  2. @RequestMapping( "/third")
  3. public class ThirdController {
  4. @RequestMapping(value = "/index",params= "name") //要求传递参数name,浏览器中输入name后,控制器会自动把参数传递给test中的name
  5. public String test(ModelMap model,String name) {
  6. model.addAttribute( "message", name);
  7. return "index";
  8. }
  9. }

这时输入http://localhost:8080/SpringMVCLearningChapter2/third/index是无法访问的:

因为它要求你一定要传递一个name参数,所以得这样写:

当然,这里也可以把需要的参数注解到方法的参数上去


  
  
  1. @RequestMapping(value = "/index") //要求传递参数name,浏览器中输入name后,控制器会自动把参数传递给test中的name
  2. public String test(ModelMap model,@RequestParam("name")String name) {
  3. model.addAttribute( "message", name);
  4. return "index";
  5. }

效果和上面和一样的。这时如果还是想访问http://localhost:8080/SpringMVCLearningChapter2/third/index,把required=false加上


  
  
  1. @RequestMapping(value = "/index")
  2. public String test(ModelMap model,@RequestParam(value="name",required=false)String name) {
  3. model.addAttribute( "message", name);
  4. return "index";
  5. }

3、method


  
  
  1. @RequestMapping(value = "/index1",method = RequestMethod.GET,params= "name")
  2. public ModelAndView test2() {
  3. ModelAndView modelAndView = new ModelAndView();
  4. ///modelAndView.setView(new RedirectView("index1"));
  5. modelAndView.setViewName( "index1"); //指定页面要跳转的view视图路径
  6. modelAndView.addObject( "message", "调用SecondController 的test1方法"); //第二个参数:指定了要项前台传递的参数,在前台可以这样取值 ${sp_ids }
  7. return modelAndView;
  8. }
表明只能通过GET来访问,或要POST,改成

method = RequestMethod.POST
  
  

4、head

@RequestMapping(headers)
headers 的作用也是用于细化映射。只有当请求的 Request Headers 中包含与 heanders 值相匹配的参数,处理方法才会被调用。
@RequestMapping(value = "/specify", headers = "accept=text/*")
public String specify(){
return "example_specify_page";
}
请求的 Request Headers 中 Accept 的值必须匹配 text/* ( 如 text/html ),方法才会被调用。


三、其它常用注解

handler method 参数绑定常用的注解,我们根据他们处理的Request的不同内容部分分为四类:(主要讲解常用类型)

A、处理requet uri 部分(这里指uri template中variable,不含queryString部分)的注解:   @PathVariable;

B、处理request header部分的注解:   @RequestHeader, @CookieValue;

C、处理request body部分的注解:@RequestParam,  @RequestBody;

D、处理attribute类型是注解: @SessionAttributes, @ModelAttribute;

1、 @PathVariable 

当使用@RequestMapping URI template 样式映射时, 即 /fourth/{num}, 这时的num可通过 @Pathvariable注解绑定它传过来的值到方法的参数上。

示例代码:


  
  
  1. @Controller
  2. @RequestMapping( "/fourth/{num}")
  3. public class FourthController {
  4. @RequestMapping(value = "/index/{string}")
  5. public String test(ModelMap model,@PathVariable("num") int num,@PathVariable("string") String string) {
  6. model.addAttribute( "message", "num="+String.valueOf(num)+ " string="+string);
  7. return "index";
  8. }
  9. }
浏览器输入:http://localhost:8080/SpringMVCLearningChapter2/fourth/1234/index/linbingwen


上面代码把URI template 中变量num的值和string的值,绑定到方法的参数上。若方法参数名称和需要绑定的uri template中变量名称不一致,需要在@PathVariable("num")指定uri template中的名称。

2、 @RequestHeader、@CookieValue

@RequestHeader 注解,可以把Request请求header部分的值绑定到方法的参数上。


  
  
  1. @RequestMapping(value = "six/index4")
  2. public String getHello(@RequestHeader ("host") String hostName,
  3. @RequestHeader ("Accept") String acceptType,
  4. @RequestHeader ("Accept-Language") String acceptLang,
  5. @RequestHeader ("Accept-Encoding") String acceptEnc,
  6. @RequestHeader ("Cookie") String cookie,
  7. @RequestHeader ("User-Agent") String userAgent)
  8. {
  9. System.out.println( "Host : " + hostName);
  10. System.out.println( "Accept : " + acceptType);
  11. System.out.println( "Accept Language : " + acceptLang);
  12. System.out.println( "Accept Encoding : " + acceptEnc);
  13. System.out.println( "Cookie : " + cookie);
  14. System.out.println( "User-Agent : " + userAgent);
  15. return "index4";
  16. }
运行后输入:http://localhost:8080/SpringMVCLearningChapter2/six/index4

运行结果:


注:@RequestHeader 与@RequestParam 一样也有3个参数,其含义与的@RequestParam 参数含义相同。

@CookieValue 可以把Request header中关于cookie的值绑定到方法的参数上。

参数绑定的代码:


  
  
  1. @RequestMapping( "six/index3")
  2. public String test3(Model model,@CookieValue(value="JSESSIONID", defaultValue="") String jsessionId) {
  3. model.addAttribute( "jsessionId", jsessionId);
  4. return "index3";
  5. }

JSP中获取:


  
  
  1. <%@ page language="java" contentType="text/html; charset=gb2312"
  2. pageEncoding= "gb2312"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
  7. <title>Insert title here </title>
  8. </head>
  9. <body>
  10. 采用String返回视图jsessionId=:${jsessionId}
  11. </body>
  12. </html>
结果:


即把JSESSIONID的值绑定到参数cookie上

注:@CookieValue 与@RequestParam 一样也有3个参数,其含义与的@RequestParam 参数含义相同

3、@RequestParam, @RequestBody

@RequestParam

A) 常用来处理简单类型的绑定,通过Request.getParameter() 获取的String可直接转换为简单类型的情况( String--> 简单类型的转换操作由ConversionService配置的转换器来完成);因为使用request.getParameter()方式获取参数,所以可以处理get 方式中queryString的值,也可以处理post方式中 body data的值;

B)用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容,提交方式GET、POST;

C) 该注解有两个属性: value、required; value用来指定要传入值的id名称,required用来指示参数是否必须绑定;

@RequestBody

该注解常用来处理Content-Type: 不是application/x-www-form-urlencoded编码的内容,例如application/json, application/xml等;

它是通过使用HandlerAdapter 配置的HttpMessageConverters来解析post data body,然后绑定到相应的bean上的。

因为配置有FormHttpMessageConverter,所以也可以用来处理 application/x-www-form-urlencoded的内容,处理完的结果放在一个MultiValueMap<String, String>里,这种情况在某些特殊需求下使用,详情查看FormHttpMessageConverter api;

示例代码:


  
  
  1. @RequestMapping(value = "/something", method = RequestMethod.PUT)
  2. public void handle(@RequestBody String body, Writer writer) throws IOException {
  3. writer.write(body);
  4. }

4、@SessionAttributes, @ModelAttribute

@SessionAttributes:

该注解用来绑定HttpSession中的attribute对象的值,便于在方法中的参数里使用。

该注解有value、types两个属性,可以通过名字和类型指定要使用的attribute 对象;

示例代码:


  
  
  1. @Controller
  2. @RequestMapping( "/editPet.do")
  3. @SessionAttributes( "pet")
  4. public class EditPetForm {
  5. // ...
  6. }

@ModelAttribute

该注解有两个用法,一个是用于方法上,一个是用于参数上;

用于方法上时:  通常用来在处理@RequestMapping之前,为请求绑定需要从后台查询的model;

用于参数上时: 用来通过名称对应,把相应名称的值绑定到注解的参数bean上;要绑定的值来源于:

A) @SessionAttributes 启用的attribute 对象上;

B) @ModelAttribute 用于方法上时指定的model对象;

C) 上述两种情况都没有时,new一个需要绑定的bean对象,然后把request中按名称对应的方式把值绑定到bean中。

用到方法上@ModelAttribute的示例代码:


  
  
  1. @ModelAttribute( "string1")
  2. public String preRun() {
  3. System.out.println( "Test Pre-Run");
  4. String string= "linbingwen";
  5. return string;
  6. }

这种方式实际的效果就是在调用@RequestMapping的方法之前,为request对象的model里put(“string1”, string);

JSP中可以这样来获取


  
  
  1. <%@ page language="java" contentType="text/html; charset=gb2312"
  2. pageEncoding= "gb2312"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
  7. <title>Insert title here </title>
  8. </head>
  9. <body>
  10. < 通过@ModelAttribute类方法传递参数:<br/>
  11. 方法一取出"{string1}":${string1} <br/>
  12. <%String string1=(String)request.getAttribute("string1");%>
  13. 方法二取出"request.getAttribute": <%=string1 %> <br/>
  14. </body>
  15. </html>

它会在每次访问网页前调用:

输入http://localhost:8080/SpringMVCLearningChapter2/six/index2,总共刷新了4次



用在参数上的@ModelAttribute示例代码:


  
  
  1. @RequestMapping(value = "six/index2") //相对于根目录的路径
  2. public String test(@ModelAttribute("str") String str) {
  3. return "index2"; //指定页面要跳转的view视图路径
  4. }
其实就是相相当于把参数传递到request中去,所以JSP中可以这样获取参数


  
  
  1. <%@ page language="java" contentType="text/html; charset=gb2312"
  2. pageEncoding= "gb2312"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
  7. <title>Insert title here </title>
  8. </head>
  9. <body>
  10. ========================================================== <br/>
  11. 通过@ModelAttribute方法上参数传递参数:
  12. <%String str=(String)request.getParameter("str");%>
  13. "request.getAttribute": <%=str%> <br/>
  14. </body>
  15. </html>
运行结果:



5、ResponseBody

用来输出响应,如


  
  
  1. @ResponseBody
  2. @RequestMapping(value= "/index/{imageld}") //相对于根目录的路径
  3. public byte[] test2( @PathVariable( "imageld") String str) {
  4. System.out.println(str);
  5. Resource resource= new ClassPathResource( "/image.jpg");
  6. byte[] data = null;
  7. try {
  8. data = FileCopyUtils.copyToByteArray(resource.getInputStream());
  9. } catch (IOException e) {
  10. e.printStackTrace();
  11. }
  12. return data; //指定页面要跳转的view视图路径
  13. }

输入:http://localhost:8080/SpringMVCLearningChapter2_1/index/imgd


四、补充讲解

问题: 在不给定注解的情况下,参数是怎样绑定的?

通过分析AnnotationMethodHandlerAdapter和RequestMappingHandlerAdapter的源代码发现,方法的参数在不给定参数的情况下:

若要绑定的对象时简单类型:  调用@RequestParam来处理的。 

若要绑定的对象时复杂类型:  调用@ModelAttribute来处理的。

这里的简单类型指java的原始类型(boolean, int 等)、原始类型对象(Boolean, Int等)、String、Date等ConversionService里可以直接String转换成目标对象的类型;

本文使用工程免费下载


猜你喜欢

转载自blog.csdn.net/weixin_42581112/article/details/88915390