使用@RequestMapping映射请求
SpringMVC使用@RequestMapping
注解为控制器指定可以处理哪些URL请求。
对于@RequestMapping
注解,在控制器的类定义及方法定义处都可以标注
- 类定义处:提供初步的请求映射信息,相对于WEB应用的根目录。
-
方法处:提供进一步的细分映射信息,相对于类定义处的URL。若类定义处未标注
@RequestMapping
,则方法处标记的URL相对于WEB应用的根目录。
DispatcherServlet截获请求后,就通过控制器上@RequestMapping
提供的映射信息确定请求所对应的处理方法
首先web.xml
配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
dispatcher-servlet.xml
配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 配置自动扫描的包-->
<context:component-scan base-package="com.cerr.springmvc.handlers"/>
<!-- 配置视图解析器:如何把handler方法返回值解析为实际的物理视图 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver" >
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
我们创建一个控制器类SpringMVCTest
,代码如下:
package com.cerr.springmvc.handlers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
private static final String SUCCESS = "success";
@RequestMapping("/testRequestMapping")
public String testRequestMapping(){
System.out.println("testRequestMapping");
return SUCCESS;
}
}
对于这个控制器类,我们在类定义处注解了@RequestMapping("/springmvc")
,在方法定义处注解了@RequestMapping("/testRequestMapping")
,则该方法的映射链接为:springmvc/testRequestMapping。
在index.jsp中
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="springmvc/testRequestMapping">Test</a>
</body>
</html>
映射请求参数、请求方法或请求头
@RequestMapping
除了可以使用请求URL映射请求外,还可以使用请求方法、请求参数及请求头映射请求。
@RequestMapping
的value
、method
、params
及heads
分别表示请求URL、请求方法、请求参数及请求头的映射条件,他们之间是与的关系,联合使用多个条件可以让请求映射更加精确化。
对于请求参数及请求头,params和headers支持简单的表达式:
例如:
- param1:表示请求必须包含名为param1的请求参数
- !param1:表示请求不能包含名为param1的请求参数
- param1!=value1:表示请求包含名为param1的请求参数,但是其值不能为value1
- {"param1=value1","param2"}:请求必须包含名为param1和param2两个参数,且param1参数的值必须为value1
package com.cerr.springmvc.handlers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
private static final String SUCCESS = "success";
/***
* 映射URL和请求参数
* @return
*/
@RequestMapping(value = "testParamsAndHeaders",params = {"username","age!=10"})
public String testParamsAndHeaders(){
System.out.println("testParamsAndHeaders");
return SUCCESS;
}
/**
* 映射URL和请求方法
* @return
*/
@RequestMapping(value = "/testMethod",method = RequestMethod.POST)
public String testMethod(){
System.out.println("testMethod");
return SUCCESS;
}
}
使用通配符
对于@RequestMapping
注解,还支持通配符:
-
?
:匹配文件名中的一个字符 -
*
:匹配文件名中的任意字符 -
**
:匹配多层路径
例如:@RequestMapping("/testAntPath/*/abc")
,可以匹配/springmvc/testAntPath/mmmm/abc
等等,其中的mmmm可以替换为任意的字符。
@PathVariable
通过@PathVariable
注解可以将URL中占位符参数绑定到控制器处理方法的入参中:URL中的{xxx}占位符通过@PathVariable("xxx")
绑定到操作方法的入参中,例如:
package com.cerr.springmvc.handlers;
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;
@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
private static final String SUCCESS = "success";
/***
* @PathVariable可以来映射URAL中的占位符到目标方法的参数中
* @param id
* @return
*/
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id){
System.out.println("testPathVariable "+ id);
return SUCCESS;
}
}
超链接为:
<a href="springmvc/testPathVariable/1">testPathVariable</a>
使用HiddenHttpMethodFilter来发送DELETE和PUT等请求
HTTP有四种表示操作方式的动词:
-
GET
:获取资源 -
POST
:新建资源 -
PUT
:更新资源 -
DELETE
:删除资源
在浏览器form表单中,只支持GET与POST请求,而DELETE、PUT等method并不支持,在Spring3.0添加了一个过滤器,可以将这些请求转换为标准的http方法,使得支持GET、POST、PUT与DELETE请求。
REST风格的URL的实例,以CRUD为例:
/order POST:新建一个order
/order/1 PUT:修改id=1的order
/order/1 GET:获取id=1的order
/order/1 DELETE:删除id=1的order
使用HiddenHttpMethodFilter来发送PUT请求和DELETE请求的步骤:
- 需要配置
HiddenHttpMethodFilter
<!-- 配置org.springframework.web.filter.HiddenHttpMethodFilter:可以把POST请求转为DELETE或POST请求 -->
<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>
- 需要发送POST请求
- 需要在发送POST请求时携带一个
name="_method"
的隐藏域,值为DELETE或PUT
下面我们对这四种请求分别举例子,我们编写了如下的html
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="springmvc/testRest/1" method="post">
<input type="hidden" name="_method" value="PUT">
<input type="submit" value="TestRest PUT"/>
</form>
<br><br>
<form action="springmvc/testRest/1" method="post">
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="TestRest DELETE"/>
</form>
<br><br>
<form action="springmvc/testRest" method="post">
<input type="submit" value="TestRest POST"/>
</form>
<br><br>
<a href="springmvc/testRest/1">Test Rest Get</a><br>
</body>
</html>
package com.cerr.springmvc.handlers;
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;
@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
private static final String SUCCESS = "success";
@RequestMapping(value = "/testRest/{id}",method = RequestMethod.PUT)
public String testRestPut(@PathVariable("id") Integer id){
System.out.println("testRest PUT:"+id);
return SUCCESS;
}
@RequestMapping(value = "/testRest/{id}",method = RequestMethod.DELETE)
public String testRestDelete(@PathVariable("id") Integer id){
System.out.println("testRest DELETE:"+id);
return SUCCESS;
}
@RequestMapping(value = "/testRest",method = RequestMethod.POST)
public String testRest(){
System.out.println("testRest POST");
return SUCCESS;
}
@RequestMapping(value = "/testRest/{id}",method = RequestMethod.GET)
public String testRest(@PathVariable("id") Integer id){
System.out.println("testRest GET:"+id);
return SUCCESS;
}
}
对于PUT、DELETE、GET请求,参数的传递我们可以使用上面所学的@PathVariable
注解来将占位符的值传递给方法的参数。
请求处理方法签名
SpringMVC通过分析处理方法的签名,将HTTP请求信息绑定到处理方法的响应入参中。
SpringMVC对控制器处理方法签名的限制是很宽松的,几乎可以按喜欢的任何方式对方法进行签名。
必要时可以对方法及方法入参标注相应的注解(@PathVariable、@RequestParam、@RequestHeader
等)、SpringMVC会将HTTP请求的信息绑定到相应的方法入参中,并根据方法的返回值类型作出相应的后续处理。
@RequestParam来映射请求参数
使用@RequestParam
来映射请求参数,其注解有如下方法:
-
value
值即为请求参数的参数名 -
request
可以指定该参数是否是必须传的 -
defaultValue
表示请求参数的默认值
例子:在jsp文件中通过超链接传入两个参数,在控制器类中接受并打印。
web.xml
文件配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置org.springframework.web.filter.HiddenHttpMethodFilter:可以把POST请求转为DELETE或POST请求 -->
<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>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
dispatcher-servlet.xml
配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 配置自动扫描的包-->
<context:component-scan base-package="com.cerr.springmvc.handlers"/>
<!-- 配置视图解析器:如何把handler方法返回值解析为实际的物理视图 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver" >
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="springmvc/testRequestParam?username=cerr&age=11">Test testRequestParam</a>
</body>
</html>
package com.cerr.springmvc.handlers;
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;
import org.springframework.web.bind.annotation.RequestParam;
@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
private static final String SUCCESS = "success";
@RequestMapping(value = "/testRequestParam")
public String testRequestParam(@RequestParam(value = "username") String un,
@RequestParam(value = "age",required = false) Integer age){
System.out.println("testRequestParam " + un + " " + age);
return SUCCESS;
}
}
使用@RequestHeader绑定请求报头的属性值
请求头包含了若干个属性,服务器可根据此获知客户端的信息,通过@RequestHeader即可将请求头中的属性值绑定到处理方法的入参中。
package com.cerr.springmvc.handlers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
private static final String SUCCESS = "success";
/***
* 用法同@RequestParam
* 作用:映射请求头
* @param al
* @return
*/
@RequestMapping(value = "/testReuqestHeader")
public String testReuqestHeader(@RequestHeader(value = "Accept-Language") String al){
System.out.println("testReuqestHeader,Accept-Language: "+al);
return SUCCESS;
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="springmvc/testReuqestHeader">Test testReuqestHeader</a>
</body>
</html>
@CookieValue
映射一个Cookie值,属性同@RequestParam
package com.cerr.springmvc.handlers;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
private static final String SUCCESS = "success";
@RequestMapping(value = "/testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String sessionId){
System.out.println("testCookieValue: sessionId:"+sessionId);
return SUCCESS;
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="springmvc/testCookieValue">Test testCookieValue</a>
</body>
</html>
使用POJO对象绑定请求参数值
SpringMVC会按请求参数名或POJO属性名进行自动匹配,自动为该对象填充属性值,并且支持级联属性。
如dept.deptId、dept.address.city
等。
我们定义一个User类,里面包含另一个实体类Address:
package com.cerr.springmvc.entities;
public class User {
private String username;
private String password;
private String email;
private int age;
private Address address;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
", age=" + age +
", address=" + address +
'}';
}
}
我们再定义一个实体类Address:
package com.cerr.springmvc.entities;
public class Address {
private String province;
private String city;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address{" +
"province='" + province + '\'' +
", city='" + city + '\'' +
'}';
}
}
index.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="springmvc/testPojo" method="post">
username:<input type="text" name="username" /> <br>
password:<input type="password" name="password"/><br>
email:<input type="text" name="email" /><br>
age:<input type="text" name="age" /><br>
city:<input type="text" name="address.city"/><br>
province:<input type="text" name="address.province">
<input type="submit" value="Submit">
</form>
</body>
</html>
控制器类的代码:
package com.cerr.springmvc.handlers;
import com.cerr.springmvc.entities.User;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import org.springframework.stereotype.Controller;
import org.springframework.util.concurrent.SuccessCallback;
import org.springframework.web.bind.annotation.*;
@RequestMapping("/springmvc")
@Controller
public class SpringMVCTest {
private static final String SUCCESS = "success";
@RequestMapping("/testPojo")
public String testPojo(User user){
System.out.println("textPojo:"+user);
return SUCCESS;
}
}
使用原生ServletAPI作为目标方法的参数
可以使用Servlet元素的API作为目标方法的参数,具体支持以下几种类型:
HttpServletRequest
HttpServletResponse
HttpSession
java.security.Principal
Locale InputStream
OutputStream
Reader
Writer
例如:我们将HttpServletRequest和HttpServletResponse作为目标方法的参数
@RequestMapping("/testServletAPI")
public String testServletApi(HttpServletRequest request,
HttpServletResponse response){
System.out.println(request+" "+response);
return SUCCESS;
}