SpringMVC(四):@RequestMapping结合org.springframework.web.filter.HiddenHttpMethodFilter实现REST请求...

本文介绍如何在SpringMVC项目中实现RESTful风格的服务,包括利用HiddenHttpMethodFilter处理非标准HTTP方法如DELETE和PUT,并提供代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1)REST具体表现:

--- /account/1  HTTP GET       获取id=1的account

--- /account/1  HTTP DELETE 删除id=1的account

--- /aacount/1  HTTP PUT        更新id=1的account

--- /account      HTTP POST     新增account

2)SpringMVC中如何实现REST?

众所周知,浏览器form表单只支持GET与POST请求,而DELETE、PUT等method并不支持。Spring3.0增加了一个过滤器,可以将这些请求转化为标准的http方法,使得支持GET、POST、PUT及DELETE请求。

这个过滤器就是:org.springframework.web.filter.HiddenHttpMethodFilter

 1 package org.springframework.web.filter;
 2 
 3 import java.io.IOException;
 4 import java.util.Locale;
 5 import javax.servlet.FilterChain;
 6 import javax.servlet.ServletException;
 7 import javax.servlet.http.HttpServletRequest;
 8 import javax.servlet.http.HttpServletRequestWrapper;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 import org.springframework.util.Assert;
12 import org.springframework.util.StringUtils;
13 import org.springframework.web.util.WebUtils;
14 
15 /**
16  * {@link javax.servlet.Filter} that converts posted method parameters into HTTP methods,
17  * retrievable via {@link HttpServletRequest#getMethod()}. Since browsers currently only
18  * support GET and POST, a common technique - used by the Prototype library, for instance -
19  * is to use a normal POST with an additional hidden form field ({@code _method})
20  * to pass the "real" HTTP method along. This filter reads that parameter and changes
21  * the {@link HttpServletRequestWrapper#getMethod()} return value accordingly.
22  *
23  * <p>The name of the request parameter defaults to {@code _method}, but can be
24  * adapted via the {@link #setMethodParam(String) methodParam} property.
25  *
26  * <p><b>NOTE: This filter needs to run after multipart processing in case of a multipart
27  * POST request, due to its inherent need for checking a POST body parameter.</b>
28  * So typically, put a Spring {@link org.springframework.web.multipart.support.MultipartFilter}
29  * <i>before</i> this HiddenHttpMethodFilter in your {@code web.xml} filter chain.
30  *
31  * @author Arjen Poutsma
32  * @author Juergen Hoeller
33  * @since 3.0
34  */
35 public class HiddenHttpMethodFilter extends OncePerRequestFilter {
36 
37     /** Default method parameter: {@code _method} */
38     public static final String DEFAULT_METHOD_PARAM = "_method";
39 
40     private String methodParam = DEFAULT_METHOD_PARAM;
41 
42 
43     /**
44      * Set the parameter name to look for HTTP methods.
45      * @see #DEFAULT_METHOD_PARAM
46      */
47     public void setMethodParam(String methodParam) {
48         Assert.hasText(methodParam, "'methodParam' must not be empty");
49         this.methodParam = methodParam;
50     }
51 
52     @Override
53     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
54             throws ServletException, IOException {
55 
56         HttpServletRequest requestToUse = request;
57 
58         if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
59             String paramValue = request.getParameter(this.methodParam);
60             if (StringUtils.hasLength(paramValue)) {
61                 requestToUse = new HttpMethodRequestWrapper(request, paramValue);
62             }
63         }
64 
65         filterChain.doFilter(requestToUse, response);
66     }
67 
68 
69     /**
70      * Simple {@link HttpServletRequest} wrapper that returns the supplied method for
71      * {@link HttpServletRequest#getMethod()}.
72      */
73     private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
74 
75         private final String method;
76 
77         public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
78             super(request);
79             this.method = method.toUpperCase(Locale.ENGLISH);
80         }
81 
82         @Override
83         public String getMethod() {
84             return this.method;
85         }
86     }
87 
88 }

从这个filter代码中可以得知,该filter是通过POST方式提交表单,该表单中包含一个名称为_method的隐藏域,该隐藏域的值用来判定将要转化的请求方式。所谓的转化请求方式,就是在该filter中重新生成了一个新的、标准化的请求。

3)如何使用到springmvc项目中?

步骤一:在web.xml中添加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>

步骤二:在HelloWord.java中添加get/post/put/delete方法:

 1 package com.dx.springlearn.handlers;
 2 
 3 import org.springframework.stereotype.Controller;
 4 import org.springframework.web.bind.annotation.PathVariable;
 5 import org.springframework.web.bind.annotation.RequestMapping;
 6 import org.springframework.web.bind.annotation.RequestMethod;
 7 
 8 @Controller
 9 @RequestMapping("class_requestmapping")
