Spring MVC核心技术:从请求映射到异常处理

发布于:2025-03-26 ⋅ 阅读:(17) ⋅ 点赞:(0)

目录

一、@RequestMapping注解深度解析

1.1 注解的层级映射机制

1.2 请求参数绑定技巧

二、结果跳转的三重境界

2.1 ModelAndView方式

2.2 Servlet API直接操作

2.3 SpringMVC语义化跳转

三、文件上传实战指南

3.1 配置上传解析器

3.2 文件处理核心代码

3.3 文件下载实现

四、异常处理最佳实践

4.1 局部异常处理

4.2 全局异常处理器

五、性能优化关键点

六、常见问题排查手册

七、最佳实践总结

一、@RequestMapping注解深度解析

RequestMapping注解的作用是建立请求URL和处理方法之间的对应关系

RequestMapping注解可以作用在方法和类上

1. 作用在类上:第一级的访问目录

2. 作用在方法上:第二级的访问目录

3. 细节:路径可以不编写 / 表示应用的根目录开始

1.1 注解的层级映射机制

多级路径配置示例

@Controller
@RequestMapping("/user")  // 一级路径
public class UserController {
    
    @GetMapping("/profile") // 二级路径 -> /user/profile
    public String showProfile() {
        return "user-profile";
    }
}

核心属性详解

属性 说明 使用场景
value/path 定义请求路径 基础路径映射
method 限制HTTP方法类型 RESTful接口设计
params 要求必须包含指定参数 条件性路由处理
headers 校验请求头信息 接口版本控制

1.2 请求参数绑定技巧

(1). 绑定机制

1. 表单提交的数据都是k=v格式的 username=haha&password=123

2. SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的

3. 要求:提交表单的name和参数的名称是相同的

(2). 支持的数据类型

1. 基本数据类型和字符串类型

2. 实体类型(JavaBean)

3. 集合数据类型(List、map集合等)

基本数据类型和字符串类型

1. 提交表单的name和参数的名称是相同的

2. 区分大小写

实体类型(JavaBean)

1. 提交表单的name和JavaBean中的属性名称需要一致

2. 如果一个JavaBean类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性 例如:address.name

给集合属性数据封装

1. JSP页面编写方式:list[0].属性

基础类型绑定

@PostMapping("/register")
public String register(
    @RequestParam("uname") String username,
    @RequestParam(value = "age", defaultValue = "18") int userAge) {
    // 业务逻辑
}

复杂对象绑定

<!-- 表单结构 -->
<input name="address.province">
<input name="address.city">

集合类型处理

public class OrderForm {
    private List<OrderItem> items;
}

// 前端传参格式
items[0].productId=1001&items[0].quantity=2

二、结果跳转的三重境界

2.1 ModelAndView方式

@RequestMapping("/detail")
public ModelAndView productDetail() {
    ModelAndView mv = new ModelAndView();
    mv.addObject("product", productService.getById(1001));
    mv.setViewName("product-detail");
    return mv;
}

2.2 Servlet API直接操作

@RequestMapping("/redirect")
public void directRedirect(HttpServletResponse response) throws IOException {
    response.sendRedirect("/home");
}

@RequestMapping("/forward")
public void directForward(HttpServletRequest request, 
                         HttpServletResponse response) throws ServletException, IOException {
    request.getRequestDispatcher("/WEB-INF/views/error.jsp").forward(request, response);
}

2.3 SpringMVC语义化跳转

// 内部转发
@RequestMapping("/internal")
public String internalForward() {
    return "forward:/api/data";
}

// 外部重定向
@RequestMapping("/external")
public String externalRedirect() {
    return "redirect:https://www.example.com";
}

三、文件上传实战指南

3.1 配置上传解析器

<bean id="multipartResolver" 
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="10485760"/> <!-- 10MB限制 -->
    <property name="defaultEncoding" value="UTF-8"/>
</bean>

3.2 文件处理核心代码

@PostMapping("/upload")
public String handleFileUpload(
    @RequestParam("file") MultipartFile file,
    HttpServletRequest request) throws IOException {

    String uploadPath = request.getServletContext().getRealPath("/uploads");
    File dest = new File(uploadPath + File.separator + file.getOriginalFilename());
    file.transferTo(dest);
    return "upload-success";
}

3.3 文件下载实现

@GetMapping("/download")
public void downloadFile(
    @RequestParam String filename,
    HttpServletResponse response) throws IOException {

    File file = new File("/storage/" + filename);
    response.setContentType("application/octet-stream");
    response.setHeader("Content-Disposition", 
                      "attachment; filename=\"" + filename + "\"");
    Files.copy(file.toPath(), response.getOutputStream());
}

四、异常处理最佳实践

4.1 局部异常处理

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(SQLException.class)
    public ModelAndView handleDatabaseError(SQLException ex) {
        ModelAndView mav = new ModelAndView("error-db");
        mav.addObject("errorMsg", "数据库操作异常:" + ex.getMessage());
        return mav;
    }
}

4.2 全局异常处理器

@Component
public class CustomExceptionResolver implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler,
            Exception ex) {
        
        ModelAndView mav = new ModelAndView("system-error");
        if(ex instanceof BusinessException) {
            mav.addObject("errorCode", ((BusinessException) ex).getErrorCode());
        }
        return mav;
    }
}

五、性能优化关键点

  1. 静态资源配置

<mvc:resources mapping="/static/**" location="/static/" cache-period="31536000"/>

2.异步请求处理

@Async
@GetMapping("/async-data")
public CompletableFuture<Data> fetchAsyncData() {
    return CompletableFuture.supplyAsync(() -> dataService.getComplexData());
}

3.缓存策略应用: 

    @Cacheable(value = "products", key = "#id")
    @GetMapping("/product/{id}")
    public Product getProduct(@PathVariable Long id) {
        return productRepository.findById(id);
    }

    六、常见问题排查手册

    问题1:参数绑定失败
    ✅ 解决方案:

    • 检查POJO字段命名一致性

    • 使用@DateTimeFormat处理日期格式

    • 验证复杂类型的默认构造函数

    问题2:文件上传大小限制
    ✅ 检查项:

    • 确认multipartResolver配置

    • 检查服务器容器配置(如Tomcat的maxSwallowSize)

    问题3:中文乱码问题
    ✅ 处理方案:

    <!-- web.xml配置 -->
    <filter>
        <filter-name>encodingFilter</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>
    </filter>

    七、最佳实践总结

    1. 接口设计原则

      • 遵循RESTful风格

      • 使用合适的HTTP状态码

      • 保持URL语义清晰

    2. 安全建议

      • 文件上传时验证文件类型

      • 对下载文件进行权限校验

      • 使用HTTPS传输敏感数据

    3. 性能优化

      • 启用Gzip压缩

      • 使用CDN分发静态资源

      • 合理设置缓存策略