为什么80%的码农都做不了架构师?>>>   

一、@RequestMapping 简介

在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,相当于Servlet中在web.xml中配置

<servlet><servlet-name>servletName</servlet-name><servlet-class>ServletClass</servlet-class>
</servlet>
<servlet-mapping><servlet-name>servletName</servlet-name><url-pattern>url</url-pattern>
</servlet-mapping>

的映射作用一致。让我们先看一下RequestMapping注解类的源码:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {String name() default "";String[] value() default {};String[] path() default {};RequestMethod[] method() default {};String[] params() default {};String[] headers() default {};String[] consumes() default {};String[] produces() default {};
}

1)在@Target中有两个属性,分别为 ElementType.METHOD 和 ElementType.TYPE ,也就是说 @RequestMapping 可以在方法和类的声明中使用

2)可以看到注解中的属性除了 name() 返回的字符串,其它的方法均返回数组,也就是可以定义多个属性值,例如 value() 和 path() 都可以同时定义多个字符串值来接收多个URL请求

二、准备工作:(注:后面的示例都将基于准备工作)

1)新建一个 Web 工程,取名为 SpringMVC

2)新建一个的控制器类:UserController

package cn.kolbe.spring.mvc.controller;import org.springframework.stereotype.Controller;@Controller
public class UserController {public String login() {return "success";}
}

3)新建和配置 web.xml 以及 spring-mvc.xml 文件

略(具体参见 前一章:‍Spring MVC 学习笔记(一):HelloWorld‍)

4)新建一个测试的 JSP 页面 index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Spring MVC</title>
</head>
<body><p> <a href="#">User Login</a>
</body>
</html>

5)新建一个成功跳转的页面 JSP 页面 welcome.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Spring MVC</title>
</head>
<body><h1>Welcome</h1></body>
</html>

三、测试 @RequestMapping 中的 value 和 path 属性(这两个属性作用相同,可以互换,如果仅有这一个属性,则可以省略,下面两个例子均采用省略的方式)

1)将 @RequestMapping 注解在 login 方法上,而UserController上不添加 @RequestMapping 注解,这时的请求 URL 是相对于 Web 根目录

@Controller
public class UserController {@RequestMapping("/login")public String login() {return "success";}
}

这时的方法 login() 能处理的 URL 请求路径是基于 Web 应用的,也就是 http://localhost/SpringMVC/login,也就是 index.jsp 页面中的 User Login 链接地址应该是:

<a href="login">User Login</a>

2)将 @RequestMapping 注解在 UserController 类上,这时类的注解是相对于 Web 根目录,而方法上的是相对于类上的路径

@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping("/login")public String login() {return "success";}
}

这时的方法login()能处理的 URL 请求路径则是 http://localhost/SpringMVC/user/login,也就是 index.jsp 页面中的 User Login 链接地址应该是:

<a href="user/login">User Login</a>

四、测试 @RequestMapping 的 method 属性

1)简介:@RequestMapping 中的 method 主要用来定义接收浏览器发来的何种请求。在Spring中,使用枚举类

org.springframework.web.bind.annotation.RequestMethod来定义浏览器请求的方式。

Http规范定义了多种请求资源的方式,最基本的有四种,分别为:GET(查)、POST(增)、PUT(改)、DELETE(删),而URL则用于定位网络上的资源相当于地址的作用,配合四种请求方式,可以实现对URL对应的资源的增删改查操作。

在实际应用中,很多人并没有按照这个规范做,因为使用GET/POST同样可以完成PUT和DELETE操作,甚至GET也可以完成POST操作,因为GET不需要用到表单,而POST却需要通过表单来发送。

2)通过 @RequestMapping(value="/login",method=RequestMethod.GET) 来指定 login()方法 仅处理通过 GET 方式发来的请求

@Controller
@RequestMapping(path = "/user")
public class UserController {@RequestMapping(path = "/login", method=RequestMethod.GET)public String login() {return "success";}
}

这时,如果浏览器发来的请求不是GET的话,将收到浏览器返回的错误提示,也就是得通过链接的方式而不是表单的方式:

<a href="user/login>User Login</a>

3)通过 @RequestMapping(value="/login",method=RequestMethod.POST) 来指定 login()方法 仅处理通过 POST 方式发来的请求

