1.SpringMVC是在原有的MVC结构上增加了 前端控制器 。前端控制器可以拦截所有请求,并对请求进行选择性派发。
前端控制器是一个Servlet,因此需要在web.xml中进行配置
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- servlet启动加载,之前servlet是第一次访问时创建对象
load-on-startup:服务器启动的时候创建对象,值越小优先级越高
-->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
2.前端控制器基本流程:
1>客户端通过点击链接发出请求:http://localhost:8080/springmvc/hello
2>Tomcat服务器接收到来自客户端的请求
3>SpringMVC的前端控制器接收所有请求
4>根据用户请求信息在IOC容器中查看与@RequestMapping中哪个方法标配,然后找到相应的类和方法。(@RequestMapping:是告诉SpringMVC哪些方法是用来处理请求,并且处理哪些请求。)
5>相应的方法处理后,返回一个值,前端控制器会认为该值是一个将要转发的页面地址
6>取到返回值之后,会经过视图解析器进行拼接,得到完整的地址
7>前端控制器根据完整地址转发到相应页面
3.@RequestMapping映射请求
(1)该注解可以放在方法上和类上:表示给该类中所有的方法都定义了基路径,因此当想要找到方法时,必须添加类的路径+方法路径
如果只注解在方法上,则表示相对于类定义处的URL。(当客户端发出请求的href处可直接写注解中value的值)
(2)@ReauqetMapping的其他属性
1>method:限定请求方式(例如method=RequestMethod.POST)
2>params:规定请求参数
3>headers:规定请求头(例如以下代码)
@RequestMapping(value="/testParamsAndHeaders",
params= {"username","age!=10"}, headers = { "Accept-Language=en-US,zh;q=0.8" })
//params中的值表示请求参数中必须带有username,且age不能为0
public String testParamsAndHeaders(){
System.out.println("testParamsAndHeaders...");
return "success";
}
(3) URL地址可以写模糊的匹配符:(精确和模糊路径下,精确路径优先)
1> ?:可以替代任一个字符
2> *:可以替代任意多个字符,和一层路径
3> **:可以替代多层路径
(4)@PathVariable:可以获取某路径下占位符的值(代码如下)
//@PathVariable 注解可以将请求URL路径中的请求参数,传递到处理请求方法的入参中
@RequestMapping(value="/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id){
System.out.println("testPathVariable...id="+id);
return "success";
}
4.SpringMVC支持REST风格,利用@RequestMapping中的参数实现REST风格
REST:将客户端向服务器发送的所有请求都可以看作是一个资源,例如请求一个文本,文件,视频等等,都可以看作是一种资源。
对资源的操作本质上来说都是增删改查。以前写代码,对每个资源的增删改查都有相应的方法,getXXX(),deleteXXX()... 而REST风格指的就是通过URL地址和请求方式的结合来表示客户端将进行什么请求。
但是由于原本在jsp中,客户端只能发送GET POST两种请求,因此还需要解决从页面发起PUT DELETE形式的请求问题。因此Spring中提供了对REST风格的支持。
/**
* 1.测试REST风格的 GET,POST,PUT,DELETE 操作
* 以CRUD为例:
* 新增: /order POST
* 修改: /order/1 PUT update?id=1
* 获取: /order/1 GET get?id=1
* 删除: /order/1 DELETE delete?id=1
* 2.如何发送PUT请求或DELETE请求?
* ①.配置HiddenHttpMethodFilter
* ②.需要发送POST请求
* ③.需要在发送POST请求时携带一个 name="_method"的隐含域,值为PUT或DELETE
* 3.在SpringMVC的目标方法中如何得到id值呢?
* 使用@PathVariable注解
*/
@RequestMapping(value="/testRESTGet/{id}",method=RequestMethod.GET)
public String testRESTGet(@PathVariable(value="id") Integer id){
System.out.println("testRESTGet id="+id);
return "success";
}
@RequestMapping(value="/testRESTPost",method=RequestMethod.POST)
public String testRESTPost(){
System.out.println("testRESTPost");
return "success";
}
@RequestMapping(value="/testRESTPut/{id}",method=RequestMethod.PUT)
public String testRESTPut(@PathVariable("id") Integer id){
System.out.println("testRESTPut id="+id);
return "success";
}
@RequestMapping(value="/testRESTDelete/{id}",method=RequestMethod.DELETE)
public String testRESTDelete(@PathVariable("id") Integer id){
System.out.println("testRESTDelete id="+id);
return "success";
}
(1)在web.xml中配置filter
<!-- 支持REST风格的过滤器:可以将POST请求转换为PUT或DELETE请求 -->
<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>
(2)在jsp中,首先创建一个post类型的表单,然后在该表单中设置一个_method的参数,对该参数进行赋值 value="delete"或者"put"
<fieldset>
<!-- 实验1 测试 REST风格 GET 请求 -->
<a href="springmvc/testRESTGet/1">testREST GET</a><br/><br/>
<!-- 实验2 测试 REST风格 POST 请求 -->
<form action="springmvc/testRESTPost" method="POST">
<input type="submit" value="testRESTPost">
</form>
<!-- 实验3 测试 REST风格 PUT 请求 -->
<form action="springmvc/testRESTPut/1" method="POST">
<input type="hidden" name="_method" value="PUT">
<input type="submit" value="testRESTPut">
</form>
<!-- 实验4 测试 REST风格 DELETE 请求 -->
<form action="springmvc/testRESTDelete/1" method="POST">
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="testRESTDelete">
</form>
</fieldset>
以上过程,主要都是在org.springframework.web.filter.HiddenHttpMethodFilter,因此查看其代码如下
public class HiddenHttpMethodFilter extends OncePerRequestFilter {
/** Default method parameter: {@code _method} */
public static final String DEFAULT_METHOD_PARAM = "_method";
private String methodParam = DEFAULT_METHOD_PARAM;
/**
* Set the parameter name to look for HTTP methods.
* @see #DEFAULT_METHOD_PARAM
*/
public void setMethodParam(String methodParam) {
Assert.hasText(methodParam, "'methodParam' must not be empty");
this.methodParam = methodParam;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String paramValue = request.getParameter(this.methodParam);
if ("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) {
String method = paramValue.toUpperCase(Locale.ENGLISH);
//将原先HttpRequest的getMethod方法重写
HttpServletRequest wrapper = new HttpMethodRequestWrapper(request, method);
//此时就可以通过wrapper得到PUT DELETE的请求方式
filterChain.doFilter(wrapper, response);
}
else {
filterChain.doFilter(request, response);
}
}
/**
* Simple {@link HttpServletRequest} wrapper that returns the supplied method for
* {@link HttpServletRequest#getMethod()}.
*/
private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
private final String method;
public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
super(request);
this.method = method;
}
@Override
public String getMethod() {
return this.method;
}
}
}