Spring MVC详解
Spring MVC简介
Spring MVC是Spring框架的一个模块,专门用于开发Web应用。它实现了模型-视图-控制器(MVC)设计模式,将业务逻辑、数据模型和视图渲染分离,使代码更加简洁、可维护。作为Java领域最流行的Web开发框架之一,Spring MVC提供了强大且灵活的功能支持。
Spring MVC工作流程

- 客户端(浏览器)发送请求到前端控制器
DispatcherServlet
DispatcherServlet
根据请求信息调用HandlerMapping
,解析请求对应的Handler
- 解析到对应的Handler(Controller控制器)后,由
HandlerAdapter
适配器处理
HandlerAdapter
执行Handler,返回ModelAndView
对象(包含模型数据和视图名)
ViewResolver
解析视图名,查找实际的View对象
- View使用模型数据渲染结果,通过
DispatcherServlet
返回给客户端
配置Spring MVC
XML配置方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <web-app> <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-app>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <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> <mvc:resources mapping="/resources/**" location="/resources/"/> </beans>
|
Java配置方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Configuration @EnableWebMvc @ComponentScan("com.example.controller") public class WebConfig 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; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[] { RootConfig.class }; }
@Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[] { WebConfig.class }; }
@Override protected String[] getServletMappings() { return new String[] { "/" }; } }
|
控制器(Controller)开发
基本Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Controller public class UserController { private final UserService userService; @Autowired public UserController(UserService userService) { this.userService = userService; } @RequestMapping(value = "/users", method = RequestMethod.GET) public String listUsers(Model model) { model.addAttribute("users", userService.getAllUsers()); return "users/list"; } @RequestMapping(value = "/users/{id}", method = RequestMethod.GET) public String getUserById(@PathVariable("id") Long id, Model model) { model.addAttribute("user", userService.getUserById(id)); return "users/detail"; } }
|
REST风格Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| @RestController @RequestMapping("/api/users") public class UserRestController { private final UserService userService; @Autowired public UserRestController(UserService userService) { this.userService = userService; } @GetMapping public List<User> getAllUsers() { return userService.getAllUsers(); } @GetMapping("/{id}") public User getUser(@PathVariable Long id) { return userService.getUserById(id); } @PostMapping @ResponseStatus(HttpStatus.CREATED) 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}") @ResponseStatus(HttpStatus.NO_CONTENT) public void deleteUser(@PathVariable Long id) { userService.deleteUser(id); } }
|
请求处理注解
注解 |
描述 |
@RequestMapping |
为控制器类或方法指定URL映射 |
@GetMapping |
处理HTTP GET请求 |
@PostMapping |
处理HTTP POST请求 |
@PutMapping |
处理HTTP PUT请求 |
@DeleteMapping |
处理HTTP DELETE请求 |
@PatchMapping |
处理HTTP PATCH请求 |
@PathVariable |
获取URL路径中的变量 |
@RequestParam |
获取请求参数 |
@RequestBody |
获取请求体并转换为Java对象 |
@RequestHeader |
获取请求头 |
@ModelAttribute |
添加属性到模型中或绑定表单参数 |
@SessionAttribute |
获取Session属性 |
@CookieValue |
获取Cookie值 |
@ResponseBody |
标记方法返回值直接写入响应体 |
@ResponseStatus |
定义HTTP响应状态码 |
表单处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| @Controller @RequestMapping("/register") public class RegisterController { private final UserService userService; @Autowired public RegisterController(UserService userService) { this.userService = userService; } @GetMapping public String showRegistrationForm(Model model) { model.addAttribute("user", new UserForm()); return "register"; } @PostMapping public String processRegistration(@Valid @ModelAttribute("user") UserForm userForm, BindingResult result) { if (result.hasErrors()) { return "register"; } userService.register(userForm); return "redirect:/login"; } }
|
文件上传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| @Controller public class FileUploadController { @PostMapping("/upload") public String handleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) { if (file.isEmpty()) { redirectAttributes.addFlashAttribute("message", "请选择要上传的文件"); return "redirect:/uploadForm"; }
try { String filename = file.getOriginalFilename(); byte[] bytes = file.getBytes(); Path path = Paths.get("uploads/" + filename); Files.write(path, bytes); redirectAttributes.addFlashAttribute("message", "成功上传文件 '" + filename + "'");
} catch (IOException e) { e.printStackTrace(); }
return "redirect:/uploadStatus"; } }
|
异常处理
@ExceptionHandler方法
1 2 3 4 5 6 7 8 9 10 11 12
| @Controller public class UserController { @ExceptionHandler(UserNotFoundException.class) public ModelAndView handleUserNotFoundException(UserNotFoundException ex) { ModelAndView mav = new ModelAndView("error/not-found"); mav.addObject("message", ex.getMessage()); return mav; } }
|
全局异常处理器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ModelAndView handleGlobalException(Exception ex) { ModelAndView mav = new ModelAndView("error/generic"); mav.addObject("message", ex.getMessage()); return mav; } @ExceptionHandler(UserNotFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public ModelAndView handleUserNotFoundException(UserNotFoundException ex) { ModelAndView mav = new ModelAndView("error/not-found"); mav.addObject("message", ex.getMessage()); return mav; } @ExceptionHandler(DataAccessException.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ModelAndView handleDataAccessException(DataAccessException ex) { ModelAndView mav = new ModelAndView("error/database"); mav.addObject("message", "数据库访问错误"); return mav; } }
|
拦截器(Interceptor)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class LoggingInterceptor implements HandlerInterceptor {
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("请求前调用: " + request.getRequestURI()); return true; }
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("控制器执行后调用: " + request.getRequestURI()); }
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("视图渲染后调用: " + request.getRequestURI()); } }
|
注册拦截器:
1 2 3 4 5 6 7 8 9 10 11
| @Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoggingInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/admin/**"); } }
|
总结
Spring MVC是一个强大的Web开发框架,提供了完整的MVC实现,使开发人员可以轻松构建可扩展的Web应用程序。它的特点包括:
- 清晰的角色分离,遵循MVC设计模式
- 灵活的配置选项(XML或Java配置)
- 强大的注解支持,减少样板代码
- 与Spring生态系统的无缝集成
- 丰富的功能支持:表单处理、文件上传、异常处理等
- REST API支持
随着微服务架构和前后端分离的兴起,Spring MVC被广泛用于构建RESTful服务,而Spring Boot更是简化了Spring MVC的配置,使开发者可以专注于业务逻辑的实现。