@Controller
@RequestMapping(path = "/user")
public class UserController {@RequestMapping(path = "/login", method=RequestMethod.POST)public String login() {return "success";}
}

这时,必须通过表单的方式发送请求,否则将收到浏览器返回的错误提示

<form action="user/login" method="post"><input type="submit" value="使用Post发送请求"/>
</form>

4)由于在 RequestMapping 注解类中 method() 方法返回的是 RequestMethod 数组,所以可以给 method 同时指定多个请求方式,例如:

@Controller
@RequestMapping(path = "/user")
public class UserController {// 该方法将同时接收通过GET和POST方式发来的请求@RequestMapping(path = "/login", method={RequestMethod.POST,RequestMethod.GET})public String login() {return "success";}
}

五、测试 @RequestMapping 的 params 属性,该属性表示请求参数,也就是追加在URL上的键值对,多个请求参数以&隔开,例如:

http://localhost/SpringMVC/user/login?username=kolbe&password=123456

则这个请求的参数为username=kolbe以及password=123456,@RequestMapping 中可以使用 params 来限制请求参数,来实现进一步的过滤请求,举个例子:

@Controller
@RequestMapping(path = "/user")
public class UserController {// 该方法将接收 /user/login 发来的请求,且请求参数必须为 username=kolbe&password=123456@RequestMapping(path = "/login", params={"username=kolbe","password=123456"})public String login() {return "success";}
}

该例中则表示 UserController 中的 login() 方法仅处理 /user/login 发来的请求,且必须带有 username=kolbe&password=123456 的请求参数,否则浏览器将返回HTTP 404的错误, 对应 index.jsp 中的键接地址为:

<a href="user/login?username=kolbe&password=123456">User Login</a>

六、测试 @RequestMapping 的 headers 属性,该属性表示请求头

用于HTTP协义交互的信息被称为HTTP报文,客户端发送的HTTP报文被称为请求报文,服务器发回给客户端的HTTP报文称为响应报文,报文由报文头部和报文体组成。

请求头部(Request Headers):请求头包含许多有关客户端环境和请求正文的信息,例如浏览器支持的语言、请求的服务器地址、客户端的操作系统等。

响应头部(Rsponse Headers):响应头也包含许多有用的信息,包括服务器类型、日期、响应内容的类型及编码,响应内容的长度等等。

如果你安装的是Chrome浏览器,可以通过在网页中  右击鼠标---->审查元素---->Network---->Name中点击网页---->右侧查看Headers即可,如果Name中没有出现网页,可以刷新一下即可,下边是我电脑中的一个请求头部示例:

Request HeadersAccept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Accept-Encoding:gzip, deflate, sdchAccept-Language:zh-CN,zh;q=0.8Cache-Control:max-age=0Connection:keep-aliveCookie:JSESSIONID=210075B5E521CWE3CDE938076295A57AHost:localhost:8080Upgrade-Insecure-Requests:1User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93

回规正题,通过 @RequestMapping 中的 headers 属性,可以限制客户端发来的请求

@Controller
@RequestMapping(path = "/user")
public class UserController {// 表示只接收本机发来的请求@RequestMapping(path = "/login", headers="Host=localhost:8080")public String login() {return "success";}
}

七、带占位符的URL

(一)带占位符的URL是Spring 3.0 新增的功能,可以通过 @PathVariable 将 URL 中的占位符绑定到控制器的处理方法的参数中,占位符使用{}括起来

(二)使用方法:

1)带占位符的URL示例:

@Controller
@RequestMapping(path = "/user")
public class UserController {@RequestMapping(value="/{id}", method=RequestMethod.GET)public String show(@PathVariable("id") Integer id) {return "success";}
}

在这个控制器中 show() 方法将可以接收 user/1、user/2、user/3等等的路径请求,请求的方法必须为GET,使用 @PathVariable 为应用实现 REST 规范提供了具大的便利条件。

八、采用 REST 风格的 URL 请求

1)简介:REST(Representational State Transfer):(资源)表现层状态转化,它是目前最流行的一种软件架构,其结构清晰、易于理解、扩展方便且符合标准,正在越来越多的被实践到应用中。

