SpringMVC注解使用详解

以下是工作中整理出来的SpringMVC注解的使用方式:

1.请求处理类和方法的注解:

将请求映射到控制器处理方法的工作包含一系列映射规则,这些规则是根据HTTP请求中的各种信息制定的,具体包括请求URL、请求参数、请求方法、请求头这4个方面的信息项。

@Controller:在POJO类定义处标注@Controller,再通过Spring IOC容器注入相应的类,即可使POJO成为一个能处理HTTP请求的控制器。

@RestController:为了方便开发,从Spring4.0开始引入了@RestController注解,该注解标注了@Controller和@ResponseBody。通过直接在控制器上标注@RestController,就不需要在每个@RequestMapper方法上添加@ResponseBody了。

@RequestMapper:使用@RequestMapper映射请求。@RequestMapper使用value值指定请求的URL。在类定义处指定的URL相对于Web应用的部署路径,在方法定义处指定的URL相对于类定义处指定的URL。@RequestMapper的value、method、params、headers分别对应HTTP的请求的URL、请求方法、请求参数、报文头,他们之间是”与”的关系,联合使用可让请求映射更加精确化。如下代码:

    /**
     * Created by xieyuhui on 2018/7/4.
     */
    @Controller
    @RequestMapping("/base")
    public class BaseController {

    /**
     *  url : 请求路径 select
     *  method : 请求方法 post
     *  params :  请求参数 userId
     *  headers : 请求头 content-type=text/*
     * @param userId:
     * @return
     */
    @RequestMapping(path = "/select", method = RequestMethod.POST, params = "userId", headers = "content-type=text/*")
    public String test(@RequestParam("userId") String userId) {
        //TODO
        return "";
     }
}

@RequestMapper不但支持标准的URL,还支持Ant风格和带{xxx}占位符的URL。如下表:

examplepattern
/root/*/select/root/aaa/select 、/root/bbb/select …
/root/**/select/user/select、/user/aaa/bbb/select …
/root/select??/root/selectaaa、 /root/selectbbb
/root/{id}/root/123、/root/456
/root/**/{id}/root/aaa/bbb/123、/root/aaa/456
/root/{id}/user/{path}/detail/root/123/user/aaa/detail …

@PathVariable:使用@PathVariable可以把@RequestMapper中的占位符参数绑定到控制器处理方法的入参中,类定义处@RequestMapping的URL如果使用占位符的参数,也可以绑定到处理方法的入参中。如下代码:

    @Controller
    @RequestMapping("/open/{ownerId}")
    public calss BaseController{

    /**
     *
     * @param ownerId 绑定 {ownerId}的值
     * @param petId 绑定 {petId}的值
     */
    @RequestMapping("/select/{petId}")
    public void select(@PathVariable String ownerId, @PathVariable String petId){
        //TODO
     }
} 

2.请求处理方法签名的注解

对处理方法进行签名,包括如何设置方法入参以绑定请求信息、如何定义返回值类型等

@RequestParam:在方法入参处使用@RequestParam注解指定其对应的请求参数,该注解有3个参数:

  1. value:参数名。
  2. required:是否必需,默认为true,表示请求中必需包含对应的参数名,如果不存在则抛出 400 bad request 错误
  3. defaultValue:默认参数名,在设置该参数时,自动将required设为false。不推荐使用该参数。

example如下:

    /**
     * userName和age绑定到handle()方法的 aaa和bbb参数中,并自动完成类型转换。
     * 如果不存在age请求参数,则抛出400错误。
     *
     * @param aaa
     * @param bbb
     * @return
     */
    @RequestMapping("/handle")
    public String handle(@RequestParam(value = "userName", required = false) String aaa, @RequestParam("age") int bbb) {
        //TODO
        return "";
 } 

