【转】Spring中的applicationContext.xml与SpringMVC的xxx-servlet.xml的区别

本文详细解析了SpringMVC框架中xxx-servlet.xml与applicationContext.xml的作用及使用场景,解释了两者如何区分,并强调了在不同架构下引入ApplicationContext的目的。

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

原文地址:http://blog.youkuaiyun.com/zb0567/article/details/7930642

 

一直搞不明白两者的区别。
如果使用了SpringMVC,事实上,bean的配置完全可以在xxx-servlet.xml中进行配置。为什么需要applicationContext.xml?一定必须?

一、
因为直接使用了SpringMVC,所以之前一直不明白xxx-servlet.xml和applicationContext.xml是如何区别的,其实如果直接使用SpringMVC是可以不添加applicationContext.xml文件的。
使用applicationContext.xml文件时是需要在web.xml中添加listener的:
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
而这个一般是采用非spring mvc架构,如使用struts之类而又想引入spring才添加的,这个是用来加载Application Context。
如果直接采用SpringMVC,只需要把所有相关配置放到xxx-servlet.xml中就OK了。

二、
Spring lets you define multiple contexts in a parent-child hierarchy.

The applicationContext.xml defines the beans for the "root webapp context", i.e. the context associated with the webapp.

The spring-servlet.xml (or whatever else you call it) defines the beans for one servlet's app context. There can be many of these in a webapp, one per Spring servlet (e.g. spring1-servlet.xml for servlet spring1, spring2-servlet.xml for servlet spring2).

Beans in spring-servlet.xml can reference beans in applicationContext.xml, but not vice versa.

All Spring MVC controllers must go in the spring-servlet.xml context.

In most simple cases, the applicationContext.xml context is unnecessary. It is generally used to contain beans that are shared between all servlets in a webapp. If you only have one servlet, then there's not really much point, unless you have a specific use for it.

