SpringMvc 注解详解

@Controller

在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示。在SpringMVC 中提供了一个非常简便的定义Controller 的方法,你无需继承特定的类或实现特定的接口,只需使用@Controller 标记一个类是Controller ,然后使用@RequestMapping 和@RequestParam 等一些注解用以定义URL 请求和Controller 方法之间的映射,这样的Controller 就能被外界访问到。此外Controller 不会直接依赖于HttpServletRequest 和HttpServletResponse 等HttpServlet 对象,它们可以通过Controller 的方法参数灵活的获取到。

@Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。单单使用@Controller 标记在一个类上还不能真正意义上的说它就是SpringMVC 的一个控制器类,因为这个时候Spring 还不认识它。那么要如何做Spring 才能认识它呢?这个时候就需要我们把这个控制器类交给Spring 来管理。

@ModelAttribute和 @SessionAttributes

代表的是:该Controller的所有方法在调用前,先执行此@ModelAttribute方法,可用于注解和方法参数中,可以把这个@ModelAttribute特性,应用在BaseController当中,所有的Controller继承BaseController,即可实现在调用Controller时,先执行@ModelAttribute方法。

 @SessionAttributes即将值放到session作用域中,写在class上面。

具体示例参见下面:使用 @ModelAttribute 和 @SessionAttributes 传递和保存数据

SpringMVC 支持使用 @ModelAttribute 和 @SessionAttributes 在不同的模型(model)和控制器之间共享数据。 @ModelAttribute 主要有两种使用方式,一种是标注在方法上,一种是标注在 Controller 方法参数上。

@ModelAttribute用法有两种 

  运用在参数上,会将客户端传递过来的参数按名称注入到指定对象中,并且会将这个对象自动加入ModelMap中,便于View层使用;

  运用在方法上,会在每一个@RequestMapping标注的方法前执行,如果有返回值,则自动将该返回值加入到ModelMap中

当 @ModelAttribute 标记在方法上的时候,该方法将在处理器方法执行之前执行,然后把返回的对象存放在 session 或模型属性中,属性名称可以使用 @ModelAttribute(“attributeName”) 在标记方法的时候指定,若未指定,则使用返回类型的类名称(首字母小写)作为属性名称。关于 @ModelAttribute 标记在方法上时对应的属性是存放在 session 中还是存放在模型中,我们来做一个实验,看下面一段代码。

@Controller
@RequestMapping ( "/myTest" )
public class MyController {

    @ModelAttribute ( "hello" )
    public String getModel() {
       System. out .println( "-------------Hello---------" );
       return "world" ;
    }

    @ModelAttribute ( "intValue" )
    public int getInteger() {
       System. out .println( "-------------intValue---------------" );
       return 10;
    }

  @RequestMapping("sayHello")
  public void sayHello(@ModelAttribute("hello") String hello, @ModelAttribute("intValue") int num, @ModelAttribute("user2") User user, Writer writer, HttpSession session, ModelMap modelMap) throws IOException {
      writer.write("Hello " + hello + " , Hello " + user.getName() + num);
      writer.write("\r");
      Object intValue = modelMap.get("intValue");
      System.out.println(intValue + "model参数展示");
      Enumeration enume = session.getAttributeNames();
      while (enume.hasMoreElements())
          writer.write(enume.nextElement() + "\r");
  }
  @ModelAttribute ( "user2" ) public User getUser(){ 
    System. out .println( "---------getUser-------------" ); return new User(3, "user2" ); 
  } 
}

当我们请求 /myTest/sayHello.do 的时候使用 @ModelAttribute 标记的方法会先执行,然后把它们返回的对象存放到模型中。最终访问到 sayHello 方法的时候,使用 @ModelAttribute 标记的方法参数都能被正确的注入值。执行结果如下所示:

 Hello world,Hello user210

值得注意的是使用  ModelMap 的get方法同样可以取到值,也证明了数据存入了model

       由执行结果我们可以看出来,此时 session 中没有包含任何属性,也就是说上面的那些对象都是存放在模型属性中,而不是存放在 session 属性中。那要如何才能存放在 session 属性中呢?这个时候我们先引入一个新的概念 @SessionAttributes ,它的用法会在讲完 @ModelAttribute 之后介绍,这里我们就先拿来用一下。我们在 MyController 类上加上 @SessionAttributes 属性标记哪些是需要存放到 session 中的。看下面的代码:

@Controller
@RequestMapping("/myTest")
@SessionAttributes(value = {"intValue", "stringValue"}, types = {User.class})
public class ModelSessionController {

    @ModelAttribute("hello")
    public String getModel() {
        System.out.println("-------------Hello---------");
        return "world";
    }

    @ModelAttribute("intValue")
    public int getInteger() {
        System.out.println("-------------intValue---------------");
        return 10;
    }