@CookieValue:使用@CookieValue绑定请求中的Cookie值。和@RequestParam注解拥一样的参数。example如下:

    /**
     * HTTP请求中如果有name为id的 cookie,则绑定到handleCookie()方法id参数中。
     * required = false 即使没有 也不会抛出异常。
     * @param id
     * @return
     */
    @RequestMapping("/handleCookie")
    public String handleCookie(@CookieValue(value = "id", required = false) int id) {
        //TODO
        return "";
    }

@RequestHeader:使用@RequestHeader绑定请求报文头的属性值,和@RequestParam注解拥一样的参数。请求报文包含了若干个报文头属性,服务器可据此获知客户端的信息,通过@RequestHeader即可将报文头属性值绑定到处理方法的入参中。example如下:

    /**
     * HTTP请求头中的Accept-Encoding和Keep-Alive属性将被绑定到handleHeader()方法encoding和keepAlive参数
     * @param encoding
     * @param keepAlive
     * @return
     */
    @RequestMapping("/handleHeader")
    public String handleHeader(@RequestHeader(value = "Accept-Encoding") String encoding, 
    @RequestHeader(value = "Keep-Alive", required = false) long keepAlive) {
        //TODO
        return "";
    } 
基于HttpMessageConverter接口的注解:

HttpMessageConverter接口负责将请求信息转换为一个范型对象,也负责将范型对象输出作为响应信息。

SpringMVC默认装配了4个 HttpMessageConverter:

  1. StringHttpMessageConverter
  2. ByteArrayHttpMessageConverter
  3. SourceHttpMessageConverter
  4. ALLEncompassingFormHttpMessageConverter

如果需要装配其它类型的HttpMessageConverter,需要在Spring容器中配置RequestMappingHandlerAdapter,如下配置了一个MappingJackson2HttpMessageConverter:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                    <property name="supportedMediaTypes">
                        <list>
                            <value>text/plain;charset=utf-8</value>
                            <value>text/html;charset=utf-8</value>
                            <value>text/json;charset=utf-8</value>
                            <value>application/json;charset=utf-8</value>
                        </list>
                    </property>
                </bean>
            </list>
        </property>
    </bean>

SpringMVC提供了两种注解方式来使用HttpMessageConverter。

@RequestBody/@ResponseBody:可以访问请求和响应报文体的数据。

    /**
     * @RequestBody: 根据方法中body的类型匹配HttpMessageConverter。
     * 由于这里的body是String类型,所以匹配到了StringHttpMessageConverter。
     * 然后用StringHttpMessageConverter把HTTP请求体信息进行转换并将结果绑定到body参数中。
     *
     * @ResponseBody: 由于方法返回类型是byte[],所以SpringMVC匹配到了ByteArrayHttpMessageConverter。
     * ByteArrayHttpMessageConverter对返回值做处理 并返回给客户端。
     *
     * @param body
     * @return
     */
    @ResponseBody
    @RequestMapping("/handle2")
    public byte[] handle2(@RequestBody String body) {
        return body.getBytes();
 } 

HttpEntity/ResponseEntity:这两个不是以注解的形式使用的,直接作为对象类型使用。它们不但可以访问请求和响应报文体的数据,还可以访问请求和响应报文头的数据。SpringMVC根据范型类型查找对应的HttpMessageConverter。改造一下@RequestBody/@ResponseBody的示例:

    /**
     * HttpEntity<T>:范型指定入参的类型,这里范型是String类型,则匹配到了StringHttpMessageConverter。
     * <p>
     * ResponseEntity<T>:范型指定返回的类型,这里是byte[],所以SpringMVC匹配到了ByteArrayHttpMessageConverter。
     *
     * @param httpEntity
     * @return
     */
    @RequestMapping("/handle3")
    public ResponseEntity<byte[]> handle3(HttpEntity<String> httpEntity) {
        ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(httpEntity.getBody().getBytes(), HttpStatus.OK);
        return responseEntity;
    }


