• 02-SpringMVC_获得用户请求


    问题:用户的请求,是如何被后台获得的,即用户的请求信息是怎么分配给不同的处理器?后台又是如何获得用户数据的?这些问题会后面的课程中一一解答

    一、 使用@RequestMapping映射请求

    • SpringMVC使用@RequestMapping注解,为控制器指定可以处理哪些URL请求
    • DispathcherSevle截获请求后,就通过控制器上@RequestMapping提供的映射信息确定请求所对应的处理方法
    • 查看@RequestMapping源码,可以知道它可以修饰方法,也可以修饰类
        

    1、@RequestMapping修饰方法

    • 测试类

    1. @Controller
    2. public class SpringMVCTest {
    3. @RequestMapping("/testMappingMethod")
    4. public String testRequestMapping(){
    5. System.out.println("testMappingMethod");
    6. return "success";
    7. }
    8. }
    • URL
    1. <a href="testMappingMethod"></a>

    2 @RequestMapping修饰类

    •  测试类
    1. @RequestMapping("/mappingClass")
    2. @Controller
    3. public class MappingClassTest {
    4. @RequestMapping("/testMappingMethod")
    5. public String testRequestMapping(){
    6. System.out.println("testRequestMapping");
    7. return "success";
    8. }
    9. }

    • 请求的url
    1. <a href="mappingClass/testMappingMethod">testMappingClass</a>

    3 总结

    • @RequestMapping可以标注在控制器类的定义或方法定义处。
      • 类定义:提供初步的请求映射信息,相对于WEB应用的根目录
      • 方法处:提供进一步细分映射信息,相对于类定义处的URL;若类定义处未标注@RequestMapping,则方法处标注的URL相对WEB应用的根目录

    二、映射请求参数、请求方式或请求头

    • @RequestMapping除了可以使用请求Url映射请求以外,还可以使用请求方法、请求参数及请求头映射请求.对应的@RequestMapping源码如下
    1. @Target({ElementType.METHOD, ElementType.TYPE})
    2. @Retention(RetentionPolicy.RUNTIME)
    3. @Documented
    4. @Mapping
    5. public @interface RequestMapping {
    6. ...
    7. RequestMethod[] method() default {};
    8. ...
    9. String[] params() default {};
    10. String[] headers() default {};
    11. ...
    12. }
    • @RequestMapping的vaule、method、params及headers分别表请求URL、请求方法、请求参数及请求头的映射条件,他们之间是“与”的关系,联合使用多个条件可让请求映射更加精确化

    1、method的属性

    • 控制器
    1. @RequestMapping(value="/testMethod",method=RequestMethod.POST)
    2. public String testMethod(){
    3. System.out.println("testMethod");
    4. return "success";
    5. }
    • 超链接是使用get请求,所以不会成功
    1. <a href="mappingOther/testMethod">测试请求方式</a>
    • form请求
    1. <form action="mappingOther/testMethod" method="post">
    2. <input type="submit" value="提交">
    3. </form>

    2、params的属性 

    2.1 params支持简单的表达式

    • param1:表示请求必须包含名为param1的请求参数
    • !param1:表示请求不能包含名为param1的请求参数
    • param1!=value1:表示请求包含名为param1的参数,但其值不能为value1
    • {"param1=value1",param2}:请求必须包含名为param1和param2的两个请求参数,且param1的参数的值必须是value1

    2.2 测试

    • 控制器
    1. @RequestMapping(value="/testParams",params={"username","age!=10"})
    2. public String testParams(){
    3. System.out.println("testParams");
    4. return "success";
    5. }
    含义:必须包含参数username和age,且age的值不能为10
    • 请求
    1. <a href="mappingOther/testParams?username=imentor&age=10">测试参数</a>
        不能成功,因为age的值为10

    3、header

    • 获得headers的值,可以通过firebug来查看

    • 控制器中的编写如下
    1. @RequestMapping(value="/testHeaders",headers={"zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3"})
    2. public String testHeaders(){
    3. System.out.println("testHeader");
    4. return "success";
    5. }

    三、映射请求路径

    • @RequestMapping支持Ant风格的请求路径,见源码
        

    1、 Ant风格资源地址支持3种匹配符

    • ?:匹配文件名中的一个字符
    • *  :匹配文件名中的任意字符
    • ** :匹配多层路径

    2 @RequestMapping支持Ant风格的URL

     
    • /user/*/createUser   :匹配/user/aaa/createUser
    •                                     匹配/user/bbb/createUser
    • /user/**/createUser   :匹配/user/createUser
    •                                     匹配/user/aaa/bbb/createUser
    • /user/createUser??   :匹配/user/createUseraa
    •                                      匹配/user/createUserbb

    3、测试

    • 控制器
    1. @RequestMapping(value="/user/*/createUser")
    2. public String createUser(){
    3. System.out.println("createUser");
    4. return "success";
    5. }
    • 请求
    1. a href="mappingOther/user/aaa/createUser">ant风格</a>

    四、REST

    1、知识点

    •  浏览器form表单只支持GET与POST请求,而DELETE、PUT等method并不支持,spring3.0添加了一个过滤器,可以将这些请求转换为标准的http方法,使得支持GET、POST、PUT与DELETE请求,该过滤器为HiddenHttpMethodFilter。
    •  HiddenHttpMethodFilter的父类是OncePerRequestFilter,它继承了父类的doFilterInternal方法,工作原理是将jsp页面的form表单的method属性值在doFilterInternal方法中转化为标准的Http方法,即GET,、POST、 HEAD、OPTIONS、PUT、DELETE、TRACE,然后到Controller中找到对应的方法。例如,在使用注解时我们可能会在Controller中用于@RequestMapping(value = "list", method = RequestMethod.PUT),所以如果你的表单中使用的是<form method="put">,那么这个表单会被提交到标了Method="PUT"的方法中。
    • REST:Representational State Transfer.即(资源)表现层状态转化。
      • 资源(Resources):网络上的一个实体,它可以是一段文本、一张图片、一首歌曲、一种服务等。可以用一个URI指向它。第一种资源对应一个特定的URI.也就是说,URI即为每个资源的独一无二的识别符。
      • 表现层(Representation):把资源具体呈现出来的形式,叫做它的表现层。比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式。
      • 状态转化(State Transfer):每发出一个请求,就代表了客户端和服务器一次交互过程。HTTP协议,是一个无状态协议,即所有的状态都保存在服务端。因此,如果客户想要操作服务器,必须通过某种手段,让服务端发生“状态转化”。而这种转化是建立在表现之上的。具体来说,就是HTTP协议里面,四个表示操作方式的动词
        • GET:获取资源
        • POST:新建资源
        • PUT:更新资源
        • DELETE:删除资源
    • 示例
      • /order/1    HTTP GET:得到id=1的order
      • /order/1    HTTP DELETE:删除id=1的order
      • /order/1    HTTP PUT:更新id=1的order
      • /order/1    HTTP POST:新增id=1的order
    • HiddenHttpMethodFilter
      • 浏览器form表单只支持GET与POST请求,而DELETE、PUT等method并不支持
      • Spring3.0添加一个过滤器,可以将这些请求转换为标准的http方法,使其支持GET、POST、PUT与DELETE请求

    2、测试

    • 在web.xml文件中HiddenHttpMethodFilter
    1. <filter>
    2. <filter-name>hiddenHttpMethodFilter</filter-name>
    3. <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    4. </filter>
    5. <filter-mapping>
    6. <filter-name>hiddenHttpMethodFilter</filter-name>
    7. <url-pattern>/*</url-pattern>
    8. </filter-mapping>
    • 控制器
    1. @RequestMapping("/testREST")
    2. @Controller
    3. public class TestREST {
    4. @RequestMapping(value="/testRest/{id}",method=RequestMethod.GET)
    5. public String testRestGet(@PathVariable Integer id){
    6. System.out.println("testRest GET:"+id);
    7. return "success";
    8. }
    9. @RequestMapping(value="/testRest/{id}",method=RequestMethod.POST)
    10. public String testRestPost(@PathVariable Integer id){
    11. System.out.println("testRest POST:"+id);
    12. return "success";
    13. }
    14. @RequestMapping(value="/testRest/{id}",method=RequestMethod.DELETE)
    15. public String testRestDelete(@PathVariable Integer id){
    16. System.out.println("testRest Delete:"+id);
    17. return "success";
    18. }
    19. @RequestMapping(value="/testRest/{id}",method=RequestMethod.PUT)
    20. public String testRestPut(@PathVariable Integer id){
    21. System.out.println("testRest Put:"+id);
    22. return "success";
    23. }
    24. }
    • 请求
    1. <a href="testREST/testRest/1">测试Get</a>
    2. <form action="testREST/testRest/1" method="post">
    3. <input type="submit" value="测试post">
    4. </form>
    5. <form action="testREST/testRest/1" method="post">
    6. <input type="hidden" name="_method" value="DELETE">
    7. <input type="submit" value="测试DELETE">
    8. </form>
    9. <form action="testREST/testRest/1" method="post">
    10. <input type="hidden" name="_method" value="PUT">
    11. <input type="submit" value="测试PUT">
    12. </form>

    3、注意

    1. 如果用tomcat8作为服务器,在测试DELETE和Put的时候,会报405错误
            
    解决方法有三种
    • 一是将Tomcat8改为Tomcat7,在Tomcat7下运行是正常的.或者升级到tomcat 8.0.9以上版本
    • 二是将请求转发(forward)改为redirect
    • 三是自己手动写一个Filter来包装HttpRequest中的getMethod方法
    下面主要介绍一下第三种方法:也就是自己写一个Filter来包装从服务器发回来的HttpRequest请求:

        


    大致说一下流程,
     
    1. 在第1步中,客户端发送请求至服务器,这时如果发送的是POST请求且带有以_method为名的参数会被Spring的HiddenHttpMethodFilter给拦截。
     
    2. HiddenHttpMethodFilter内有一个静态内部类通过继承HttpServletRequestWrapper类并重写getMethod()方法,将该方法返回值设为_method隐藏域的值。
     
    3. HiddenHttpMethodFilter在包装好Request后,将请求发往服务器的控制器中对应的方法处理器,这时的请求变成了图中的 3、WrapperRequest by SpringFilter
     
    4. 服务器处理完请求后,产生了一个forward请求,产生相应的请求处理信息发往客户端,注意这时的request的getMethod()方法仍然是HiddenHttpMethodFilter包装过的
     
    5. 我们需要在服务器的响应请求到达客户端前进行拦截,这也是最关键的一步,通过自定义过滤器 MyMethodConvertingFilter  进一步包装请求,将getMethod()方法返回值改成POST或GET即可 
    1. public class MyMethodConvertingFilter implements Filter {
    2. @Override
    3. public void destroy() {
    4. // TODO Auto-generated method stub
    5. }
    6. @Override
    7. public void doFilter(ServletRequest request, ServletResponse response,
    8. FilterChain chain) throws IOException, ServletException {
    1. chain.doFilter(wrapRequest((HttpServletRequest) request), response);
    1. }
    2. @Override
    3. public void init(FilterConfig arg0) throws ServletException {
    4. // TODO Auto-generated method stub
    5. }
    6. private static HttpServletRequestWrapper wrapRequest(HttpServletRequest request) {
    7. return new HttpServletRequestWrapper(request) {
    8. @Override
    9. public String getMethod() {
    10. return "GET";
    11. }
    12. };
    13. }
    14. }
    6. 在web.xml中配置该filter,注意dispatcher结点值必须为FORWARD。
    1. <filter-mapping>
    2. <filter-name>myFilter</filter-name>
    3. <url-pattern>/*</url-pattern>
    4. <dispatcher>FORWARD</dispatcher>
    5. </filter-mapping>




    关注我们
        师享空间的宗旨是分享知识,传播价值。关注我们,及时获得更多信息。



    捐赠我们

        如果您对我们的成果表示认同并且觉得对你有所帮助,欢迎您对我们捐赠^_^。
           








  • 相关阅读:
    toj 2975 Encription
    poj 1797 Heavy Transportation
    toj 2971 Rotating Numbers
    zoj 2281 Way to Freedom
    toj 2483 Nasty Hacks
    toj 2972 MOVING DHAKA
    toj 2696 Collecting Beepers
    toj 2970 Hackle Number
    toj 2485 Card Tric
    js页面定位,相关几个属性
  • 原文地址:https://www.cnblogs.com/imentors/p/5009186.html
Copyright © 2020-2023  润新知