10 public class HelloWord {
11     private static String SUCCESS = "success";
12 
13     @RequestMapping(value = "/accountDelete/{id}", method = RequestMethod.DELETE)
14     public String accountDelete(@PathVariable("id") Integer id) {
15         System.out.println("test rest DELETE,account id:" + id);
16         return SUCCESS;
17     }
18 
19     @RequestMapping(value = "/accountPut/{id}", method = RequestMethod.PUT)
20     public String accountPut(@PathVariable("id") Integer id) {
21         System.out.println("test rest PUT,account id:" + id);
22         return SUCCESS;
23     }
24 
25     @RequestMapping(value = "/account", method = RequestMethod.POST)
26     public String account() {
27         System.out.println("test rest POST");
28         return SUCCESS;
29     }
30 
31     @RequestMapping(value = "/account/{id}", method = RequestMethod.GET)
32     public String account(@PathVariable("id") Integer id) {
33         System.out.println("test rest GET,account id:" + id);
34         return SUCCESS;
35     }
36 }

步骤三:在index.jsp中添加get/post/put/delete方法请求的html脚本:

    <!-- delete提交 -->    
    <form id="form_testRestMethod_DELETE" name="form_testRestMethod_DELETE" method="POST"
        action="class_requestmapping/accountDelete/2">
        <input type="hidden" name="_method" value="DELETE" />
        <button name="submit" id="submit">test rest DELETE</button>
    </form>
    <br>
    <!-- put提交 -->    
    <form id="form_testRestMethod_PUT" name="form_testRestMethod_PUT" method="POST"
        action="class_requestmapping/accountPut/2">
        <input type="hidden" name="_method" value="PUT" />
        <button name="submit" id="submit">test rest PUT</button>
    </form>
    <br>
    <!-- post提交 -->    
    <form id="form_testRestMethod_POST" name="form_testRestMethod_POST"
        method="POST" action="class_requestmapping/account">
        <button name="submit" id="submit">test rest POST</button>
    </form>
    <br>
    <!-- get提交 -->    
    <a href="class_requestmapping/account/1">test rest GET</a>
    <br>

步骤四:测试打印结果为:

test rest GET,account id:1
test rest POST
test rest PUT,account id:2
test rest DELETE,account id:2

 

转载于:https://www.cnblogs.com/yy3b2007com/p/8194386.html

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>员工信息</title> <script type="text/javascript" th:src="@{/js/vue.global.js}"></script> </head> <body> <table id="dataTable" border="1" cellspacing="0" cellpadding="0" style="text-align:center"> <tr> <th colspan="5">员工信息</th> </tr> <tr> <th>编号</th> <th>姓名</th> <th>邮箱</th> <th>性别</th> <th>操作</th> </tr> <tr th:each="employee : ${employeeList}"> <td th:text="${employee.id}"></td> <td th:text="${employee.lastName}"></td> <td th:text="${employee.email}"></td> <td th:text="${employee.gender}"></td> <td> <a @click="deleteEmployee" th:href="@{'/employee/' + ${employee.id}}">删除</a> <a href="">修改</a> </td> </tr> </table> <form id="deleteForm" method="post"> <input type="hidden" name="_method" value="delete"> </form> <script type="text/javascript"> var vue = new Vue({ el: "#dataTable", methods: { deleteEmployee: function (event) { var deleteForm = document.getElementById("deleteForm"); deleteForm.action = event.target.href; deleteForm.submit(); event.preventDefault(); } } }); </script> </body> </html> //删除员工信息 @RequestMapping(value = "/employee/{id}",method = RequestMethod.DELETE) public String deleteEmployee(@PathVariable("id") Integer id){ employeeDao.delete(id); return "redirect:/employee"; } <?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"> <!--配置编码过滤器--> <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>forceResponseEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--配置 处理请求方式put,delete的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> <!--配置SpringMVC的前端控制器DispatcherServlet--> <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> </web-app> <?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 https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--开启组件扫描--> <context:component-scan base-package="com.atguigu.rest"/> <!--配置thymeleaf视图解析器--> <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver"> <property name="order" value="1"/> <property name="characterEncoding" value="UTF-8"/> <property name="templateEngine"> <bean class="org.thymeleaf.spring5.SpringTemplateEngine"> <property name="templateResolver"> <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver"> <!-- 视图前缀 --> <property name="prefix" value="/WEB-INF/templates/"/> <!-- 视图后缀 --> <property name="suffix" value=".html"/> <property name="templateMode" value="HTML5"/> <property name="characterEncoding" value="UTF-8"/> </bean> </property> </bean> </property> </bean> <!--配置视图控制器--> <mvc:view-controller path="/" view-name="index"></mvc:view-controller> <!--开放对静态资源的访问呢--> <mvc:default-servlet-handler></mvc:default-servlet-handler> <!--开启mvc注解驱动--> <mvc:annotation-driven></mvc:annotation-driven> </beans> 报错 405 找不到方法
最新发布
07-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值