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 {@Autowiredprivate 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 {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("Pre-handle: " + request.getRequestURI());return true; // 继续处理请求}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("Post-handle: " + request.getRequestURI());}@Overridepublic 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 {@Autowiredprivate 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 {@Autowiredprivate UserService userService;@GetMappingpublic List<User> getAllUsers() {return userService.getAllUsers();}@GetMapping("/{id}")public User getUserById(@PathVariable Long id) {return userService.getUserById(id);}@PostMappingpublic 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 {@Autowiredprivate AsyncService asyncService;@RequestMapping("/async")public DeferredResult<String> handleAsyncRequest() {DeferredResult<String> deferredResult = new DeferredResult<>();asyncService.handleAsync(deferredResult);return deferredResult;}
}@Service
public class AsyncService {@Asyncpublic 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 {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("Pre-handle: " + request.getRequestURI());return true; // 继续处理请求}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("Post-handle: " + request.getRequestURI());}@Overridepublic 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 {@Overridepublic 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 {@Autowiredprivate UserService userService;@GetMappingpublic 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 {@Autowiredprivate HttpServletRequest request;@Overridepublic boolean supportsParameter(MethodParameter parameter) {return parameter.getParameterAnnotation(CurrentUser.class) != null;}@Overridepublic 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 {@Autowiredprivate CurrentUserMethodArgumentResolver currentUserMethodArgumentResolver;@Overridepublic 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 {@Beanpublic CacheManager cacheManager() {return new ConcurrentMapCacheManager("users");}
}
缓存注解示例
@RestController
@RequestMapping("/api/users")
public class UserController {@Autowiredprivate 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 {@Autowiredprivate DataSource dataSource;@Beanpublic PlatformTransactionManager transactionManager() {return new DataSourceTransactionManager(dataSource);}
}
事务管理注解示例
@Service
@Transactional
public class UserService {@Autowiredprivate 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 {@Beanpublic 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 {@Overridepublic void configureViewResolvers(ViewResolverRegistry registry) {registry.jsp("/WEB-INF/views/", ".jsp");}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoggingInterceptor());}@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/");}@Beanpublic MessageSource messageSource() {ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();messageSource.setBasename("classpath:messages");messageSource.setDefaultEncoding("UTF-8");return messageSource;}@Beanpublic LocaleResolver localeResolver() {SessionLocaleResolver localeResolver = new SessionLocaleResolver();localeResolver.setDefaultLocale(Locale.US);return localeResolver;}
}
总结
通过上述详细的步骤和示例,我们可以看到Spring MVC的工作流程涉及多个组件的协同工作。每个组件都有其特定的职责,确保请求能够被正确地处理和响应。