- 当控制器处理方法使用@RequestBody/@ResponseBody或HttpEntity/ResponseEntity时,SpringMVC才使用注册的HttpMessageConverter对请求/响应消息进行处理。
- SpringMVC首先根据请求头或响应头的Accept属性选择匹配的HttpMessageConverter,然后根据参数类型或范型类型的过滤得到匹配的HttpMessageConverter,如果找不到可用的HttpMessageConverter则报错。
- @RequestBody/@ResponseBody不需要成对出现。如果方法入参使用了@RequestBody,则SpringMVC选择匹配的HttpMessageConverter将请求消息转换并绑定到该入参数中。如果处理方法标注了@ResponseBody,则SpringMVC选择匹配的HttpMessageConverter将方法返回值转换并输出响应信息。
- HttpEntity/ResponseEntity的功能和@RequestBody/@ResponseBody的功能类似。

3.处理模型数据注解

方法逻辑处理完后,会产生模型数据,导向指定的视图。将模型数据暴露给视图是SpringMVC框架的一项重要工作。SpringMVC提供了多种途径输出模型数据。

ModelAndView:ModelAndView类型作为方法返回值,则即包含视图信息,又包含模型数据,这样SpringMVC就可以使用视图对模型数据进行渲染了。

@ModelAttribute:如果希望将方法入参对象添加到模型中,则使用该注解。该注解既可以在方法入参上使用,也可以在方法定义中使用。example如下:

/**
 * Created by xieyuhui on 2018/7/4.
 */
@Controller
@RequestMapping("/base")
public class BaseController {
    /**
     * 在访问BaseController中任何一个请求处理方法前,
     * SpringMVC先执行该方法,把"requiredString"这个字符串添加到模型中。
     *
     * @return
     */
    @ModelAttribute
    public String requiredAttribute() {
        return "requiredString";
    }

    /**
     * 先把"requiredString" 赋值给str,再根据HTTP请求参数进一步覆盖str的值。
     *
     * @param str
     * @return
     */
    @RequestMapping("/handle4")
    public String handle4(@ModelAttribute("requiredString") String str) {
        return str;
    }
} 

@SessionAttributes:该注解可以让多个请求共享某个数据模型,在控制器类中标注一个@SessionAttributes,SpringMVC会把模型数据暂存到HttpSession中。除了可以通过属性名指定需要放入会话的属性外,还可以通过模型属性的对象类型指定,也可以属性名和属性类型同时指定,二者都允许多值,放到会话的属性是二者的并集
example如下:


/**
 * Created by xieyuhui on 2018/7/5.
 */
@Controller
@RequestMapping("/root")
/**
 *@SessionAttributes: SpringMVC会自动将当前Controller类中任何方法属性名为"xxx"的模型存储到HttpSession中。
 * 此时"xxx"为会话属性。
 *
 * @SessionAttributes(value = {"aaa","bbb"}) 将名为aaa,bbb的模型属性添加到会话中
 * @SessionAttributes(types = String.class) 将模型数据中所有String类型到的模型属性添加到会话中
 * @SessionAttributes(value = {"aaa","bbb"},types = String.class)将名为aaa,bbb的模型属性和所有String类型到的模型属性添加到会话中
 */
@SessionAttributes("commonAttribute")
public class RootController {


    /**
     * 请求handle1是,SpringMVC通过@ModelAttribute将请求入参添加到模型中。
     * @param commonAttribute
     */
    @RequestMapping("/handle1")
    public void handle1(@ModelAttribute("commonAttribute") String commonAttribute) {
        //TODO
    }


    /**
     * 通过ModelMap可以访问到模型中的所有数据,这里读取到模型中的"commonAttribute"属性值。
     * @param modelMap
     * @return
     */
    @RequestMapping("/handle2")
    public String handle2(ModelMap modelMap) {
        String commonAttribute = (String) modelMap.get("commonAttribute");
        return commonAttribute;
    }
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值