springboot接收浏览器发送delete请求( method not allowed 405解决方法)

【README】

浏览器使用form提交信息的时候只支持GET和POST,如果需要在浏览器上使用PUT和DELETE请求方式的话,只能使用欺骗的方式了,SpringMvc提供了HiddenHttpMethodFilter类来提供支持;


【1】前端

1)list.html

<body><!-- 引入抽取的topbar --><!--模板名: 会使用 thymeleaf的前后缀配置规则进行解析  --><!--<div th:replace="~{dashboard::topbar}"></div-->><div th:replace="commons/bar::topbar"></div><div class="container-fluid"><div class="row"><!-- 引入侧边栏 --><!--<div th:replace="~{dashboard::#sidebar}"></div>--><div th:replace="commons/bar::#sidebar(activeUri='emps')"></div><main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"><h2><a class="btn btn-sm btn-success" href="emp" th:href="@{/emp}">员工添加</a></h2><div class="table-responsive"><table class="table table-striped table-sm"><thead><tr><td>id</td><td>lastName</td><td>email</td><td>gender</td><td>department</td><td>birth</td><td>操作</td></tr></thead><tbody><tr th:each="emp:${emps}"><td th:text="${emp.id}"></td><td>[[${emp.lastName}]]</td><td>[[${emp.email}]]</td><td th:text="${emp.gender=='0'?'女':'男'}"></td><td th:text="${emp.department.departmentName}"></td><td th:text="${#dates.format(emp.birth,'yyyy-MM-dd')}"></td><td><a class="btn btn-sm btn-primary" th:href="@{/emp/}+${emp.id}">编辑</a><button th:attr="del_uri=@{/emp/}+${emp.id}" class="btn btn-sm btn-danger deleteBtn">删除</button></td></tr></tbody></table></div></main><form id="deleteEmpForm" method="post"><input type="hidden" name="_method" value="delete" /></form></div>
</div>

其中删除发送的是 rest风格的delete请求;

<button th:attr="del_uri=@{/emp/}+${emp.id}" class="btn btn-sm btn-danger deleteBtn">删除</button><form id="deleteEmpForm" method="post"><input type="hidden" name="_method" value="delete" />
</form><script>$(".deleteBtn").click(function(){// 删除当前员工			                             $("#deleteEmpForm").attr("action",$(this).attr("del_uri")).submit();return false;});
</script>

【2】springboot后端

EmployeeController 控制器


@Controller
public class EmployeeController {@AutowiredEmployeeDao employeeDao;@AutowiredDepartmentDao departmentDao;// 查询所有员工返回列表页面@GetMapping(value="/emps")public String list(Model model) {Collection<Employee> employees = employeeDao.getAll();// 放在请求域中model.addAttribute("emps", employees);// thymeleaf 默认拼串// classpath:/templates/XXXX.htmlreturn "emp/list";}// 来到员工添加页面@GetMapping("/emp")public String toAddPage(Model model) {// 来到添加页面, 查询所有部门,在页面显示Collection<Department> departments = departmentDao.getDepartments();model.addAttribute("depts", departments);return "emp/add";}// 员工添加功能,springmvc自动将请求参数和入参对象的属性进行一一绑定 ,请求参数名字和javaBean入参属性名是一致的@PostMapping("/emp")public String addEmp(Employee employee) {employeeDao.save(employee);/*** 添加成功后,来到员工列表页面,emp/list.html,有两种方式:* 方式1,redirect:/emps 重定向;方式2,forward: /emps 请求转发;* 不能直接返回 /emps,因为thymeleaf模板引擎会解析为 emps.html*/return "redirect:/emps";}// 来到员工修改页面, 查出当前员工,在页面回显@GetMapping("/emp/{id}")public String toEditPage(@PathVariable("id") Integer id, Model model) {// 页面显示所有部门列表model.addAttribute("depts", departmentDao.getDepartments());// 查询员工model.addAttribute("emp", employeeDao.get(id));// 回到修改或编辑页面(add是新增或编辑页面)return "emp/add";}// 员工修改请求@PutMapping("/emp")public String toEditPage(Employee employee) {employeeDao.save(employee);return "redirect:/emps";}// 员工删除请求@DeleteMapping("/emp/{id}")public String deleteEmployee(@PathVariable("id") Integer id) {employeeDao.delete(id);return "redirect:/emps";}
}

其中处理删除请求的映射如下:

 // 员工删除请求,接收delete请求@DeleteMapping("/emp/{id}")public String deleteEmployee(@PathVariable("id") Integer id) {employeeDao.delete(id);return "redirect:/emps";}

【3】点击删除

报错:(type=Method Not Allowed, status=405 

 method not allowed 405,表示 服务器不接收delete请求;

原因: springboot 没有启用 HiddenHttpMethodFilter 过滤器来支持delete请求;

解决方法:在 application.properties 中启用该过滤器, 如下:

application.properties 
# 启动HiddenHttpMethodFilter过滤器,以支持浏览器可以发送DELETE PUT 请求
spring.mvc.hiddenmethod.filter.enabled=true

 重启后,再次访问,如下:


 【4】附录:HiddenHttpMethodFilter

javax.servlet.Filter 将发布的方法参数转换为 HTTP 方法,可通过 HttpServletRequest.getMethod() 检索。 由于浏览器目前仅支持 GET 和 POST,因此一种常用技术(例如 Prototype 库使用的技术)是使用带有附加隐藏表单字段 (_method) 的普通 POST 来传递“真正的”HTTP 方法。 此过滤器读取该参数并相应地更改 HttpServletRequestWrapper.getMethod() 返回值。 只允许使用“PUT”、“DELETE”和“PATCH”HTTP 方法。
请求参数的名称默认为 _method,但可以通过 methodParam 属性进行调整。

public class HiddenHttpMethodFilter extends OncePerRequestFilter {private static final List<String> ALLOWED_METHODS =Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(),HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));/** 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;}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {HttpServletRequest requestToUse = request;if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {String paramValue = request.getParameter(this.methodParam);if (StringUtils.hasLength(paramValue)) {String method = paramValue.toUpperCase(Locale.ENGLISH);if (ALLOWED_METHODS.contains(method)) {requestToUse = new HttpMethodRequestWrapper(request, method);}}}filterChain.doFilter(requestToUse, 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;}@Overridepublic String getMethod() {return this.method;}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329965.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

tensorflow图形检测_社交距离检测器——Tensorflow检测模型设计

在隔离期间&#xff0c;我花时间在github上探索Tensorflow的大量预训练模型。这样做时&#xff0c;我偶然发现了一个包含25 个带有性能和速度指标的预训练对象检测模型的存储库。拥有一些计算机视觉知识并给出了实际的背景知识&#xff0c;我认为使用其中之一来构建社交隔离应用…

leetcode初级算法4.两个数组的交集 II

leetcode初级算法4.两个数组的交集 II 仅为个人刷题记录&#xff0c;不提供解题思路 题解与收获 我的解法&#xff1a;&#xff08;总结在代码中&#xff09; public int[] intersect(int[] nums1, int[] nums2) {//为空则返回if(nums1 null || nums2 null){return null;…

Java NIO:Buffer、Channel 和 Selector

转载自 Java NIO&#xff1a;Buffer、Channel 和 Selector本文将介绍 Java NIO 中三大组件 Buffer、Channel、Selector 的使用。 本来要一起介绍非阻塞 IO 和 JDK7 的异步 IO 的&#xff0c;不过因为之前的文章真的太长了&#xff0c;有点影响读者阅读&#xff0c;所以这里将它…

(转)使用IDEA将普通MAVEN项目转为WEB项目

转自&#xff1a; 使用IDEA将普通MAVEN项目转为WEB项目_yun0000000的博客-CSDN博客使用IDEA将普通MAVEN项目转为WEB项目https://blog.csdn.net/yun0000000/article/details/70664944 1、file--project Structure--,然后点“”号&#xff0c;,若没有war包&#xff0c;可修改mav…

python创建文件对象_python基础教程:文件读写

在Linux系统中&#xff0c;一切都是文件。但我们通常说的文件是保存在磁盘上的图片、文档、数据、程序等等。而在程序的IO操作中&#xff0c;很多时候就是从磁盘读写文件。本节我们讲解Python中的文件对象如何操作文件。创建文件对象 通过Python内置函数open()可以很容易的创建…

(转)springboot:添加JSP支持

转自&#xff1a; 14.springboot:添加JSP支持 - 简书&#xff08;1&#xff09;创建Maven web project 使用Eclipse新建一个Maven Web Project &#xff0c;项目取名为&#xff1a;spring-boot-jsp &#xff08;2&#xff09;在pom.xm...https://www.jianshu.com/p/4216bbd1e0…

leetcode初级算法5.加一

leetcode初级算法5.加一 仅为个人刷题记录&#xff0c;不提供解题思路 题解与收获 我的解法&#xff1a;&#xff08;总结在代码中&#xff09; public int[] plusOne(int[] digits) {//获取digits长度int length digits.length;//判断条件int count 0;//全是9的情况for …

epoll 浅析以及 nio 中的 Selector

转载自 epoll 浅析以及 nio 中的 Selector首先介绍下epoll的基本原理&#xff0c;网上有很多版本&#xff0c;这里选择一个个人觉得相对清晰的讲解&#xff08;详情见reference&#xff09;&#xff1a;首先我们来定义流的概念&#xff0c;一个流可以是文件&#xff0c;socket&…

转-SpringBoot——使用外置的Tomcat服务器

转自&#xff1a; SpringBoot——使用外置的Tomcat服务器_架构师的小跟班的博客-CSDN博客_springboot使用外置tomcat1 前言2 修改步骤2.1 修改打包方式&#xff08;jar -> war&#xff09;2.2 排除 SprignBoot的Web模块中的Tomcat依赖2.2.1 将嵌入的Tomcat依赖方式改成 pro…

leetcode初级算法6.字符串转整数(atoi)

leetcode初级算法6.字符串转整数(atoi) 仅为个人刷题记录&#xff0c;不提供解题思路 题解与收获 我的解法&#xff1a; public int myAtoi(String s) {//避免魔法值先设spaceString space " ";//如果是空或者是一串空字符串就滚回去&#xff01;if(s null || …

inner join on 加条件和where加条件_SQL学习笔记 - GROUP BY / JOIN / UNION

最近在DataCamp上学习SQL&#xff08;基于PostgreSQL&#xff09;的课程&#xff0c;本文主要记录自己易记混的点&#xff0c;以便日后参考学习&#xff0c;不做原理讲解。GROUP BY&#xff08;分组&#xff09;一般和聚合函数一起使用&#xff0c;包括COUNT()&#xff0c;AVG(…

Selector 实现原理

转载自 Selector 实现原理概述 Selector是NIO中实现I/O多路复用的关键类。Selector实现了通过一个线程管理多个Channel&#xff0c;从而管理多个网络连接的目的。 Channel代表这一个网络连接通道&#xff0c;我们可以将Channel注册到Selector中以实现Selector对其的管理。一个C…

转: 深入浅出-网络七层模型

转自 深入浅出&#xff0d;网络七层模型 - sunsky303 - 博客园引言 今天回顾一下&#xff0d;&#xff0d;网络七层模型&&网络数据包 网络基本概念 OSI模型 OSI 模型(Open System Interconnection model)是一个由国际标准化组织&#https://www.cnblogs.com/sunsky3…

date转timestamp格式_技术分享 | MySQL:timestamp 时区转换导致 CPU %sys 高的问题

作者&#xff1a;高鹏文章末尾有他著作的《深入理解 MySQL 主从原理 32 讲》&#xff0c;深入透彻理解 MySQL 主从&#xff0c;GTID 相关技术知识。本文为学习记录&#xff0c;可能有误请谅解。本文建议PC端观看&#xff0c;效果更佳。这个问题是一个朋友遇到的风云&#xff0c…

2021年最新springcloud配置中心不生效的版本原因

想直接看结论请到最下面&#xff0c;中间是我的纠错细节 实名吐槽一波cloudAlibaba文档。 github上的官方文档明明白白写着&#xff1a; 2.2.X版本适用于Springboot 2.2.X 彳亍&#xff01; 于是我将原本的2.6.0版本改成了SpringBoot 2.2.4Release&#xff0c;然后启动报错&a…

python爬新闻并保存csv_用python爬取内容怎么存入 csv 文件中

小白一个&#xff0c;爬取豆瓣电影250作为练习&#xff0c;想把爬取的内容用csv存储&#xff0c;想存但是不知道怎么自己原来代码拼接在一起。 ps:非伸手党&#xff0c;查阅了官方文档&#xff0c;也做了csv读写的练习&#xff0c;就是拼不到一起&#xff0c;不知道该怎么改。求…

idea部署springboot项目到外部tomcat

【README】 本文旨在记录idea部署springboot项目到外部tomcat的步骤&#xff1b; 第一次部署会踩很多坑儿&#xff0c;多查google&#xff0c;多重试&#xff1b; 第一次部署&#xff0c;不建议手动录入依赖&#xff0c;因为有可能遗漏&#xff1b;而且网络上资料很多但也很…

生成configDataContextRefres失败:Error creating bean with name ‘configDataContextRefresher‘

被这个问题折磨了很久&#xff0c;本人解决方法如下&#xff0c;奉劝一句&#xff0c;该看的官方文档还是要看&#xff0c;但是千万别傻傻地照做&#xff01; 首先编写bootstrap.properties&#xff0c;往里写入&#xff1a; 这些基础配置 然后检查自己是否引入了这个依赖&am…

python怎么用for循环找出最大值_用for循环语句写一个在输入的十个数字中求最大和最小值的python程序应该怎么写?...

“在输入的十个数字中求最大和最小值的 python 代码”这个需求&#xff0c;在不同时间来看&#xff0c;解题思路不同&#xff0c;所需要的 python 知识点不同。 作为萌新的我&#xff0c;为此特意整理了 3 种解法&#xff0c;以及相应的知识点笔记。 解法A&#xff1a;不使用列…

(转)mysql查看连接客户端ip和杀死进程

转自&#xff1a; mysql &#xff1a; show processlist 详解 - _小豪豪 - 博客园最近排查一些MySQL的问题&#xff0c;会经常用到 show processlist&#xff0c;所以在这里把这个命令总结一下&#xff0c;做个备忘&#xff0c;以备不时只需。 首先是几条常用的SQL。 1、按客户…