Spring+SpringMVC+MyBatis深入学习及搭建(十一)——SpringMVC架构

在Java企业级应用开发领域,SpringMVC作为Spring框架的核心模块,提供了强大而灵活的Web层解决方案。本文将深入剖析SpringMVC的架构设计、核心组件及请求处理流程,结合最佳实践和代码示例,帮助您全面掌握其内部工作机制。

目录#

  1. SpringMVC概述
  2. 核心组件详解
    • DispatcherServlet
    • HandlerMapping
    • HandlerAdapter
    • ViewResolver
  3. 请求处理全流程
  4. 配置方式对比
    • XML配置
    • Java Config配置
  5. 核心实践与最佳实践
    • RESTful支持
    • 全局异常处理
    • 拦截器应用
    • 参数验证
  6. 性能优化建议
  7. 完整示例代码
  8. 总结
  9. 参考文献

1. SpringMVC概述#

SpringMVC是基于前端控制器模式设计的Web框架,其核心设计理念围绕DispatcherServlet展开。采用松耦合的设计架构,通过可插拔组件实现高度可扩展性,完美支持RESTful风格开发。

核心优势

  • 清晰的职责分离
  • 灵活的配置选项
  • 强大的注解支持
  • 无缝集成Spring生态系统

2. 核心组件详解#

2.1 DispatcherServlet(前端控制器)#

作为统一入口点,承担请求分发和响应合成的核心职责。在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-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

2.2 HandlerMapping#

实现请求URL到Controller的映射策略:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // 直接映射视图
        registry.addViewController("/home").setViewName("home");
    }
}

2.3 HandlerAdapter#

适配执行处理器方法,支持多种控制器类型:

  • @Controller注解类
  • 传统Controller接口实现
  • HttpRequestHandler等

2.4 ViewResolver#

视图解析策略,支持多种视图技术:

@Bean
public ViewResolver viewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setSuffix(".jsp");
    return resolver;
}

3. 请求处理全流程#

sequenceDiagram
    participant Client
    participant DispatcherServlet
    participant HandlerMapping
    participant HandlerAdapter
    participant Controller
    participant ViewResolver
 
    Client->>DispatcherServlet: HTTP Request
    DispatcherServlet->>HandlerMapping: 查询Handler
    HandlerMapping-->>DispatcherServlet: 返回Handler
    DispatcherServlet->>HandlerAdapter: 调用Handler
    HandlerAdapter->>Controller: 执行对应方法
    Controller-->>HandlerAdapter: 返回ModelAndView
    HandlerAdapter-->>DispatcherServlet: 返回结果
    DispatcherServlet->>ViewResolver: 解析视图
    ViewResolver-->>DispatcherServlet: 返回View对象
    DispatcherServlet->>View: 渲染视图
    View-->>DispatcherServlet: 返回渲染结果
    DispatcherServlet->>Client: HTTP Response

4. 配置方式对比#

XML配置#

<!-- spring-mvc.xml -->
<beans>
    <context:component-scan base-package="com.example.controller"/>
    <mvc:annotation-driven/>
 
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

Java Config配置(推荐)#

@Configuration
@EnableWebMvc
@ComponentScan("com.example.controller")
public class WebMvcConfig implements WebMvcConfigurer {
 
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
}

5. 核心实践与最佳实践#

5.1 RESTful支持#

@RestController
@RequestMapping("/api/users")
public class UserController {
 
    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        // ...
        return ResponseEntity.ok(user);
    }
 
    @PostMapping
    public ResponseEntity<Void> createUser(@Valid @RequestBody User user) {
        // ...
        return ResponseEntity.created(URI.create("/users/" + id)).build();
    }
}

5.2 全局异常处理#

@ControllerAdvice
public class GlobalExceptionHandler {
 
    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleUserNotFound(
        UserNotFoundException ex) {
        
        ErrorResponse error = new ErrorResponse(
            "USER_NOT_FOUND", 
            ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }
}

5.3 拦截器应用#

public class LoggingInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                             HttpServletResponse response, 
                             Object handler) {
        logger.info("Request URL: {}", request.getRequestURL());
        return true;
    }
}
 
// 配置
@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LoggingInterceptor());
}

5.4 参数验证#

@PostMapping("/register")
public ResponseEntity<?> registerUser(
    @Valid @RequestBody UserRegistrationDto dto,
    BindingResult bindingResult) {
 
    if (bindingResult.hasErrors()) {
        Map<String, String> errors = bindingResult.getFieldErrors()
            .stream()
            .collect(Collectors.toMap(
                FieldError::getField,
                FieldError::getDefaultMessage));
        
        return ResponseEntity.badRequest().body(errors);
    }
    // 处理业务
}

6. 性能优化建议#

  1. 合理使用拦截器:避免在拦截器中执行耗时操作
  2. 视图解析优化
    • 开启模板缓存(Thymeleaf/FreeMarker)
    • 避免不必要的视图跳转
  3. 合理设置文件上传限制
    @Bean
    public MultipartResolver multipartResolver() {
        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
        resolver.setMaxUploadSize(5242880); // 5MB
        return resolver;
    }
  4. 使用异步处理
    @GetMapping("/async")
    @ResponseBody
    public Callable<String> asyncProcessing() {
        return () -> {
            Thread.sleep(3000);
            return "Async result";
        };
    }

7. 完整示例代码#

@Controller
@RequestMapping("/products")
public class ProductController {
 
    @GetMapping
    public String listProducts(Model model) {
        model.addAttribute("products", productService.getAllProducts());
        return "product/list";
    }
 
    @PostMapping("/{id}/purchase")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> purchaseProduct(
        @PathVariable Long id, 
        @RequestParam int quantity) {
        
        if (quantity <= 0) {
            throw new InvalidQuantityException();
        }
        
        productService.purchase(id, quantity);
        Map<String, Object> response = new HashMap<>();
        response.put("success", true);
        response.put("message", "Purchase successful");
        return ResponseEntity.ok(response);
    }
}

8. 总结#

通过对SpringMVC架构的深度剖析,我们应该掌握:

  • 核心组件:理解DispatcherServlet、HandlerMapping等核心组件的职责
  • 请求流程:熟悉从请求到响应的完整生命周期
  • 现代配置:掌握基于Java Config的现代配置方式
  • 最佳实践:运用RESTful设计、全局异常处理等关键技能
  • 性能优化:了解常见的性能优化点及解决方案

SpringMVC通过其优雅的设计和丰富的功能,为构建企业级Web应用提供了强大基础。


参考文献#

  1. Spring Framework 官方文档 - Web MVC
  2. 《Spring in Action》第五版 - Craig Walls
  3. Spring MVC @RequestMapping注解指南
  4. Spring Boot参考指南

作者:技术团队
最后更新日期:2023年11月