<context:annotation-config/>和 <context:component-scan base-package=""/>的区别
时间: 2023-05-11 14:06:19 浏览: 150
<context:annotation-config/>是用来启用注解的支持,它会扫描 Spring 容器中的所有 Bean,查找其中使用了注解的类,并将这些注解解析成相应的 Bean 定义。而<context:component-scan base-package=""/>则是用来扫描指定包下的所有类,查找其中使用了特定注解的类,并将其注册为 Bean。因此,它们的作用略有不同,但都是用来帮助 Spring 容器管理 Bean 的。
相关问题
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <context-param> <param-name>metadata-complete</param-name> <param-value>true</param-value> </context-param> <servlet> <servlet-name>exampleServlet</servlet-name> <servlet-class>com.example.ExampleServlet</servlet-class> </servlet> <servlet> <description>generated-servlet</description> <servlet-name>KuCun2 Servlet</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:KuCun2-web-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet> <description>generated-resources-servlet</description> <servlet-name>Resource Servlet</servlet-name> <servlet-class> org.springframework.js.resource.ResourceServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>exampleServlet</servlet-name> <url-pattern>/example</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Resource Servlet</servlet-name> <url-pattern>/resources/*</url-pattern> </servlet-mapping> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <listener> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> </web-app>
<think>我们有一个web.xml配置文件,该文件配置了一个SpringMVC应用。但是,这个配置看起来有些过时(比如使用了SpringJSResourceServlet,这通常与SpringWebFlow一起使用,但现在较少使用)。此外,还配置了一个示例Servlet(ExampleServlet)和一个SpringMVC的DispatcherServlet。问题分析:1.配置了`ContextLoaderListener`和`DispatcherServlet`,这会导致创建两个Spring容器:一个根应用上下文(由ContextLoaderListener创建)和一个Web应用上下文(由DispatcherServlet创建)。2.根应用上下文的配置文件通过`contextConfigLocation`指定为`classpath:applicationContext.xml`。3.DispatcherServlet的配置文件通过其`init-param`指定为`classpath:KuCun2-web-context.xml`。4.还配置了一个`ResourceServlet`,用于处理静态资源,但现代SpringMVC通常使用`<mvc:resources>`标签或重写`WebMvcConfigurer`的`addResourceHandlers`方法。但是,这个配置可能存在的问题:-如果应用不需要两个Spring容器,可以考虑只使用一个(通常将配置全部放在DispatcherServlet的上下文中,或者使用组件扫描)。-`ResourceServlet`可能不是必要的,因为SpringMVC自己可以处理静态资源。另外,注意`metadata-complete`被设置为`true`,这意味着不会扫描web-fragment和注解(如@WebServlet),所以所有的配置都必须在这个web.xml中显式配置。根据这个配置,应用启动时会加载两个配置文件:`applicationContext.xml`(根上下文)和`KuCun2-web-context.xml`(DispatcherServlet的上下文)。如何改进?1.如果不需要两个上下文,可以去掉`ContextLoaderListener`,并将所有配置放在DispatcherServlet的上下文中。2.移除`ResourceServlet`,改为在Spring配置中使用`<mvc:resources>`。下面给出一个更现代化的web.xml配置示例(假设使用Spring5和Servlet3.1),并去掉不必要的部分:但是,请注意:从Servlet3.0开始,我们可以使用Java配置代替web.xml。不过,如果你仍然需要web.xml,这里提供一个改进版本。改进后的web.xml(去掉了ResourceServlet和示例Servlet,并调整了DispatcherServlet的配置):</think>根据提供的 `web.xml` 配置文件,这是一个基于 Spring MVC 的 Java Web 应用配置。以下是关键配置的分析和改进建议:
### 问题分析
1. **DispatcherServlet 配置问题**:
- 使用了过时的 `KuCun2-web-context.xml` 命名方式(应遵循标准命名规范)
- 缺少现代 Spring MVC 的注解驱动配置
2. **静态资源处理问题**:
- 使用 `ResourceServlet` 处理静态资源的方式已过时(Spring 3.1+ 推荐使用 `<mvc:resources>`)
3. **上下文配置问题**:
- 同时配置了 `ContextLoaderListener` 和 `DispatcherServlet` 的上下文,可能导致冲突
- 缺少组件扫描(component-scan)配置
### 改进后的配置方案
```xml
<?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">
<!-- 上下文参数 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
</param-value>
</context-param>
<!-- Spring 根容器初始化 -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- Spring MVC 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:spring-mvc-config.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Servlet 映射 -->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 字符编码过滤器 -->
<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>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
```
### 配套的 Spring MVC 配置文件 (`spring-mvc-config.xml`)
```xml
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 启用注解驱动 -->
<mvc:annotation-driven />
<!-- 组件扫描 -->
<context:component-scan base-package="com.kucun.controller" />
<!-- 静态资源处理 -->
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 异常处理 -->
<bean class="com.kucun.controller.ErrorController" />
</beans>
```
### 关键改进说明
1. **标准化命名**:
- 使用 `dispatcherServlet` 作为标准名称
- 将 MVC 配置重命名为 `spring-mvc-config.xml`
2. **注解驱动配置**:
- 添加 `<mvc:annotation-driven>` 启用现代注解驱动开发模式
- 添加 `<context:component-scan>` 自动扫描控制器
3. **静态资源处理**:
- 使用 `<mvc:resources>` 替代 `ResourceServlet`
- 更高效地处理 CSS/JS/图片等静态资源
4. **字符编码过滤器**:
- 添加 UTF-8 字符编码过滤器,解决中文乱码问题
5. **异常处理**:
- 明确配置异常处理控制器
### 迁移到 Java Config(推荐)
现代 Spring 项目推荐使用 Java 配置代替 XML:
```java
// SpringMvcConfig.java
@Configuration
@EnableWebMvc
@ComponentScan("com.kucun.controller")
public class SpringMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
// WebInitializer.java
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { SpringMvcConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
encodingFilter.setForceEncoding(true);
return new Filter[] { encodingFilter };
}
}
```
### 改进优势
1. **现代化配置**:符合当前 Spring 最佳实践
2. **可维护性**:分离关注点,配置更清晰
3. **扩展性**:更容易添加拦截器、消息转换器等组件
4. **性能优化**:更高效的静态资源处理机制
---
(一)项目构建 使用 Maven 构建项目,在pom.xml中引入 Spring MVC 相关依赖,如spring - webmvc,配置 Servlet、JSP 等相关依赖,确保项目具备 Spring MVC 运行环境 。示例关键依赖配置: <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring - webmvc</artifactId> <version>5.3.18</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet - api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp - api</artifactId> <version>2.3.3</version> <scope>provided</scope> </dependency> <!-- 其他如JSTL等依赖按需添加 --> </dependencies> (二)Spring MVC 配置 DispatcherServlet 配置:在 Web.xml(或 Servlet 3.0 + 环境下用 Java 配置)中配置 DispatcherServlet,指定 Spring MVC 配置文件位置,使其能拦截处理请求 。示例 Web.xml 配置: <servlet> <servlet - name>springmvc</servlet - name> <servlet - class>org.springframework.web.servlet.DispatcherServlet</servlet - class> <init - param> <param - name>contextConfigLocation</param - name> <param - value>classpath:springmvc - servlet.xml</param - value> </init - param> <load - on - startup>1</load - on - startup> </servlet> <servlet - mapping> <servlet - name>springmvc</servlet - name> <url - pattern>/</url - pattern> </servlet - mapping> Spring MVC 配置文件(springmvc - servlet.xml):开启组件扫描(扫描控制器等组件)、视图解析器(配置前缀后缀,解析 JSP 视图)、开启注解驱动等 。示例: <context:component - scan base - package="com.example.controller"/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB - INF/views/"/> <property name="suffix" value=".jsp"/> </bean> <mvc:annotation - driven/> 三)功能模块实现 1. 用户登录验证 o 控制器(Controller):创建LoginController,编写方法处理/login请求(对应login.jsp表单提交),接收用户名、密码参数(可通过@RequestParam注解),进行简单验证(如硬编码用户名 “admin”、密码 “123” 模拟,实际可连数据库查询),验证成功用return "redirect:/main";重定向到主页控制器方法,失败则带错误信息(通过model.addAttribute)返回login视图(即login.jsp )。示例代码: package com.example.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class LoginController { @RequestMapping("/login") public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model) { if ("admin".equals(username) && "123".equals(password)) { return "redirect:/main"; } else { model.addAttribute("error", "用户名或密码错误"); return "login"; } } 2. 登录页面(login.jsp):使用 Spring 表单标签库(需引入相关标签库)或普通 HTML 表单,提交到/login,显示错误信息(通过 EL 表达式${error} )。示例关键代码: <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <html> <body> <form:form action="/login" method="post"> 用户名:<form:input path="username"/><br> 密码:<form:password path="password"/><br> <input type="submit" value="登录"> </form:form> <c:if test="${not empty error}"> <p style="color:red">${error}</p> </c:if> </body> </html> 3. 访问控制(拦截器实现) o 创建拦截器类:实现HandlerInterceptor接口,在preHandle方法中检查会话是否有用户登录标识(如session.getAttribute("user") ,假设登录成功时在会话存user对象),无则redirect到/login并返回false拦截,有则返回true放行 。示例: package com.example.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object user = request.getSession().getAttribute("user"); if (user == null) { response.sendRedirect(request.getContextPath() + "/login"); return false; } return true; } } 4. 配置拦截器:在 Spring MVC 配置文件(springmvc - servlet.xml)中注册拦截器,指定拦截路径(如/main )。示例: <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/main"/> <bean class="com.example.interceptor.LoginInterceptor"/> </mvc:interceptor> </mvc:interceptors> 5. 会话管理(登出功能) o 控制器方法:在MainController中编写处理登出的方法,调用session.invalidate()销毁会话,然后redirect到登录页 。示例: package com.example.controller; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class MainController { @RequestMapping("/main") public String main() { return "main"; } @RequestMapping("/logout") public String logout(HttpSession session) { session.invalidate(); return "redirect:/login"; } } 6. 主页(main.jsp):添加 “退出” 链接, href 指向/logout 。示例: <html> <body> <h1>欢迎访问主页</h1> <a href="${pageContext.request.contextPath}/logout">退出</a> </body> </html>
### 1. Maven依赖配置
在构建Spring MVC项目时,需要在`pom.xml`中添加必要的Maven依赖。以下是完整的依赖配置:
```xml
<dependencies>
<!-- Spring Web MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.22</version>
</dependency>
<!-- Servlet API -->
<dependency>
<groupId>jakarta.servlet.jsp</groupId>
<artifactId>jakarta.servlet.jsp-api</artifactId>
<version>3.0.0</version>
<scope>provided</scope>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>jakarta.servlet.jsp.jstl</groupId>
<artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
<version>3.0.0</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.36</version>
</dependency>
<!-- Jackson for JSON processing -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.3</version>
</dependency>
</dependencies>
```
以上配置包含了Spring Web MVC的核心依赖[^1]、Servlet API、JSTL以及日志和JSON处理库。
---
### 2. DispatcherServlet配置
在`web.xml`中配置`DispatcherServlet`,它是Spring MVC框架的前端控制器。以下是示例配置:
```xml
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
```
上述配置将`/WEB-INF/spring-mvc-config.xml`作为Spring MVC的配置文件,并将所有请求映射到`DispatcherServlet`[^2]。
---
### 3. Spring MVC配置文件
`spring-mvc-config.xml`用于定义组件扫描路径、视图解析器等。以下是一个示例配置:
```xml
<?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
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 启用注解驱动 -->
<mvc:annotation-driven />
<!-- 组件扫描 -->
<context:component-scan base-package="com.example.controller" />
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
```
此配置启用了注解驱动[^2]、扫描了指定包下的控制器类,并设置了JSP视图解析器。
---
### 4. 用户登录验证的Controller实现
以下是一个简单的用户登录验证控制器示例:
```java
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class LoginController {
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String showLoginPage() {
return "login"; // 映射到 /WEB-INF/views/login.jsp
}
@RequestMapping(value = "/perform_login", method = RequestMethod.POST)
public ModelAndView performLogin(@RequestParam("username") String username,
@RequestParam("password") String password) {
if ("admin".equals(username) && "password".equals(password)) {
return new ModelAndView("redirect:/home");
} else {
ModelAndView modelAndView = new ModelAndView("login");
modelAndView.addObject("error", "Invalid credentials!");
return modelAndView;
}
}
}
```
---
### 5. 登录页面开发(login.jsp)
以下是一个简单的`login.jsp`页面示例:
```jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Login</title>
</head>
<body>
<h2>Login Page</h2>
<form action="${pageContext.request.contextPath}/perform_login" method="post">
Username: <input type="text" name="username"><br><br>
Password: <input type="password" name="password"><br><br>
<input type="submit" value="Login">
</form>
<c:if test="${not empty error}">
<p style="color:red">${error}</p>
</c:if>
</body>
</html>
```
---
### 6. HandlerInterceptor拦截器实现及配置
以下是一个简单的拦截器实现及其配置:
#### 拦截器实现
```java
package com.example.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@Component
public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession(false);
if (session != null && session.getAttribute("user") != null) {
return true; // 已登录,继续处理请求
} else {
response.sendRedirect(request.getContextPath() + "/login");
return false; // 未登录,重定向到登录页面
}
}
}
```
#### 拦截器配置
在`spring-mvc-config.xml`中注册拦截器:
```xml
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/login"/>
<mvc:exclude-mapping path="/perform_login"/>
<bean class="com.example.interceptor.AuthenticationInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
```
---
### 7. 登出功能和会话管理
登出功能可以通过销毁会话实现:
```java
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logout(HttpSession session) {
session.invalidate(); // 销毁会话
return "redirect:/login";
}
```
---
### 总结
以上内容涵盖了使用Maven构建Spring MVC项目的完整流程,包括依赖配置、`DispatcherServlet`配置、Spring MVC配置文件、控制器实现、登录页面开发、拦截器实现及配置、登出功能和会话管理。
---
阅读全文
相关推荐

