<!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
<think>我们正在解决Spring MVC中DELETE请求方法导致的405错误。用户提到了使用HiddenHttpMethodFilter的情况。 根据引用[1],Spring通过HttpMethod类来解析HTTP方法,其中包含了对DELETE等方法的支持。 引用[2]提到了Spring MVC的初始化入口,这涉及到整个MVC配置的加载。 引用[3]提到了获取HttpServletResponse的问题,但这不是当前问题的重点。 引用[4]提到了从ApplicationContext中获取bean的过程,这有助于我们理解Spring如何解析和获取组件。 用户的问题:使用HiddenHttpMethodFilter时,DELETE请求返回405错误。 原因分析: 1. HiddenHttpMethodFilter的工作原理:它允许通过隐藏域(通常是名为"_method"的参数)来覆盖实际的HTTP方法。例如,在表单中,我们可以设置<input type="hidden" name="_method" value="delete">,然后通过POST请求来发送,该过滤器会将其换为DELETE请求。 2. 405错误(方法不允许)通常表示请求的URL不支持该HTTP方法。可能的原因包括: - 控制器方法没有正确映射到DELETE方法(例如,使用了@RequestMapping但没有指定method=RequestMethod.DELETE,或者使用了@DeleteMapping)。 - 过滤器没有正确配置,导致请求方法没有被换为DELETE。 - 服务器配置问题(例如,Tomcat等服务器可能默认不允许DELETE方法?但通常不会,因为Spring MVC会处理)。 解决方案步骤: 步骤1:确保在web.xml或通过Java配置注册了HiddenHttpMethodFilter,并且顺序正确(应该在Spring的DispatcherServlet之前)。 在web.xml中: ```xml <filter> <filter-name>hiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hiddenHttpMethodFilter</filter-name> <servlet-name>dispatcherServlet</servlet-name> </filter-mapping> ``` 步骤2:检查表单是否正确设置隐藏域_method。例如: ```html <form action="/someUrl" method="post"> <input type="hidden" name="_method" value="delete"> <!-- 其他表单内容 --> <input type="submit" value="Delete"> </form> ``` 步骤3:确保控制器方法映射了DELETE请求。例如: ```java @DeleteMapping("/someUrl") public ResponseEntity<?> deleteSomething() { // 删除操作 return ResponseEntity.ok().build(); } ``` 或者: ```java @RequestMapping(value="/someUrl", method=RequestMethod.DELETE) public ResponseEntity<?> deleteSomething() { // 删除操作 return ResponseEntity.ok().build(); } ``` 步骤4:检查是否还有其他过滤器或安全配置(如Spring Security)可能阻止了DELETE请求。 步骤5:如果使用Spring Security,确保在安全配置中允许DELETE方法。例如,在http配置中: ```java http.csrf().disable(); // 如果使用CSRF保护,可能需要禁用或配置csrf以支持DELETE ``` 因为CSRF保护可能会拦截非GET、POST等请求。或者,在表单中包含CSRF token。 步骤6:检查服务器日志,看是否有更详细的错误信息。 步骤7:如果使用Tomcat,检查web.xml中是否配置了<security-constraint>限制了DELETE方法?通常不会。 步骤8:确保DispatcherServlet的映射是“/”,而不是“/*”或“*.xxx”,以免导致请求被错误处理。 步骤9:如果使用RESTful风格,请确保URL路径匹配正确。 常见陷阱: -Spring Boot中,HiddenHttpMethodFilter是自动配置的,但需要设置spring.mvc.hiddenmethod.filter.enabled=true(默认是true,但有时可能被关闭)。 - 如果使用Spring Boot 2.2及以上,自动配置的HiddenHttpMethodFilter默认是启用的,但需要确保在表单中正确设置。 如果以上步骤都检查无误,仍然出现405错误,可以尝试以下方法: - 使用Postman等工具直接发送DELETE请求,看是否是客户端表单的问题。 - 在控制器方法上添加日志,看请求是否到达了控制器。 引用[1]中HttpMethod.resolve方法用于解析HTTP方法字符串,包括"DELETE",所以Spring内部是支持DELETE方法的。 根据引用[2],Spring MVC的初始化入口是initWebApplicationContext(),确保整个MVC配置正确加载。 引用[4]提到从ApplicationContext中获取bean,所以确保HiddenHttpMethodFilter已经被Spring容器管理(通常由Spring提供,我们只需配置即可)。 最后,如果问题仍然存在,请提供更多的上下文信息,例如配置代码、控制器代码和表单代码。 相关问题: 1. 如何在Spring MVC中正确配置HiddenHttpMethodFilter? 2. 除了HiddenHttpMethodFilter,还有哪些方法可以在HTML表单中发送PUT/DELETE请求? 3. Spring Security如何影响HTTP方法的使用? 4. 如何调试Spring MVC中的HTTP 405错误? 5.Spring Boot中如何启用或禁用HiddenHttpMethodFilter?</think>### 解决 Spring MVC DELETE 请求返回 405 错误的方法 在 Spring MVC 中使用 `HiddenHttpMethodFilter` 时出现 DELETE 请求返回 405 错误(Method Not Allowed),通常由以下原因导致: #### 1. **过滤器配置问题** [^2] - **过滤器未生效**:确保 `HiddenHttpMethodFilter` 在 `web.xml` 或配置类中正确注册: ```xml <!-- web.xml 配置 --> <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> ``` ```java // Java 配置类(Spring Boot) @Bean public FilterRegistrationBean<HiddenHttpMethodFilter> hiddenHttpMethodFilter() { return new FilterRegistrationBean<>(new HiddenHttpMethodFilter()); } ``` - **过滤器顺序错误**:该过滤器必须在 `DispatcherServlet` 之前执行,否则无法换请求方法。 #### 2. **请求参数缺失** - **必须包含 `_method` 参数**:HTML 表单需添加隐藏字段覆盖原始方法: ```html <form method="post"> <input type="hidden" name="_method" value="DELETE"> <!-- 其他字段 --> <button type="submit">删除</button> </form> ``` - **参数名称检查**:默认参数名为 `_method`,若自定义需同步修改过滤器逻辑。 #### 3. **控制器映射错误** - **未声明 DELETE 映射**:确保控制器方法使用 `@DeleteMapping` 或明确指定 `method = RequestMethod.DELETE`: ```java @DeleteMapping("/resource/{id}") public ResponseEntity<?> deleteResource(@PathVariable Long id) { // 业务逻辑 return ResponseEntity.ok().build(); } ``` - **URL 路径不匹配**:检查请求 URL 是否控制器中定义的路径一致。 #### 4. **CSRF 保护拦截**(Spring Security) - **CSRF Token 缺失**:若启用 Spring Security,表单需包含 CSRF Token: ```html <input type="hidden" name="_csrf" value="${_csrf.token}"> ``` - **临时禁用 CSRF**(仅测试): ```java @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); } ``` #### 5. **服务器配置限制** - **Tomcat 限制**:检查 `web.xml` 是否禁用 HTTP 方法: ```xml <!-- 错误示例:禁用 DELETE 方法 --> <security-constraint> <web-resource-collection> <http-method>DELETE</http-method> <!-- 删除此行 --> </web-resource-collection> </security-constraint> ``` #### 6. **其他排查步骤** - **日志分析**:启用 DEBUG 日志查看请求是否被正确换: ```properties logging.level.org.springframework.web=DEBUG ``` - **直接测试 DELETE**:用 Postman 直接发送 DELETE 请求,验证是否是客户端问题: ```http DELETE /resource/1 HTTP/1.1 ``` ### 常见解决方案总结 | 问题类型 | 解决措施 | |-------------------|--------------------------------------------------------------------------| | 过滤器未生效 | 检查 `web.xml`/Java 配置,确保过滤器注册且路径匹配正确 | | `_method` 参数缺失 | 在表单中添加 `<input type="hidden" name="_method" value="DELETE">` | | 控制器未映射 | 为方法添加 `@DeleteMapping` 或 `@RequestMapping(method = RequestMethod.DELETE)` | | CSRF 拦截 | 在表单中添加 CSRF Token 或临时禁用保护 | | 服务器限制 | 检查 `web.xml` 和服务器配置,允许 DELETE 方法 | > **关键提示**:`HiddenHttpMethodFilter` 的工作原理是将 **POST 请求** 中的 `_method` 参数值(如 `DELETE`)覆盖原始方法。因此实际请求必须是 **POST**,而非直接发送 DELETE 请求[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值