- 表单提交发送PUT和DELETe请求
- IDEA模拟HTTP请求
本篇和RESTFul与RESTFul案例这篇文章有很多重复的地方,就当是复习吧。
表单提交发送PUT和DELETE请求REST(Representational State Transfer,表述性状态转移)是一种架构风格,它使用HTTP请求方式动词表示对资源的 *** 作。
具体看下面的例子吧。
- 新建Spring项目:demo3。
新建时添加3个依赖:Lombok、Spring Configuration Processor和SpringWeb。
项目新建好后,自动生成的pom.xml如下所示。
另外,将自动生成的配置文件application.properties重命名为application.yml。
4.0.0 org.springframework.boot spring-boot-starter-parent2.6.2 com.example demo30.0.1-SNAPSHOT demo3 Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-weborg.springframework.boot spring-boot-configuration-processortrue org.projectlombok lomboktrue org.springframework.boot spring-boot-starter-testtest org.springframework.boot spring-boot-maven-pluginorg.projectlombok lombok
- com.example.boot下新建控制器类controller.Demo3Controller。
package com.example.boot.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class Demo3Controller { @RequestMapping(value = "/user",method = RequestMethod.GET) public String get(){ return "get user"; } @RequestMapping(value = "/user",method = RequestMethod.POST) public String post(){ return "add user"; } @RequestMapping(value = "/user",method = RequestMethod.PUT) public String put(){ return "update user"; } @RequestMapping(value = "/user",method = RequestMethod.DELETE) public String delete(){ return "delete user"; } }
- resources.static下新建欢迎页面index.html。
首页
- 启动应用,访问localhost:8080。
点击按钮REST-GET,表单method设置为get,返回“查询用户”,OK;
点击按钮REST-POST,表单method设置为post,返回“新增用户”,OK;
点击按钮REST-PUT,表单method设置为put,返回“新增用户”,NOK;
点击按钮REST-POST,表单method设置为delete,返回“新增用户”,NOK。
由于表单method仅支持get和post方法,如果method设置为其他请求方式,如本例中的put或delete,浏览器会当作get请求方式处理。
要想使用表单发送put或delete请求,需要借助过滤器HiddenHttpMethodFilter,其源码如下,
public class HiddenHttpMethodFilter extends OncePerRequestFilter { private static final ListALLOWED_METHODS; public static final String DEFAULT_METHOD_PARAM = "_method"; private String methodParam = "_method"; public HiddenHttpMethodFilter() { } public void setMethodParam(String methodParam) { Assert.hasText(methodParam, "'methodParam' must not be empty"); this.methodParam = methodParam; } protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { HttpServletRequest requestToUse = request; if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) { String paramValue = request.getParameter(this.methodParam); if (StringUtils.hasLength(paramValue)) { String method = paramValue.toUpperCase(Locale.ENGLISH); if (ALLOWED_METHODS.contains(method)) { requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method); } } } filterChain.doFilter((ServletRequest)requestToUse, response); } static { ALLOWED_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.PATCH.name())); } private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper { private final String method; public HttpMethodRequestWrapper(HttpServletRequest request, String method) { super(request); this.method = method; } public String getMethod() { return this.method; } } }
做好以下两点就行:
1)表单的method设置为post。
2)发送给服务器的数据必须包括名为_method,值为put或delete的这么一个数据,可用input[type=“hidden”]实现。
按照以上思路修改index.html,修改后的结果如下,
首页
另外,还有很重要的一点,那就是需要在配置文件application.yml中添加以下内容,以启用HiddenHttpMethodFilter。
spring: mvc: hiddenmethod: filter: enabled: true
想知道为啥,到spring-boot-autoconfigure-2.6.2.jar的org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration里看看了。
public class WebMvcAutoConfiguration { public WebMvcAutoConfiguration() { } @Bean @ConditionalOnMissingBean({HiddenHttpMethodFilter.class}) @ConditionalOnProperty( prefix = "spring.mvc.hiddenmethod.filter", name = {"enabled"} ) public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() { return new OrderedHiddenHttpMethodFilter(); } //... }
需要满足两个条件,OrderedHiddenHttpMethodFilter实例才会添加到容器中 。
1)@ConditionalOnMissingBean({HiddenHttpMethodFilter.class}) ,条件:类路径下有HiddenHttpMethodFilter。
Ctrl+N,输入OrderedHiddenHttpMethodFilter,可找到,所以满足条件。
2) @ConditionalOnProperty( prefix = "spring.mvc.hiddenmethod.filter", name = {"enabled"} ),条件:配置文件中需要配置spring.mvc.hiddenmthod.filter.enable,且为true或者on。
最后,重启应用,查看效果。
刚刚提到,表单要发送put或delete请求,发送给服务器的数据必须包括名为_method,值为put或delete的这么一个数据,通常用来实现。其实,不一定非得name="_method",也可以是name="_mymethod或者其他,也就是说,可以自定义。具体怎么自定义,还得回到HiddenHttpMethodFilter的源码。
public class HiddenHttpMethodFilter extends OncePerRequestFilter { //... private String methodParam = "_method"; public void setMethodParam(String methodParam) { Assert.hasText(methodParam, "'methodParam' must not be empty"); this.methodParam = methodParam; } //... }
在com.example.boot下新建配置类config.MyConfig,如下,
package com.example.boot.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.filter.HiddenHttpMethodFilter; @Configuration public class MyConfig { @Bean public HiddenHttpMethodFilter hiddenHttpMethodFilter(){ HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter(); hiddenHttpMethodFilter.setMethodParam("_mymethod"); return hiddenHttpMethodFilter; } }
同时修改index.html,将name="_method"修改为name=_mymethod,如下。
重启应用,访问localhost:8080,验证结果,符合预期。
IDEA模拟HTTP请求使用IDEA发送HTTP请求,不需要使用HiddenHttpMethodFilter,不信瞧瞧。
首先修改application.yml把HiddenHttpMethodFilter关闭,如下。
spring: mvc: hiddenmethod: filter: enabled: off
然后,在demo3项目根目录下新建目录http,在http下新建文件demo3.http,内容如下。
GET http://localhost:8080/user Content-Type: application/json ### POST http://localhost:8080/user Content-Type: application/json ### PUT http://localhost:8080/user Content-Type: application/json ### DELETE http://localhost:8080/user Content-Type: application/json
最后,重启应用,发送请求。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)