1. 用户发起请求
- 用户行为:用户在浏览器中输入URL或点击链接,向Web服务器(如Tomcat)发起一个HTTP请求。
- 请求传输:请求被发送到Web容器,Web容器根据配置将请求转发给
DispatcherServlet
。
2. 前端控制器(DispatcherServlet)
- 作用:
DispatcherServlet
是Spring MVC的核心组件,负责接收所有进入的HTTP请求,并将它们分发给适当的处理器(Controller)。 - 初始化:在Web应用启动时,
DispatcherServlet
会被初始化,并且会读取Spring配置文件(如dispatcher-servlet.xml
)来初始化相关的Bean。
web.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/appServlet/servlet-context.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>
3. 处理器映射(HandlerMapping)
- 作用:
DispatcherServlet
接收到请求后,会查询HandlerMapping
以确定哪个控制器应该处理该请求。 - 常见类型:
RequestMappingHandlerMapping
:基于@RequestMapping
注解的映射。BeanNameUrlHandlerMapping
:基于Bean名称的映射。SimpleUrlHandlerMapping
:基于简单的URL映射。
dispatcher-servlet.xml
配置
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
4. 控制器(Controller)
- 作用:控制器负责处理具体的业务逻辑,可以访问请求参数、表单数据、会话信息等。
- 返回值:控制器方法处理完请求后,返回一个
ModelAndView
对象给DispatcherServlet
。ModelAndView
包含两个部分:- Model:模型数据,即业务数据,可以是一个Map对象,用于向视图传递数据。
- View:逻辑视图名,表示要使用的视图资源的名称。
控制器示例
@Controller
public class HelloController {
@Autowired
private SomeService someService;
@RequestMapping("/hello")
public ModelAndView hello(@RequestParam("name") String name) {
// 调用服务层方法
String message = someService.getMessage(name);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("message", message);
modelAndView.setViewName("hello");
return modelAndView;
}
}
5. 视图解析器(ViewResolver)
- 作用:
DispatcherServlet
接收到ModelAndView
对象后,会使用ViewResolver
来解析逻辑视图名,找到对应的物理视图资源(如JSP页面)。 - 常见类型:
InternalResourceViewResolver
:用于JSP视图。ThymeleafViewResolver
:用于Thymeleaf视图。FreeMarkerViewResolver
:用于FreeMarker视图。
dispatcher-servlet.xml
配置
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
6. 视图渲染
- 作用:找到具体的视图资源后,
DispatcherServlet
将模型数据传递给视图进行渲染。 - 渲染过程:视图负责将模型数据转换为HTML或其他格式的输出,这个过程可能包括数据格式化、模板渲染等。
视图示例 (hello.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Hello Page</title>
</head>
<body>
<h1>${message}</h1>
</body>
</html>
7. 响应客户端
- 作用:渲染完成后,
DispatcherServlet
将最终的HTML页面通过HTTP响应返回给客户端浏览器,用户可以看到请求的结果。
8. 拦截器(Interceptor)
- 作用:在请求处理的过程中,可以配置拦截器来执行一些额外的操作,如日志记录、权限验证、性能监控等。
- 实现方式:通过实现
HandlerInterceptor
接口或继承HandlerInterceptorAdapter
类来创建拦截器。
拦截器示例
@Component
public class LoggingInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Pre-handle: " + request.getRequestURI());
return true; // 继续处理请求
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Post-handle: " + request.getRequestURI());
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("After completion: " + request.getRequestURI());
}
}
拦截器配置示例
<mvc:interceptors>
<bean class="com.example.interceptor.LoggingInterceptor" />
</mvc:interceptors>
9. 异常处理(ExceptionHandler)
- 作用:Spring MVC提供了异常处理机制,可以在控制器中使用
@ExceptionHandler
注解来处理特定类型的异常。 - 全局异常处理:还可以在全局范围内使用
@ControllerAdvice
注解来定义全局异常处理。
异常处理示例
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ModelAndView handleResourceNotFoundException(ResourceNotFoundException ex) {
ModelAndView modelAndView = new ModelAndView("error");
modelAndView.addObject("errorMessage", ex.getMessage());
return modelAndView;
}
@ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception ex) {
ModelAndView modelAndView = new ModelAndView("error");
modelAndView.addObject("errorMessage", "An unexpected error occurred.");
return modelAndView;
}
}
10. 数据绑定和验证
- 数据绑定:Spring MVC提供了数据绑定机制,可以自动将请求参数绑定到控制器方法的参数上。
- 数据验证:可以使用
@Valid
和@Validated
注解结合JSR 303(如Hibernate Validator)来进行数据验证。
数据绑定和验证示例
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/users", method = RequestMethod.POST)
public ModelAndView createUser(@Valid @ModelAttribute User user, BindingResult result) {
if (result.hasErrors()) {
return new ModelAndView("userForm");
}
userService.createUser(user);
return new ModelAndView("redirect:/users");
}
}
11. 模型属性管理
- 作用:可以使用
@ModelAttribute
注解将对象添加到模型中,以便在视图中使用。
模型属性管理示例
@Controller
public class UserController {
@ModelAttribute("user")
public User createUserModel() {
return new User();
}
@RequestMapping("/userForm")
public String showUserForm() {
return "userForm";
}
}
12. 国际化(I18N)
- 作用:Spring MVC支持国际化,可以通过
LocaleResolver
和MessageSource
来实现多语言支持。
国际化配置示例
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="en_US" />
</bean>
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
国际化使用示例
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<title><fmt:message key="title" /></title>
</head>
<body>
<h1><fmt:message key="welcome.message" /></h1>
</body>
</html>
13. 文件上传
- 作用:Spring MVC支持文件上传功能,可以通过
MultipartFile
接口来处理上传的文件。 - 配置:需要配置
CommonsMultipartResolver
或StandardServletMultipartResolver
来处理文件上传。
文件上传配置示例
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10000000" /> <!-- 10MB -->
</bean>
文件上传控制器示例
@Controller
public class FileUploadController {
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public ModelAndView handleFileUpload(@RequestParam("file") MultipartFile file) {
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
// 处理文件保存逻辑
// ...
return new ModelAndView("success");
} catch (IOException e) {
return new ModelAndView("error");
}
} else {
return new ModelAndView("error");
}
}
}
14. RESTful API
- 作用:Spring MVC支持RESTful API的开发,可以通过
@RestController
和@RequestMapping
注解来定义RESTful接口。 - 返回JSON:可以使用
@ResponseBody
注解将返回对象转换为JSON格式。
RESTful API示例
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getUserById(id);
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.createUser(user);
}
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
return userService.updateUser(id, user);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
}
}
15. 安全性(Security)
- 作用:Spring Security可以与Spring MVC集成,提供安全保护,如认证和授权。
- 配置:需要配置Spring Security的相关Bean和过滤器。
Spring Security配置示例
<security:http auto-config="true">
<security:intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
<security:form-login login-page="/login" default-target-url="/home" authentication-failure-url="/login?error" />
<security:logout logout-success-url="/login?logout" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="user" password="password" authorities="ROLE_USER" />
<security:user name="admin" password="password" authorities="ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
16. 异步处理
- 作用:Spring MVC支持异步处理,可以通过
@Async
注解和DeferredResult
来实现异步请求处理。
异步处理示例
@Controller
public class AsyncController {
@Autowired
private AsyncService asyncService;
@RequestMapping("/async")
public DeferredResult<String> handleAsyncRequest() {
DeferredResult<String> deferredResult = new DeferredResult<>();
asyncService.handleAsync(deferredResult);
return deferredResult;
}
}
@Service
public class AsyncService {
@Async
public void handleAsync(DeferredResult<String> deferredResult) {
// 模拟耗时操作
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
deferredResult.setResult("Async processing completed");
}
}
17. 消息转换器(MessageConverter)
- 作用:Spring MVC使用消息转换器(MessageConverter)将请求体和响应体转换为Java对象或从Java对象转换为响应体。
- 常见类型:
MappingJackson2HttpMessageConverter
:用于JSON转换。StringHttpMessageConverter
:用于字符串转换。
消息转换器配置示例
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
<bean class="org.springframework.http.converter.StringHttpMessageConverter" />
</list>
</property>
</bean>
18. 模板引擎
- 作用:Spring MVC支持多种模板引擎,如Thymeleaf、FreeMarker等。
- 配置:需要配置相应的模板解析器和视图解析器。
Thymeleaf配置示例
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolvers">
<set>
<bean class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
</bean>
</set>
</property>
</bean>
<bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
</bean>
19. 拦截器链
- 作用:Spring MVC支持多个拦截器组成一个拦截器链,按顺序执行。
- 配置:可以在
dispatcher-servlet.xml
中配置多个拦截器。
拦截器链配置示例
<mvc:interceptors>
<bean class="com.example.interceptor.LoggingInterceptor" />
<bean class="com.example.interceptor.AuthorizationInterceptor" />
</mvc:interceptors>
20. 异常处理策略
- 作用:Spring MVC提供了多种异常处理策略,如全局异常处理、局部异常处理等。
- 配置:可以通过
@ControllerAdvice
和@ExceptionHandler
注解来定义异常处理策略。
全局异常处理示例
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFoundException(ResourceNotFoundException ex) {
ErrorResponse errorResponse = new ErrorResponse("NOT_FOUND", ex.getMessage());
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception ex) {
ErrorResponse errorResponse = new ErrorResponse("INTERNAL_ERROR", "An unexpected error occurred.");
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
21. 拦截器的生命周期
- 作用:拦截器有三个主要的生命周期方法:
preHandle
、postHandle
和afterCompletion
。 - 方法说明:
preHandle
:在请求处理之前调用,返回true
继续处理请求,返回false
中断请求处理。postHandle
:在请求处理之后、视图渲染之前调用。afterCompletion
:在请求处理完成之后调用,无论是否发生异常。
拦截器生命周期示例
@Component
public class LoggingInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("Pre-handle: " + request.getRequestURI());
return true; // 继续处理请求
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Post-handle: " + request.getRequestURI());
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("After completion: " + request.getRequestURI());
}
}
22. 跨域请求(CORS)
- 作用:Spring MVC支持跨域请求(CORS),可以在控制器或全局配置中启用CORS支持。
- 配置:可以通过
@CrossOrigin
注解或WebMvcConfigurer
接口来配置CORS。
跨域请求配置示例
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://example.com")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true);
}
}
控制器级别的CORS配置
@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = "http://example.com")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}
// 其他方法...
}
23. 自定义注解
- 作用:Spring MVC支持自定义注解,可以通过自定义注解来简化代码或实现特定的功能。
- 实现方式:定义自定义注解并使用
HandlerMethodArgumentResolver
来解析注解。
自定义注解示例
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUser {
}
自定义注解解析器
@Component
public class CurrentUserMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
private HttpServletRequest request;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterAnnotation(CurrentUser.class) != null;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
// 从请求中获取当前用户信息
User user = (User) request.getSession().getAttribute("user");
return user;
}
}
注册自定义注解解析器
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private CurrentUserMethodArgumentResolver currentUserMethodArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(currentUserMethodArgumentResolver);
}
}
使用自定义注解
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/current")
public User getCurrentUser(@CurrentUser User user) {
return user;
}
}
24. 缓存支持
- 作用:Spring MVC支持缓存,可以通过
@Cacheable
、@CacheEvict
和@CachePut
注解来实现缓存管理。 - 配置:需要配置缓存管理器(如
ConcurrentMapCacheManager
或RedisCacheManager
)。
缓存配置示例
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("users");
}
}
缓存注解示例
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
@Cacheable(value = "users", key = "#id")
public User getUserById(@PathVariable Long id) {
return userService.getUserById(id);
}
@PostMapping
@CachePut(value = "users", key = "#user.id")
public User createUser(@RequestBody User user) {
return userService.createUser(user);
}
@PutMapping("/{id}")
@CachePut(value = "users", key = "#id")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
return userService.updateUser(id, user);
}
@DeleteMapping("/{id}")
@CacheEvict(value = "users", key = "#id")
public void deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
}
}
25. AOP(面向切面编程)
- 作用:Spring MVC支持AOP,可以通过切面来实现横切关注点的分离,如日志记录、事务管理等。
- 实现方式:使用
@Aspect
注解定义切面,并使用@Before
、@After
、@Around
等注解定义通知。
切面示例
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.controller.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("Before method: " + joinPoint.getSignature().getName());
}
@After("execution(* com.example.controller.*.*(..))")
public void logAfter(JoinPoint joinPoint) {
System.out.println("After method: " + joinPoint.getSignature().getName());
}
@Around("execution(* com.example.service.*.*(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Around before method: " + joinPoint.getSignature().getName());
Object result = joinPoint.proceed();
System.out.println("Around after method: " + joinPoint.getSignature().getName());
return result;
}
}
26. 事务管理
- 作用:Spring MVC支持事务管理,可以通过
@Transactional
注解来管理事务。 - 配置:需要配置事务管理器(如
DataSourceTransactionManager
)。
事务管理配置示例
@Configuration
@EnableTransactionManagement
public class TransactionConfig {
@Autowired
private DataSource dataSource;
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource);
}
}
事务管理注解示例
@Service
@Transactional
public class UserService {
@Autowired
private UserRepository userRepository;
public User createUser(User user) {
return userRepository.save(user);
}
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}
27. 异步任务调度
- 作用:Spring MVC支持异步任务调度,可以通过
@Scheduled
注解来定期执行任务。 - 配置:需要配置任务调度器(如
TaskScheduler
)。
任务调度配置示例
@Configuration
@EnableScheduling
public class SchedulingConfig {
@Bean
public TaskScheduler taskScheduler() {
return new ThreadPoolTaskScheduler();
}
}
任务调度注解示例
@Component
public class ScheduledTasks {
@Scheduled(fixedRate = 5000)
public void scheduledTask() {
System.out.println("Scheduled task executed at " + new Date());
}
}
28. 配置类
- 作用:Spring MVC支持使用Java配置类来替代传统的XML配置文件。
- 配置:可以通过
@Configuration
注解定义配置类,并使用@ComponentScan
、@EnableWebMvc
等注解来启用Web MVC功能。
Java配置类示例
@Configuration
@ComponentScan(basePackages = "com.example")
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/views/", ".jsp");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggingInterceptor());
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/");
}
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.US);
return localeResolver;
}
}
总结
通过上述详细的步骤和示例,我们可以看到Spring MVC的工作流程涉及多个组件的协同工作。每个组件都有其特定的职责,确保请求能够被正确地处理和响应。