2)REST 风格的 URL 请求

 请求路径        请求方法           作用
-/user/1        HTTP GET        得到id为1的user
-/user/1        HTTP DELETE     删除id为1的user
-/user/1        HTTP PUT        更新id为1的user
-/user          HTTP POST       新增user

3)由于浏览器表单只支持 GET 和 POST 请求,为了实现 DELETE 和 PUT 请求,Spring 为我们提供了一个过滤器org.springframework.web.filter.HiddenHttpMethodFilter,可以为我们将 GET 和 POST 请求通过过滤器转化成 DELETE 和 PUT 请求。

4)在 web.xml 中配置过滤器

<!-- 配置 org.springframework.web.filter.HiddenHttpMethodFilter 过滤器 -->
<filter><filter-name>hiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping><filter-name>hiddenHttpMethodFilter</filter-name><!-- 拦截所有请求 --><url-pattern>/*</url-pattern>
</filter-mapping>

5)由于浏览器表单无法发送 DELETE 和 PUT 请求,所以为了让 HiddenHttpMethodFilter 识别请求的方法,需要在表单中添加一个隐藏域,名字为 _method 值为 DELETE 或 POST 或PUT,修改后 index.jsp 页面代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Spring MVC</title>
</head>
<body>
<p><!-- 得到id为1的user --><a href="user/1">Test Rest GET</a><!-- 新建id为1的user --><form action="user" method="post"><input type="hidden" name="_method" value="POST"/><input type="submit" value="Test Rest POST"/></form><!-- 删除id为1的user --><form action="user/1" method="post"><input type="hidden" name="_method" value="DELETE"/><input type="submit" value="Test Rest DELETE"/></form><!-- 更新id为1的user --><form action="user/1" method="post"><input type="hidden" name="_method" value="PUT"/><input type="submit" value="Test Rest PUT"/></form></body>
</html>

6)修改后的UserController代码

package cn.kolbe.spring.mvc.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;@Controller
@RequestMapping(path = "/user")
public class UserController {@RequestMapping(value="/{id}", method=RequestMethod.GET)public String show(@PathVariable("id") Integer id) {System.out.println("查看id为:" + id + "的user");return "success";}@RequestMapping(value="/{id}", method=RequestMethod.PUT)public String update(@PathVariable("id") Integer id) {System.out.println("更新id为:" + id + "的user");return "success";}@RequestMapping(value="/{id}", method=RequestMethod.DELETE)public String destroy(@PathVariable("id") Integer id) {System.out.println("删除id为:" + id + "的user");return "success";}@RequestMapping(value="", method=RequestMethod.POST)public String create() {System.out.println("新建user");return "success";}
}

注:如果你的web项目是运行在Tomcat 8下,你会发现被过滤成DELETE和PUT请求,到达控制器后,返回时(forward)会报HTTP 405的错误提示

HTTP Status 405 - Request method 'DELETE' not supported
或
HTTP Status 405 - JSPs only permit GET POST or HEAD

有三种解决方案:

(一)将 Tomcat 8 改为 Tomcat 7,在Tomcat 7 下运行是正常的

(二)将请求转发(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. 我们需要在服务器的响应请求到达客户端前进行拦截,这也是最关键的一步,通过自定义过滤器MyHttpMethodFilter进一步包装请求,将getMethod()方法返回值改成POST或GET即可

6. 在web.xml中配置该filter,注意dispatcher结点值必须为FORWARD。由于字数超限,暂时说到这。。。

<filter-mapping><filter-name>myFilter</filter-name><url-pattern>/*</url-pattern><dispatcher>FORWARD</dispatcher>
</filter-mapping>

转载于:https://my.oschina.net/kolbe/blog/509810

Spring MVC 入门指南(二):@RequestMapping用法详解相关推荐

  1. Spring MVC中@Controller和@RequestMapping注解详解

    在<第一个Spring MVC应用>教程中创建了两个传统风格的控制器,它们是实现 Controller 接口的类.传统风格的控制器不仅需要在配置文件中部署映映射,而且只能编写一个处理方法, ...

  2. Spring Cloud Eureka 入门 (二)服务提供者详解

    2019独角兽企业重金招聘Python工程师标准>>> 摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! "优秀不是过 ...

  3. 微信小程序云开发入门(二)-数据库详解

    微信小程序云开发入门(二)-数据库详解 接上一篇:微信小程序云开发入门(一) 摘要: 因为微信小程序云数据库有点类似传统的关系型数据库,但又有所不同.所以刚入手的时候会有点困扰,经过一段时间的学习和摸 ...

  4. Unity快速入门之二 GUI Transform 详解

    Unity快速入门之一 3D基础概念.Camera.Canvas RenderMode的几种方式对比_翕翕堂 Unity快速入门之二 GUI Transform 详解_翕翕堂 Unity快速入门之三 ...

  5. requestmapping配置页面后_Spring MVC 入门指南(二):@RequestMapping用法详解

    一.@RequestMapping 简介 在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,相当于Servlet中在web.x ...

  6. [Spring mvc 深度解析(一)] 详解Servlet

    详解Servlet ​ Servlet是Server+Applet的缩写,表示一个服务器应用.通过上面的分析我们知道Servlet其实就是一套规范,我们按照这套规范写的代码就可以直接在Java的服务器 ...

  7. Spring MVC Formatter(数据格式化)详解

    Spring MVC 框架的 Formatter<T> 与 Converter<S,T> 一样,也是一个可以将一种数据类型转换成另一种数据类型的接口.不同的是,Formatte ...

  8. 【重温SSM框架系列】1 - Spring快速入门(配置文件及API详解)

    Spring快速入门 Spring是什么 Spring发展历史 Spring的优势 Spring的开发步骤 没有Spring的时候的开发步骤 使用Spring的开发步骤 Spring配置文件(appl ...

  9. Spring MVC Converter(类型转换器)详解

    Spring MVC 框架的 Converter<S,T> 是一个可以将一种数据类型转换成另一种数据类型的接口,这里 S 表示源类型,T 表示目标类型.开发者在实际应用中使用框架内置的类型 ...

最新文章

  1. 囊括三大视觉顶会,行人重识别新基准方法AGW!已被TPAMI录用
  2. 有关rsync的一些语句
  3. 关于黑客的报道里绝对不会提到的信息
  4. php自定义商品属性,php – 可变产品属性:自定义每个显示的单选按钮文本值
  5. 数据建模大数据就业挑战月薪30K
  6. 基于Java+jsp+servlet的养老院管理系统设计和实现
  7. 人工智能在fpga的具体应用_“基于FPGA的人工智能应用技术师资培训”圆满落幕!...
  8. 基于Tezos构建的DEX Dexter被曝合约存在漏洞,开发团队Nomadic Labs已重写合约
  9. mysql缓存怎么防止缓存击穿_带你搞明白什么是缓存穿透、缓存击穿、缓存雪崩...
  10. js遍历数组和遍历对象的区别
  11. 数字转中文大写= 1234= 一千二百三十四
  12. u-boot中nand相关命令使用---- ubi, ubifsls, ubifsmount, ubifsumount
  13. 教你在硬件不满足Windows 11最低硬件要求的情况下安装Windows 11(绝对有效)
  14. 编程初学者看不懂程序的几点建议
  15. 常见的爬虫error以及解决方法
  16. 【论文阅读】深度学习去雾1——论文精选
  17. Ubuntu16.04 rc.local不生效,启动过程中报“Failed to start /etc/rc.local Compatibility”错误
  18. 集成电路,微小电子元件焊接技巧
  19. lgx06:连接数据库的驱动和url
  20. Jnpf 快速开发平台框架源码 java+Netcore版本 3.3.3 3.4.1 旗舰版企业版

热门文章

  1. Google再曝偷偷收集用户隐私,安卓苹果用户全都中招
  2. 马斯克“地狱”归来,回应一切
  3. 顶会ICML特别开设“怼日”Workshop,意见不同您尽管来
  4. 国内学者新研究:中医AI登场,自动开出药方
  5. 让自定义view宽高成比例显示
  6. bugkuCTF解题记录——5、web基础$_POST
  7. php git pull
  8. SQL Server 2000 ——系统表和系统视图
  9. 《android深入探索》第四章心得
  10. java.lang.ClassCastException:android.widget.Button cannot be cast to android.widget.ImageView