springboot接收浏览器发送delete请求( method not allowed 405解决方法)
Posted PacosonSWJTU
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 {
@Autowired
EmployeeDao employeeDao;
@Autowired
DepartmentDao departmentDao;
// 查询所有员工返回列表页面
@GetMapping(value="/emps")
public String list(Model model) {
Collection<Employee> employees = employeeDao.getAll();
// 放在请求域中
model.addAttribute("emps", employees);
// thymeleaf 默认拼串
// classpath:/templates/XXXX.html
return "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;
}
@Override
protected 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;
}
@Override
public String getMethod() {
return this.method;
}
}
}
以上是关于springboot接收浏览器发送delete请求( method not allowed 405解决方法)的主要内容,如果未能解决你的问题,请参考以下文章
spring boot 2.0 之后发送delete,put请求问题
http中get,post,put,delete方法的用法以及区别