    @RequestMapping("sayHello")
    public void sayHello(@ModelAttribute("hello") String hello, @ModelAttribute("intValue") int num, @ModelAttribute("user2") User user, Writer writer, HttpSession session, ModelMap modelMap) throws IOException {
        writer.write("Hello " + hello + " , Hello " + user.getName() + num);
        writer.write("\r");
        Object intValue = modelMap.get("intValue");
        System.out.println(intValue + "model参数展示");
        Enumeration enume = session.getAttributeNames();
        while (enume.hasMoreElements())
            writer.write(enume.nextElement() + "\r");
    }

    @ModelAttribute("user2")
    public User getUser() {
        System.out.println("---------getUser-------------");
        return new User("2", "user2");
    }
}

在上面代码中我们指定了属性为 intValue 或 stringValue 或者类型为 User 的都会放到 Session中,利用上面的代码当我们访问 /myTest/sayHello.do 的时候,结果如下:

 Hello world,Hello user210

仍然没有打印出任何 session 属性,这是怎么回事呢?怎么定义了把模型中属性名为 intValue 的对象和类型为 User 的对象存到 session 中,而实际上没有加进去呢?难道我们错啦?我们当然没有错,只是在第一次访问 /myTest/sayHello.do 的时候 @SessionAttributes 定义了需要存放到 session 中的属性,而且这个模型中也有对应的属性,但是这个时候还没有加到 session 中,所以 session 中不会有任何属性,等处理器方法执行完成后 Spring 才会把模型中对应的属性添加到 session 中。所以当请求第二次的时候就会出现如下结果:

 Hello world,Hello user210

user2

intValue

stringValue

当 @ModelAttribute 标记在处理器方法参数上的时候,表示该参数的值将从模型或者 Session 中取对应名称的属性值,该名称可以通过 @ModelAttribute(“attributeName”) 来指定,若未指定,则使用参数类型的类名称(首字母小写)作为属性名称。

@RequestMapping 注解

RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

@Controller//表示表现层的对象,注入Spring的容器作用等同于 @Component==bean标签
@RequestMapping("hello")//分类作用
public class D02RequestMappingController {
    @RequestMapping("sayHello")//映射前端URL地址到当前方法中,@WebServlet
    public ModelAndView sayHello(ModelAndView modelAndView) {...}
}

RequestMapping注解有六个属性,下面我们把她分成三类进行说明(下面有相应示例)。

1、 value, method;

value:     指定请求的实际地址,指定的地址可以是URI Template 模式(后面将会说明),也可以将两个地址映射到同一个方法;

