REST风格
(资源)表现层状态转化,是一种目前最流行的互联网软件架构,主要是用来要求URL地址的!
系统希望以非常简洁的URL地址来发请求;
怎样表示对一个资源的增删改查用请求方式来区分
- 例如:(以前的方式)
getBook?id=1
updateBook?id=1bookName=aaa
deleteBook?id=1
addBook?bookName=1
Rest推荐:
url地址这么起名:/资源名/资源标识符
/book/1 :GET----查询1号图书
/book/1 :PUT----更新1号图书
/book/1 :DELETE----删除1号图书
/book :POST----添加1号图书
系统的URL地址就这么来设计,简洁的URL提交请求,以请求方式区分对资源的操作。
问题:从页面上只能发起两种请求,GET、POST
其他的请求方式没法使用:
使用Rest来构造一个CRUD系统
从页面发起PUT,DELETE形式的请求?Springr提供了Rest风格的支持
1.springMVC有一个Filter,可以把请求转化了规定形式的
<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.如何发其他形式请求?
1.创建一个post类型的请求
2.表单项中携带一个_method的参数
3.这个_method的值就是DELETE、PUT
- 一个CRUD的小Demo
<a href="book/1">查询图书</a>
<form action="book" method="post">
<input type="submit" value="添加1号图书"/>
</form><br/>
<form action="book/1" method="post">
<input name="_method" value="delete">
<input type="submit" value="删除图书"/>
</form><br/>
<form action="book/1" method="post">
<input name="_method" value="put">
<input type="submit" value="更新图书"/>
</form><br/>
- success.jsp(注意如果是其他的请求时,成功页面必须加isErrorPage="true")
<%@ page contentType="text/html;charset=UTF-8" language="java"
isErrorPage="true" %>
<html>
<head>
<title>Title</title>
</head><body>
<h1>你成功了,666666</h1>
</body></html>
- BookController.class
@Controller
public class BookController {
@RequestMapping(value = "/book/{bid}",method = RequestMethod.GET)
public String addBook(@PathVariable("bid") Integer id){
System.out.println("查询到了"+id+"号图书");
return "success";
}
@RequestMapping(value = "/book/{bid}",method = RequestMethod.DELETE)
public String deleteBook(@PathVariable("bid") Integer id){
System.out.println("删除了"+id+"号图书");
return "success";
}
@RequestMapping(value = "/book/{bid}",method = RequestMethod.PUT)
public String updateBook(@PathVariable("bid") Integer id){
System.out.println("更新了"+id+"号图书");
return "success";
}
@RequestMapping(value = "/book",method = RequestMethod.POST)
public String getBook(){
System.out.println("添加了新的图书");
return "success";
}
}
- web.xml
<display-name>Archetype Created Web Application</display-name>
<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>
<servlet>
<servlet-name>dispatcherServlet</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>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<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>
-
运行结果
- 我们来看一下请求过滤方法HiddenHttpMethodFilter的源码
public class HiddenHttpMethodFilter extends OncePerRequestFilter {
/** Default method parameter: {@code _method} */
//接收带来的_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 {
HttpServletRequest requestToUse = request;
//如果是post方法并且没有异常
if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
//拿到这个请求中的参数
String paramValue = request.getParameter(this.methodParam);
//判断长度是否为空
if (StringUtils.hasLength(paramValue)) {
//然后调用HttpMethodRequestWrapper将参数转换为大写
//然后new了一个新的HttpMethodRequestWrapper,最后用新传进来的method重写了原来的getMethod
requestToUse = new HttpMethodRequestWrapper(request, paramValue);
}
}
filterChain.doFilter(requestToUse, response);
}
private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
private final String method;
public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
super(request);
this.method = method.toUpperCase(Locale.ENGLISH);
}
@Override
public String getMethod() {
return this.method;
}
}