zoukankan      html  css  js  c++  java
  • 第一节:SpringMVC 处理请求数据【1】

    一、请求数据传入(从页面获取数据)

      1、JavaWeb 获取请求数据

        请求数据:请求参数、cookie 信息、请求头信息......

    JavaWEB:HttpRequest、
                    Request.getParameter(参数名);Request.getParameterMap();
                    Request.getCookie();
                    Request.getHeader();    
    

      

      2、请求处理方法签名

      (1)Spring MVC 通过分析处理方法的签名(方法名+参数列表)将HTTP 请求信息绑定到处理方法的相应入参中
      (2)Spring MVC 对控制器处理方法签名的限制是很宽松的,几乎可以按喜欢的任何方式对方法进行签名;
      (3)必要时可以对方法及方法形参标注相应的注解(@PathVariable、@RequestParam、@RequestHeader 等);
      (4)Spring MVC 框架会将 HTTP 请求的信息绑定到相应的方法入参中,并根据方法的返回值类型做出相应的后续处理;

    二、@RequestParam注解

      1、用法

        使用 SpringMVC 时,可以自动把根据请求中的参数映射到入参上面,即在处理请求的方法中,加入相对应的形参,保证入参参数名和传递的数据的参数名保持一致,就可以自动赋值。

        当请求中的参数名与入参参数名不一致时,就可以在处理方法形参处使用 @RequestParam 可以把请求参数传递给请求方法

        

      2、属性

    value 参数名,当不满足赋值条件时,可以使用 value 属性,指定映射关系;
    
    required 是否必须。
        默认为 true,必须赋值,表示请求参数中必须包含对应的参数,若不存在,将抛出异常。
        若设置为 false,则不必须赋值,因此形参的值可能为 null。
    
    defaultValue 默认值,当没有传递参数时使用该值;
        若形参所获得的值为null,则设置一个默认值,(用在分页和模糊查询中)
    

      

      3、示例

        /**
          * @RequestMapping 注解用于映射请求参数
          *   value        用于映射请求参数名称
          *   required     用于设置请求参数是否必须赋值
          *   defaultValue 设置默认值,当没有传递参数时使用该值
          *
          */
        @RequestMapping(value = "/handle01")
        public String handle01(@RequestParam(value = "user", required = false, defaultValue = "Tom")String userName, String age) {
            System.out.println("handle01...");
            System.out.println("userName = " + userName);
            System.out.println("age = " + age);
            return "success";
        }

      请求链接:

    <a href="/handle01?user=abc&age=10">testRequestParam</a>
    

      

      4、细节

        (1)默认方式获取请求参数

            直接给方法入参上写一个和请求参数名相同的变量,这个变量就用来接收请求参数的值;

            如果请求中带值:就是获取的参数值;

            如果请求中没带值:获取为 null

            对于上面案例中的 age 就是这样获取方式;

        (2)@RequestParam 注解

           使用 @RequestParam 注解获取请求参数,参数默认是必须带的,如果没有会报错,可以使用 required 指定该参数是否为必须;还可以使用 defaultValue 指定参数的默认值。

           

    @RequestParam("user")String userName
    相当于
    userName = request.getParameter("user");

        (3)@RequestParam 与 @PathVariable 区别?

          @RequestParam 是获取请求参数?后面的值

          @PathVariable 是获取路径中的参数值

     /book/【{user}pathVariable】?【user=admin(requestParam)】
    

      

    三、@RequestHeader 注解

      1、用法

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

      2、属性

    value   获取的请求头,指定映射关系;
    
    required 是否必须。
        默认为 true,必须赋值,表示请求头中必须包含对应的参数,若不存在,将抛出异常。
        若设置为 false,则不必须赋值,因此值为 null。
    
    defaultValue 设置请求头默认值,当没有传递请求头时使用该值;
    

      

      3、示例

        @RequestMapping(value = "/handle02")
        public String handle02(@RequestHeader(value = "User-Agent", required = false, defaultValue = "Chrome")String userAgent) {
            System.out.println("handle02...");
            System.out.println("userAgent = " + userAgent);
            return "success";
        }

        注意:如果请求头中没有对应的值就会报错,可以使用 required 和 defaultValue 属性;

     

    四、@CookieValue 注解

      1、用法

        (1)使用 @CookieValue 绑定请求中的 cookie 值;
        (2)@CookieValue 可让处理方法形参绑定某个 cookie 值

      2、属性

    value   绑定请求中的 cookie 值,指定映射关系;
    
    required 是否必须。
        默认为 true,必须赋值,表示 cookie 中必须包含对应的参数,若不存在,将抛出异常。
        若设置为 false,则不必须赋值,因此值为 null。
    
    defaultValue 设置 cookie 默认值,当没有传递指定 cookie 时就使用该值;
    

      

      3、示例

        @RequestMapping(value = "/handle03")
        public String handle03(@CookieValue(value = "JSESSIONID", required = false, defaultValue = "sessionID")String jid) {
            System.out.println("handle03...");
            System.out.println("cookie = " + jid);
            return "success";
        }

    五、使用POJO作为参数

      1、用法

        (1)使用 POJO 对象绑定请求参数值;

        (2)Spring MVC 会按请求参数名和 POJO 属性名自动匹配,自动为该对象填充属性值,支持级联属性。如dept.deptId、dept.deptaddress.tel 等   

      2、示例

        ① 增加实体类

    public class User {
        private Integer id;
        private String username;
        private String password;
        private Integer age;
        private Address address;
    }
    
    public class Address {
        private String province;
        private String city;
        private String country;
    }

        ② 控制器方法

        @RequestMapping(value = "/handle04")
        public String handle04(User user) {
            System.out.println("handle04...");
            System.out.println("user = " + user);
            return "success";
        }

        ③ 表单页面

    <!-- 测试 POJO 对象传参,支持级联属性-->
    <form action="/handle04" method="post">
        username:<input type="text" name="username"  /><br />
        password:<input type="text" name="password"  /><br />
        age:<input type="text" name="age" /><br />
        province:<input type="text"  name="address.province" /><br />
        city:<input type="text" name="address.city"  /><br />
        country:<input type="text"  name="address.country" /><br />
        <input type="submit" value="添加" />
    </form>

        ④ 测试

        可以看到数据可以封装进来,但是存在请求的乱码问题。 

      3、提交的中文乱码

        对于提交的数据出现了乱码情况:

        请求乱码:

          方式一:修改 Tomcat 的 server.xml,在 8080 端口处添加 URIEncoding="UTF-8";

          方式二:将请求参数转码(SpringMVC中不可用)

            String user = new String(request.getParameter("user").getBytes("ISO-8859-1"), "UTF-8");

        响应乱码:

    response.setContentType("text/html;charset=utf-8"); //解决响应乱码

    六、使用Servlet原生API作为参数

      1、SpringMVC 的 Handler 方法可以接受Servlet原生 Servlet API 类型的参数:

    (1)HttpServletRequest      请求对象
    (2)HttpServletResponse     响应对象
    (3)HttpSession             会话对象
    (4)java.security.Pincipal  HTTPS安全相关
    (5)Locale                  国际化有关的区域信息对象
    (6)InputStream         获取字节输入流 request.getInputStream()
    (8)OutputStream        获取字节输出流 request.getOutputStream()
    (9)Reader            获取字符输入流 request.getReader()
    (10)Writer                  获取字符输出流 request.getWriter()
    

      

      2、示例

        控制器:

        /*
            SpringMVC 可以直接在参数上写原生API
         */
        @RequestMapping(value = "/handle05")
        public String handle05(HttpServletRequest request, HttpSession session) {
            System.out.println("handle05...");
            request.setAttribute("request", "这个是 request 域");
            session.setAttribute("session", "这个是 session 域");
            return "success";
        }

        请求链接:

    <!-- 测试 Servlet API 作为处理请求参数 -->
    <a href="handle05">testServletAPI</a>
    

      

      3、源码参考:

        源码:AnnotationMethodHandlerAdapter(L866)

             @Override
             protected Object  resolveStandardArgument(Class<?> parameterType,  NativeWebRequest webRequest) throws Exception {
                  HttpServletRequest request =  webRequest.getNativeRequest(HttpServletRequest.class);
                  HttpServletResponse response =  webRequest.getNativeResponse(HttpServletResponse.class);
                  if  (ServletRequest.class.isAssignableFrom(parameterType)  ||
                           MultipartRequest.class.isAssignableFrom(parameterType))  {
                      Object nativeRequest =  webRequest.getNativeRequest(parameterType);
                      if (nativeRequest == null) {
                           throw new IllegalStateException(
                                    "Current request is not  of type [" + parameterType.getName() + "]: " +  request);
                      }
                      return nativeRequest;
                  }
                  else if  (ServletResponse.class.isAssignableFrom(parameterType))  {
                      this.responseArgumentUsed = true;
                      Object nativeResponse =  webRequest.getNativeResponse(parameterType);
                      if (nativeResponse == null) {
                           throw new IllegalStateException(
                                    "Current response is  not of type [" + parameterType.getName() + "]: " +  response);
                      }
                      return nativeResponse;
                  }
                  else if  (HttpSession.class.isAssignableFrom(parameterType)) {
                      return request.getSession();
                  }
                  else if  (Principal.class.isAssignableFrom(parameterType)) {
                      return request.getUserPrincipal();
                  }
                  else if  (Locale.class.equals(parameterType)) {
                      return  RequestContextUtils.getLocale(request);
                  }
                  else if  (InputStream.class.isAssignableFrom(parameterType)) {
                      return request.getInputStream();
                  }
                  else if  (Reader.class.isAssignableFrom(parameterType)) {
                      return request.getReader();
                  }
                  else if  (OutputStream.class.isAssignableFrom(parameterType)) {
                      this.responseArgumentUsed = true;
                      return response.getOutputStream();
                  }
                  else if  (Writer.class.isAssignableFrom(parameterType)) {
                      this.responseArgumentUsed = true;
                      return response.getWriter();
                  }
                  return  super.resolveStandardArgument(parameterType,  webRequest);
             }

      

    八、字符编码过滤器(解决请求中文乱码)

      1、字符编码过滤器

        SpringMVC 给我们提供了一个字符编码过滤器 CharacterEncodingFilter。

        如果有中文乱码问题,需要配置字符编码过滤器,而且一定要配置其他过滤器之前,如(HiddenHttpMethodFilter),否则不起作用。

      2、在 web.xml 中配置字符编码过滤器:

        <!--  字符编码过滤器  -->
        <filter>
            <filter-name>characterEncodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <!-- 设置字符编码 -->
            <init-param>
                <param-name>encoding</param-name>
                <param-value>UTF-8</param-value>
            </init-param>
            <!-- 强制设置响应进行编码 -->
            <init-param>
                <param-name>forceEncoding</param-name>
                <param-value>true</param-value>
            </init-param>
        </filter>
    
        <filter-mapping>
            <filter-name>characterEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>  <!-- 对所有的请求都拦截,处理所有响应-->
        </filter-mapping>

      注意:字符编码过滤器一定要在配置文件其他过滤器之前,否则不起作用。

      获取在获取流或者其他处理的时候就不起作用。

      3、字符编码过滤器 CharacterEncodingFilter 源码

    public class CharacterEncodingFilter extends OncePerRequestFilter {
    
        private String encoding;
    
        private boolean forceEncoding = false;
    
        public void setEncoding(String encoding) {
            this.encoding = encoding;
        }
    
        public void setForceEncoding(boolean forceEncoding) {
            this.forceEncoding = forceEncoding;
        }
    
        @Override
        protected void doFilterInternal(
                HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {
    
            if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
                request.setCharacterEncoding(this.encoding);
                if (this.forceEncoding) {
                    response.setCharacterEncoding(this.encoding);
                }
            }
            filterChain.doFilter(request, response);
        }
    
    }
  • 相关阅读:
    C#中yield return用法
    vs生成命令和属性的宏
    开源的库RestSharp轻松消费Restful Service
    【C#】工具类-FTP操作封装类FTPHelper
    常见编码bug
    用Redis存储Tomcat集群的Session(转载)
    session转载
    pv,uv
    cookie读取设置name
    转载cookie理解
  • 原文地址:https://www.cnblogs.com/niujifei/p/15527453.html
Copyright © 2011-2022 走看看