@RequestMapping(value = {"helloOne", "helloTwo"})
public ModelAndView oneAndTwo(ModelAndView modelAndView) {......

method:  指定请求的method类型, GET、POST、PUT、DELETE等;

@RequestMapping(value = "methodGet",method = RequestMethod.GET)
public ModelAndView methodGet(ModelAndView modelAndView) {...

测试非get请求会报错

2、params,headers

params: 指定request中必须包含某些参数值是,才让该方法处理。

@Controller//表示表现层的对象,注入Spring的容器作用等同于 @Component==bean标签
@RequestMapping("requestParam")//分类作用
public class D03RequestParamController {
    /**
     * 限定进入请求方法中的参数
     */
    @RequestMapping(value = "login",params = {"id1=1","id2","!id3"})
    public ModelAndView login(ModelAndView modelAndView) {.....

只有满足参数条件的请求才会执行对应的controller,比如以上的 id1必须等于1,id2必须存在,id3必须不存在

headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。

@RequestMapping (value= "testHeaders" , headers={ "host=localhost" , "Accept" })
public String testHeaders() {
   return "headers" ;
}

headers 属性的用法和功能与params 属性相似。在上面的代码中当请求/testHeaders.do 的时候只有当请求头包含Accept 信息,且请求的host 为localhost 的时候才能正确的访问到testHeaders 方法。

3、consumes,produces

consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;

produces:    指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;

@RequestMapping 标记的处理器方法支持的方法参数和返回类型

1. 支持的方法参数类型

   (1 )HttpServlet 对象,主要包括HttpServletRequest 、HttpServletResponse 和HttpSession 对象。 这些参数Spring 在调用处理器方法的时候会自动给它们赋值,所以当在处理器方法中需要使用到这些对象的时候,可以直接在方法上给定一个方法参数的申明,然后在方法体里面直接用就可以了。但是有一点需要注意的是在使用HttpSession 对象的时候,如果此时HttpSession 对象还没有建立起来的话就会有问题。

@RequestMapping("requestWried")
public void requestWried(HttpServletResponse response, HttpServletRequest request, HttpSession session){
   System.out.println(response);
   System.out.println(request);
   System.out.println(session);
}

   (2 )Spring 自己的WebRequest 对象。 使用该对象可以访问到存放在HttpServletRequest 和HttpSession 中的属性值。

@RequestMapping("WebRequest")
public void requestWried(WebRequest webRequest){
   System.out.println(webRequest);
}

   (3 )InputStream 、OutputStream 、Reader 和Writer 。 InputStream 和Reader 是针对HttpServletRequest 而言的,可以从里面取数据;OutputStream 和Writer 是针对HttpServletResponse 而言的,可以往里面写数据。

@RequestMapping("requestWried")
public void requestWried(HttpServletResponse response, HttpServletRequest request) throws IOException {
   System.out.println(response.getWriter());
   System.out.println(request.getReader());
}

   (4 )使用@PathVariable 、@RequestParam 、@CookieValue 和@RequestHeader 标记的参数。

     转到参数映射和获取详解  https://www.cnblogs.com/xiaozhang666/p/13657846.html

   (5 )使用@ModelAttribute 标记的参数。

@RequestMapping("sayHello")
public void sayHello(
    @ModelAttribute("hello") String hello,
    @ModelAttribute("intValue") int num,
    @ModelAttribute("user2") User user,
  ) throws IOException { }

   (6 )java.util.Map 、Spring 封装的Model 和ModelMap 。 这些都可以用来封装模型数据,用来给视图做展示。

@RequestMapping("modelAndView")
   public void requestWried(ModelAndView modelAndView, Model model, ModelMap modelMap) {
}

   (7 )实体类。 可以用来接收上传的参数。

   (8 )Spring 封装的MultipartFile 。 用来接收上传文件的。

  转到文件上传 转至 

   (9 )Spring 封装的Errors 和BindingResult 对象。 这两个对象参数必须紧接在需要验证的实体对象参数之后,它里面包含了实体对象的验证结果。

2. 支持的返回类型

   (1 )一个包含模型和视图的ModelAndView 对象。

   (2 )一个模型对象,这主要包括Spring 封装好的Model 和ModelMap ,以及java.util.Map ,当没有视图返回的时候视图名称将由RequestToViewNameTranslator 来决定。

   (3 )一个View 对象。这个时候如果在渲染视图的过程中模型的话就可以给处理器方法定义一个模型参数,然后在方法体里面往模型中添加值。

   (4 )一个String 字符串。这往往代表的是一个视图名称。这个时候如果需要在渲染视图的过程中需要模型的话就可以给处理器方法一个模型参数,然后在方法体里面往模型中添加值就可以了。

   (5 )返回值是void 。这种情况一般是我们直接把返回结果写到HttpServletResponse 中了,如果没有写的话,那么Spring 将会利用RequestToViewNameTranslator 来返回一个对应的视图名称。如果视图中需要模型的话,处理方法与返回字符串的情况相同。

   (6 )如果处理器方法被注解@ResponseBody 标记的话,那么处理器方法的任何返回类型都会通过HttpMessageConverters 转换之后写到HttpServletResponse 中,而不会像上面的那些情况一样当做视图或者模型来处理。

   (7 )除以上几种情况之外的其他任何返回类型都会被当做模型中的一个属性来处理,而返回的视图还是由RequestToViewNameTranslator 来决定,添加到模型中的属性名称可以在该方法上用@ModelAttribute(“attributeName”) 来定义,否则将使用返回类型的类名称的首字母小写形式来表示。使用@ModelAttribute 标记的方法会在@RequestMapping 标记的方法执行之前执行。

@ResponseBody

作用: 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。

使用时机:返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;

@RestController

加在类上,全局方法添加了 @ResponseBody

@RequestBody 作用

请求体中的json字符串转换为java中的对象(或集合)

@requestParam

@requestParam主要用于在SpringMVC后台控制层获取参数,类似一种是request.getParameter("name"),它有三个常用参数:defaultValue = "0", required = false, value = "isApp";defaultValue 表示设置默认值,required 铜过boolean设置是否是必须要传入的参数,value 值表示接受的传入的参数类型。

@PathVariable

用于将请求URL中的模板变量映射到功能处理方法的参数上

@RequestHeader

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

示例代码:

这是一个Request 的header部分:

  1. Host                    localhost:8080  
  2. Accept                  text/html,application/xhtml+xml,application/xml;q=0.9  
  3. Accept-Language         fr,en-gb;q=0.7,en;q=0.3  
  4. Accept-Encoding         gzip,deflate  
  5. Accept-Charset          ISO-8859-1,utf-8;q=0.7,*;q=0.7  
  6. Keep-Alive              300  
@RequestMapping("/displayHeaderInfo.do")  
public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding,  
                              @RequestHeader("Keep-Alive") long keepAlive)  {  
}  

上面的代码,把request header部分的 Accept-Encoding的值,绑定到参数encoding上了, Keep-Alive header的值绑定到参数keepAlive上。

@CookieValue

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

例如有如下Cookie值:

  JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84

@RequestMapping("/displayHeaderInfo.do")  
public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie)  {  
} 

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

详细的 mvc接受参数 https://www.cnblogs.com/xiaozhang666/p/13657846.html 和 返回参数跳转  https://www.cnblogs.com/xiaozhang666/p/11648104.html

此篇幅内容转载至  https://www.cnblogs.com/leskang/p/5445698.html

posted @ 2019-10-21 13:55  一半人生  阅读(393)  评论(0编辑  收藏  举报