zoukankan      html  css  js  c++  java
  • Spring MVC 请求处理方法签名

    @RequestMapping 像一个迎宾,将 HTTP 请求正确地迎接到主人的面前(负责处理该请求的方法头主人起身相迎,进而与 HTTP 请求交杯换盏、把酒言欢;最后在欢声笑语中送走 HTTP 请求(返回响应)。Spring MVC 通过分析处理方法的签名,将 HTTP 请求信息绑定到处理方法的相应入参中,然后再调用处理方法得到返回值,最后对返回值进行处理并返回响应。

    Spring MVC 对控制器处理方法签名的限制是很宽松的,用户几乎可以按自己喜欢的方式进行方法签名。在必要时对方法及方法入参标注相应的注解(如@PathVariable、@RequestParam、@RequestHeader等)即可,Spring MVC 会优雅地完成剩下的工作:将 HTTP 请求的信息绑定到相应的方法入参中,并根据方法返回值类型做出相应的后续处理。

    一般情况下,处理方法的返回值类型为 ModelAndView 或 String,前者包含模型和逻辑视图名,而后者仅代表一个逻辑视图名。下面来看几个典型的方法签名,如下代码所示。

    // ①请求参数按名称匹配的方式绑定到方法入参中,方法返回对应的字符串代表逻辑视图名
    @RequestMapping(value = "/handle1")
    public String handle1(@RequestParam("userName") String userName,
            @RequestParam("password") String password,
            @RequestParam("realName") String realName) {
        return "success";
    }
    
    // ②将Cooke值及报文头属性绑定到入参中、方法返回ModelAndView
    @RequestMapping(value = "/handle2")
    public ModelAndView handle2(@CookieValue("JSESSIONID") String sessionId,
            @RequestHeader("Accept-Language") String accpetLanguage) {
        ModelAndView mav = new ModelAndView();
        mav.setViewName("success");
        mav.addObject("user", new User());
        return mav;
    }
    
    // ③请求参数按名称匹配的方式绑定到user的属性中、方法返回对应的字符串代表逻辑视图名
    @RequestMapping(value = "/handle3")
    public String handle3(User user) {
        return "success";
    }
    
    // ④直接将HTTP请求对象传递给处理方法、方法返回对应的字符串代表逻辑视图名
    @RequestMapping(value = "/handle4")
    public String handle4(HttpServletRequest request) {
        return "success";
    }

    从上面代码中可以发现,Spring MVC 会结合方法入参类型、入参的注解、返回值的类型,按照“契约”进行相应的处理。

    1.使用 @RequestParam 绑定请求参数值

    Java 类反射对象默认不记录方法入参的名称,因此需要在方法入参处使用 @RequestParam 注解指定其对应的请求参数。@RequestParam 注解有以下3个参数。

    1)value:参数名。

    2)required:是否必需,默认为true,表示请求中必须包含对应的参数名,如果不存在则抛出异常。

    3)defaultvalue:默认参数名,在设置该参数时,自动将 required 设为 false。极少情况需要使用该参数,也不推荐使用该参数。

    下面的实例将 userName 和 age 请求参数分别绑定到 handlel11() 方法的 userName 和 age 中,并自动完成类型转换。如果不存在 age 请求参数,则将抛出异常。

    @RequestMapping(value = "/handle11")
    public String handle11(
      @RequestParam(value = "userName", required = false) String userName,
      @RequestParam("age") int age) {
      ...
    }

    2.使用 @CookieValue 绑定请求中的 Cookie 值

    使用 @CookieValue 可让处理方法入参绑定某个 Cookie 的值,它和 @RequestParam 拥有3个一样的参数。来看一个使用 @CookieValue 的实例,代码如下:

    @RequestMapping(value = "/handle12")
    public String handle12(
      @CookieValue(value = "sessionId", required = false) String sessionId,
      @RequestParam("age") int age) {
      ...
    }

    3.使用 @RequestHeader 绑定请求报文头的属性值

    请求报文包含了若干个报文头属性,服务器可据此获知客户端的信息,通过 @RequestHeader 即可将报文头属性值绑定到处理方法的入参中。

    @RequestMapping(value = "/handle13")
    public String handle13(@RequestHeader("Accept-Encoding") String encoding,
      @RequestHeader("Keep-Alive") long keepAlive) {
      ...
    }

    4.使用命令/表单对象绑定请求参数值

    所谓命令/表单对象并不需要实现任何接口,仅是一个拥有若干属性的POJO。Spring MVC 会按请求参数名和命令/表单对象属性名匹配的方式,自动为该对象填充属性值。支持级联的属性名,如 dept.deptld、dept.address.tel 等。

    @RequestMapping(value = "/handle14")
    public String handle14(User user) {
        ...
    }

    假设 User 类的结构如下图所示,则如下的 URL 请求,其请求参数将正确地填充到 User 对象中。

    /handle14.html?userName=tom&dept.deptId=1&dept.address.tel=102

    5.使用Servlet API 对象作为入参

    在 Spring MVC 中,控制器类可以不依赖任何 Servlet API 对象,但是 Spring MVC 并不能阻止我们使用 Servlet API 的类作为处理方法的入参。以下处理方法都可以正确地工作,如下面代码所示。

    @RequestMapping(value = "/handle21")
    public void handle21(HttpServletRequest request,
            HttpServletResponse response) {
        String userName = request.getParameter("userName");
        response.addCookie(new Cookie("userName", userName));
    }
    
    @RequestMapping(value = "/handle22")
    public ModelAndView handle22(HttpServletRequest request) {
        String userName = WebUtils.findParameterValue(request, "userName");
        ModelAndView mav = new ModelAndView();
        mav.setViewName("success");
        mav.addObject("userName", userName);
        return mav;
    }
    
    @RequestMapping(value = "/handle23")
    public String handle23(HttpSession session) {
        session.setAttribute("sessionId", 1234);
        return "success";
    }
    
    @RequestMapping(value = "/handle24")
    public String handle24(HttpServletRequest request,
            @RequestParam("userName") String userName) {
    
        return "success";
    }

    在使用 Servlet API 的类作为入参时,Spring MVC 会自动将 web 层对应的 Servlet 对象传递给处理方法的入参。处理方法入参可以同时使用 Servlet API 类的入参和其他符合要求的入参,它们之间的位置顺序没有特殊要求。

    值得注意的是,如果处理方法自行使用 HttpServletResponse 返回响应,则处理方法的返回值设置成 void 即可,如 handle21 所示。

    Spring MVC 在 org.springframework.web.context.request 包中定义了若干个可代理 Servlet 原生 API 类的接口,如 WebRequest 和 NativeWebRequest,它们也允许作为处理类的入参,通过这些代理类可访问请求对象的任何信息,如下:

    @RequestMapping(value = "/handle25")
    public String handle25(WebRequest request) {
        String userName = request.getParameter("userName");
        return "success";
    }

    6.使用 I/O 对象作为入参

    Servlet 的 ServletRequest 拥有 getInputStream() 和 getReader() 方法,可以通过它们读取请求的信息。相应的,Servlet 的 ServletResponse 拥有 getOutputStream() 和 getWriter() 方法,可以通过它们输出响应信息。

    Spring MVC 允许控制器的处理方法使用 java.io.InputStream/java.io.Reader 及
    java.io.OutputStream/java.io.Writer 作为方法的入参,Spring MVC 将获取 ServletRequest 的 InputStream/Reader 或 ServIetResponse 的 OutputStream/Writer,然后传递给控制器的处理方法,如下代码所示。

    @RequestMapping(value = "/handle31")
    public void handle31(OutputStream os) throws IOException {
        Resource res = new ClassPathResource("/image.jpg");
        FileCopyUtils.copy(res.getInputStream(), os);
    }

    7.其他类型的参数

    控制器处理方法的入参除支持以上类型的参数外,还支持 java.util.Locale、java.security.Principal,可以通过Servlet 的 HttpServletRequest 的 getLocale() 和 getUserPrincipal() 方法得到相应的值。如果处理方法的入参类型为 Locale 或 Principal,则 Spring MVC 自动从请求对象中获取相应的对象并传递给处理方法的入参。

  • 相关阅读:
    SpringBoot Schedule 配置
    ElasticSearch与Spring Boot集成问题
    Mybaits使用
    Java生成随机验证码
    Netty-FastThreadLocal快在哪里呢?
    直方图反向投影学习-----个人理解(你究竟是不是凶手)
    zookeeper启动报 Unexpected exception, exiting abnormally 错误
    upload三种上传方式(上)---Servlet---post---commons-fileupload.1.2.1.jar方式请求上传文件
    request.getRealPath为什么会被代替
    Java2E中的路径问题
  • 原文地址:https://www.cnblogs.com/jwen1994/p/11146591.html
Copyright © 2011-2022 走看看