SSM从入门到实战:3.2 SpringMVC请求处理与控制器

👋 大家好,我是 阿问学长!专注于分享优质开源项目解析、毕业设计项目指导支持、幼小初高教辅资料推荐等,欢迎关注交流!🚀

SpringMVC请求处理与控制器

📖 本文概述

本文是SSM框架系列SpringMVC基础篇的第二篇,将深入探讨SpringMVC的请求处理机制和控制器的使用方法。通过详细的代码示例和最佳实践,帮助读者掌握Controller的各种用法和请求处理技巧。

🎯 学习目标

  • 深入理解SpringMVC的请求处理流程
  • 掌握Controller的各种注解和用法
  • 学会处理不同类型的HTTP请求
  • 了解参数绑定和数据传递机制
  • 掌握RESTful风格的URL设计

1. 请求处理流程详解

1.1 完整的请求处理流程

java 复制代码
/**
 * SpringMVC请求处理流程演示
 */
public class RequestProcessingFlow {
    
    /**
     * 详细的请求处理步骤
     */
    public void demonstrateFlow() {
        /*
         * 1. 客户端发送请求
         * GET /user/profile/123?tab=basic
         */
        
        /*
         * 2. DispatcherServlet接收请求
         * - 解析请求URL: /user/profile/123
         * - 解析请求方法: GET
         * - 解析请求参数: tab=basic
         */
        
        /*
         * 3. HandlerMapping查找处理器
         * - 根据URL模式匹配: /user/profile/{id}
         * - 找到对应的Controller方法: UserController.getProfile()
         * - 创建HandlerExecutionChain(包含拦截器)
         */
        
        /*
         * 4. HandlerAdapter调用处理器
         * - 参数解析: 将{id}绑定为123,将tab绑定为"basic"
         * - 调用Controller方法: getProfile(123, "basic")
         * - 处理返回值: 转换为ModelAndView
         */
        
        /*
         * 5. ViewResolver解析视图
         * - 根据视图名称查找视图: "user/profile"
         * - 创建View对象: JstlView
         */
        
        /*
         * 6. View渲染响应
         * - 将Model数据填充到视图中
         * - 生成HTML响应
         * - 返回给客户端
         */
    }
}

1.2 请求映射机制

java 复制代码
/**
 * 请求映射演示
 */
@Controller
@RequestMapping("/user")
public class UserController {
    
    /**
     * 基本的请求映射
     */
    @RequestMapping("/list")
    public String list() {
        return "user/list";
    }
    
    /**
     * 指定HTTP方法
     */
    @RequestMapping(value = "/create", method = RequestMethod.GET)
    public String showCreateForm() {
        return "user/create";
    }
    
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public String create() {
        return "redirect:/user/list";
    }
    
    /**
     * 使用组合注解(推荐)
     */
    @GetMapping("/edit/{id}")
    public String showEditForm(@PathVariable Long id) {
        return "user/edit";
    }
    
    @PostMapping("/edit")
    public String edit() {
        return "redirect:/user/list";
    }
    
    @PutMapping("/{id}")
    public String update(@PathVariable Long id) {
        return "redirect:/user/list";
    }
    
    @DeleteMapping("/{id}")
    public String delete(@PathVariable Long id) {
        return "redirect:/user/list";
    }
    
    /**
     * 多个URL映射
     */
    @GetMapping({"/profile", "/info", "/detail"})
    public String profile() {
        return "user/profile";
    }
    
    /**
     * 带参数的映射
     */
    @GetMapping(value = "/search", params = "type=advanced")
    public String advancedSearch() {
        return "user/advanced-search";
    }
    
    @GetMapping(value = "/search", params = "!type")
    public String basicSearch() {
        return "user/basic-search";
    }
    
    /**
     * 带请求头的映射
     */
    @GetMapping(value = "/api/users", headers = "Accept=application/json")
    @ResponseBody
    public List<User> getUsersJson() {
        return userService.findAll();
    }
    
    @GetMapping(value = "/api/users", headers = "Accept=application/xml")
    @ResponseBody
    public List<User> getUsersXml() {
        return userService.findAll();
    }
    
    /**
     * 内容类型映射
     */
    @PostMapping(value = "/api/users", consumes = "application/json")
    @ResponseBody
    public User createUserFromJson(@RequestBody User user) {
        return userService.save(user);
    }
    
    @PostMapping(value = "/api/users", consumes = "application/xml")
    @ResponseBody
    public User createUserFromXml(@RequestBody User user) {
        return userService.save(user);
    }
}

2. 参数绑定详解

2.1 各种参数绑定方式

java 复制代码
/**
 * 参数绑定演示
 */
@Controller
@RequestMapping("/demo")
public class ParameterBindingController {
    
    /**
     * 1. 基本类型参数绑定
     */
    @GetMapping("/basic")
    public String basicParams(
            String name,           // 自动绑定name参数
            int age,              // 自动类型转换
            boolean active,       // 布尔类型转换
            Date birthday,        // 日期类型转换(需要配置)
            Model model) {
        
        model.addAttribute("name", name);
        model.addAttribute("age", age);
        model.addAttribute("active", active);
        model.addAttribute("birthday", birthday);
        
        return "demo/basic";
    }
    
    /**
     * 2. @RequestParam注解
     */
    @GetMapping("/request-param")
    public String requestParam(
            @RequestParam("username") String name,                    // 指定参数名
            @RequestParam(value = "age", defaultValue = "18") int age, // 默认值
            @RequestParam(required = false) String email,             // 可选参数
            @RequestParam List<String> hobbies,                       // 数组/集合参数
            Model model) {
        
        model.addAttribute("name", name);
        model.addAttribute("age", age);
        model.addAttribute("email", email);
        model.addAttribute("hobbies", hobbies);
        
        return "demo/request-param";
    }
    
    /**
     * 3. @PathVariable路径变量
     */
    @GetMapping("/user/{id}/posts/{postId}")
    public String pathVariable(
            @PathVariable Long id,                           // 路径变量
            @PathVariable("postId") Long pid,               // 指定变量名
            @PathVariable Map<String, String> pathVars,     // 所有路径变量
            Model model) {
        
        model.addAttribute("userId", id);
        model.addAttribute("postId", pid);
        model.addAttribute("allPathVars", pathVars);
        
        return "demo/path-variable";
    }
    
    /**
     * 4. @RequestHeader请求头
     */
    @GetMapping("/headers")
    public String requestHeader(
            @RequestHeader("User-Agent") String userAgent,           // 指定请求头
            @RequestHeader(value = "Accept", required = false) String accept, // 可选请求头
            @RequestHeader Map<String, String> headers,              // 所有请求头
            Model model) {
        
        model.addAttribute("userAgent", userAgent);
        model.addAttribute("accept", accept);
        model.addAttribute("headers", headers);
        
        return "demo/headers";
    }
    
    /**
     * 5. @CookieValue Cookie值
     */
    @GetMapping("/cookies")
    public String cookieValue(
            @CookieValue(value = "JSESSIONID", required = false) String sessionId,
            @CookieValue(value = "theme", defaultValue = "default") String theme,
            Model model) {
        
        model.addAttribute("sessionId", sessionId);
        model.addAttribute("theme", theme);
        
        return "demo/cookies";
    }
    
    /**
     * 6. @ModelAttribute对象绑定
     */
    @PostMapping("/user")
    public String modelAttribute(@ModelAttribute User user, Model model) {
        // Spring自动将请求参数绑定到User对象
        model.addAttribute("user", user);
        return "demo/model-attribute";
    }
    
    /**
     * 7. @RequestBody JSON/XML绑定
     */
    @PostMapping("/api/user")
    @ResponseBody
    public User requestBody(@RequestBody User user) {
        // 将请求体中的JSON/XML转换为User对象
        return userService.save(user);
    }
    
    /**
     * 8. HttpServletRequest和HttpServletResponse
     */
    @GetMapping("/servlet")
    public String servletApi(
            HttpServletRequest request,
            HttpServletResponse response,
            HttpSession session,
            Model model) {
        
        String remoteAddr = request.getRemoteAddr();
        String sessionId = session.getId();
        
        model.addAttribute("remoteAddr", remoteAddr);
        model.addAttribute("sessionId", sessionId);
        
        return "demo/servlet";
    }
}

2.2 复杂对象绑定

java 复制代码
/**
 * 复杂对象绑定演示
 */
@Controller
@RequestMapping("/complex")
public class ComplexBindingController {
    
    /**
     * 嵌套对象绑定
     */
    @PostMapping("/nested")
    public String nestedObject(@ModelAttribute UserForm userForm, Model model) {
        /*
         * 请求参数示例:
         * username=john
         * email=john@example.com
         * profile.realName=John Doe
         * profile.phone=1234567890
         * profile.address.city=Beijing
         * profile.address.street=Chaoyang Road
         */
        
        model.addAttribute("userForm", userForm);
        return "complex/nested";
    }
    
    /**
     * 集合对象绑定
     */
    @PostMapping("/collection")
    public String collectionBinding(@ModelAttribute UserListForm form, Model model) {
        /*
         * 请求参数示例:
         * users[0].username=user1
         * users[0].email=user1@example.com
         * users[1].username=user2
         * users[1].email=user2@example.com
         */
        
        model.addAttribute("form", form);
        return "complex/collection";
    }
    
    /**
     * Map对象绑定
     */
    @PostMapping("/map")
    public String mapBinding(@RequestParam Map<String, String> params, Model model) {
        model.addAttribute("params", params);
        return "complex/map";
    }
}

/**
 * 表单对象定义
 */
public class UserForm {
    private String username;
    private String email;
    private UserProfile profile;
    
    // getter/setter...
}

public class UserProfile {
    private String realName;
    private String phone;
    private Address address;
    
    // getter/setter...
}

public class Address {
    private String city;
    private String street;
    
    // getter/setter...
}

public class UserListForm {
    private List<User> users;
    
    // getter/setter...
}

3. 数据传递机制

3.1 Model数据传递

java 复制代码
/**
 * Model数据传递演示
 */
@Controller
@RequestMapping("/data")
public class DataTransferController {
    
    /**
     * 使用Model传递数据
     */
    @GetMapping("/model")
    public String useModel(Model model) {
        model.addAttribute("message", "Hello from Model");
        model.addAttribute("user", new User("John", "john@example.com"));
        model.addAttribute("users", userService.findAll());
        
        return "data/model";
    }
    
    /**
     * 使用ModelMap传递数据
     */
    @GetMapping("/model-map")
    public String useModelMap(ModelMap modelMap) {
        modelMap.addAttribute("message", "Hello from ModelMap");
        modelMap.put("timestamp", new Date());
        
        return "data/model-map";
    }
    
    /**
     * 使用ModelAndView传递数据
     */
    @GetMapping("/model-and-view")
    public ModelAndView useModelAndView() {
        ModelAndView mav = new ModelAndView("data/model-and-view");
        mav.addObject("message", "Hello from ModelAndView");
        mav.addObject("data", getData());
        
        return mav;
    }
    
    /**
     * 使用@ModelAttribute预处理数据
     */
    @ModelAttribute("commonData")
    public Map<String, Object> commonData() {
        Map<String, Object> data = new HashMap<>();
        data.put("appName", "SSM Demo");
        data.put("version", "1.0.0");
        data.put("currentTime", new Date());
        
        return data;
    }
    
    @GetMapping("/common")
    public String useCommonData(Model model) {
        // commonData会自动添加到所有请求的Model中
        model.addAttribute("pageTitle", "Common Data Demo");
        
        return "data/common";
    }
    
    /**
     * 使用Session存储数据
     */
    @GetMapping("/session")
    public String useSession(HttpSession session, Model model) {
        session.setAttribute("sessionData", "Data stored in session");
        
        Object data = session.getAttribute("sessionData");
        model.addAttribute("sessionData", data);
        
        return "data/session";
    }
    
    /**
     * 使用@SessionAttributes
     */
    @Controller
    @SessionAttributes({"user", "preferences"})
    public static class SessionAttributesController {
        
        @GetMapping("/session-attrs")
        public String sessionAttributes(Model model) {
            model.addAttribute("user", new User("Session User", "session@example.com"));
            model.addAttribute("preferences", getPreferences());
            
            return "data/session-attrs";
        }
        
        @GetMapping("/use-session-attrs")
        public String useSessionAttributes(@ModelAttribute("user") User user, Model model) {
            // user对象从Session中获取
            model.addAttribute("message", "Hello " + user.getUsername());
            
            return "data/use-session-attrs";
        }
    }
}

3.2 重定向和转发

java 复制代码
/**
 * 重定向和转发演示
 */
@Controller
@RequestMapping("/redirect")
public class RedirectController {
    
    /**
     * 重定向
     */
    @PostMapping("/save")
    public String save(@ModelAttribute User user, RedirectAttributes redirectAttributes) {
        try {
            userService.save(user);
            
            // 重定向时传递成功消息
            redirectAttributes.addFlashAttribute("message", "用户保存成功");
            redirectAttributes.addFlashAttribute("messageType", "success");
            
            // 重定向到列表页面
            return "redirect:/user/list";
            
        } catch (Exception e) {
            redirectAttributes.addFlashAttribute("message", "保存失败:" + e.getMessage());
            redirectAttributes.addFlashAttribute("messageType", "error");
            
            // 重定向回表单页面
            return "redirect:/user/create";
        }
    }
    
    /**
     * 带参数的重定向
     */
    @GetMapping("/with-params")
    public String redirectWithParams(RedirectAttributes redirectAttributes) {
        // 添加URL参数
        redirectAttributes.addAttribute("id", 123);
        redirectAttributes.addAttribute("tab", "profile");
        
        // 添加Flash属性(不会出现在URL中)
        redirectAttributes.addFlashAttribute("message", "重定向成功");
        
        // 重定向到: /user/detail?id=123&tab=profile
        return "redirect:/user/detail";
    }
    
    /**
     * 转发
     */
    @GetMapping("/forward")
    public String forward(Model model) {
        model.addAttribute("message", "这是转发的数据");
        
        // 转发到另一个Controller方法
        return "forward:/data/model";
    }
    
    /**
     * 条件重定向
     */
    @PostMapping("/conditional")
    public String conditionalRedirect(@RequestParam String action, 
                                    @ModelAttribute User user,
                                    RedirectAttributes redirectAttributes) {
        
        switch (action) {
            case "save":
                userService.save(user);
                redirectAttributes.addFlashAttribute("message", "保存成功");
                return "redirect:/user/list";
                
            case "saveAndContinue":
                User savedUser = userService.save(user);
                redirectAttributes.addFlashAttribute("message", "保存成功,继续编辑");
                return "redirect:/user/edit/" + savedUser.getId();
                
            case "cancel":
                return "redirect:/user/list";
                
            default:
                return "redirect:/user/create";
        }
    }
}

4. RESTful风格设计

4.1 RESTful Controller设计

java 复制代码
/**
 * RESTful风格的用户管理Controller
 */
@RestController
@RequestMapping("/api/users")
public class UserRestController {
    
    @Autowired
    private UserService userService;
    
    /**
     * GET /api/users - 获取用户列表
     */
    @GetMapping
    public ResponseEntity<List<User>> getUsers(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(required = false) String keyword) {
        
        List<User> users = userService.findUsers(page, size, keyword);
        return ResponseEntity.ok(users);
    }
    
    /**
     * GET /api/users/{id} - 获取指定用户
     */
    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        User user = userService.findById(id);
        if (user == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(user);
    }
    
    /**
     * POST /api/users - 创建用户
     */
    @PostMapping
    public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
        User createdUser = userService.save(user);
        
        URI location = ServletUriComponentsBuilder
                .fromCurrentRequest()
                .path("/{id}")
                .buildAndExpand(createdUser.getId())
                .toUri();
        
        return ResponseEntity.created(location).body(createdUser);
    }
    
    /**
     * PUT /api/users/{id} - 更新用户
     */
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, 
                                         @Valid @RequestBody User user) {
        if (!userService.exists(id)) {
            return ResponseEntity.notFound().build();
        }
        
        user.setId(id);
        User updatedUser = userService.update(user);
        return ResponseEntity.ok(updatedUser);
    }
    
    /**
     * PATCH /api/users/{id} - 部分更新用户
     */
    @PatchMapping("/{id}")
    public ResponseEntity<User> patchUser(@PathVariable Long id, 
                                        @RequestBody Map<String, Object> updates) {
        if (!userService.exists(id)) {
            return ResponseEntity.notFound().build();
        }
        
        User updatedUser = userService.partialUpdate(id, updates);
        return ResponseEntity.ok(updatedUser);
    }
    
    /**
     * DELETE /api/users/{id} - 删除用户
     */
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        if (!userService.exists(id)) {
            return ResponseEntity.notFound().build();
        }
        
        userService.deleteById(id);
        return ResponseEntity.noContent().build();
    }
    
    /**
     * GET /api/users/{id}/roles - 获取用户角色
     */
    @GetMapping("/{id}/roles")
    public ResponseEntity<List<Role>> getUserRoles(@PathVariable Long id) {
        if (!userService.exists(id)) {
            return ResponseEntity.notFound().build();
        }
        
        List<Role> roles = userService.getUserRoles(id);
        return ResponseEntity.ok(roles);
    }
    
    /**
     * POST /api/users/{id}/roles - 为用户添加角色
     */
    @PostMapping("/{id}/roles")
    public ResponseEntity<Void> addUserRole(@PathVariable Long id, 
                                           @RequestBody Role role) {
        if (!userService.exists(id)) {
            return ResponseEntity.notFound().build();
        }
        
        userService.addRole(id, role.getId());
        return ResponseEntity.ok().build();
    }
}

4.2 统一响应格式

java 复制代码
/**
 * 统一响应格式
 */
public class ApiResponse<T> {
    private int code;
    private String message;
    private T data;
    private long timestamp;
    
    public static <T> ApiResponse<T> success(T data) {
        ApiResponse<T> response = new ApiResponse<>();
        response.setCode(200);
        response.setMessage("success");
        response.setData(data);
        response.setTimestamp(System.currentTimeMillis());
        return response;
    }
    
    public static <T> ApiResponse<T> error(int code, String message) {
        ApiResponse<T> response = new ApiResponse<>();
        response.setCode(code);
        response.setMessage(message);
        response.setTimestamp(System.currentTimeMillis());
        return response;
    }
    
    // getter/setter...
}

/**
 * 使用统一响应格式的Controller
 */
@RestController
@RequestMapping("/api/v2/users")
public class UserApiController {
    
    @GetMapping
    public ApiResponse<List<User>> getUsers() {
        List<User> users = userService.findAll();
        return ApiResponse.success(users);
    }
    
    @GetMapping("/{id}")
    public ApiResponse<User> getUser(@PathVariable Long id) {
        User user = userService.findById(id);
        if (user == null) {
            return ApiResponse.error(404, "用户不存在");
        }
        return ApiResponse.success(user);
    }
    
    @PostMapping
    public ApiResponse<User> createUser(@Valid @RequestBody User user) {
        try {
            User createdUser = userService.save(user);
            return ApiResponse.success(createdUser);
        } catch (Exception e) {
            return ApiResponse.error(500, "创建用户失败:" + e.getMessage());
        }
    }
}

5. 小结

本文深入介绍了SpringMVC的请求处理和控制器使用:

  1. 请求处理流程:从请求接收到响应返回的完整过程
  2. 请求映射:@RequestMapping及其组合注解的使用
  3. 参数绑定:各种参数绑定方式和复杂对象绑定
  4. 数据传递:Model、Session、重定向等数据传递机制
  5. RESTful设计:符合REST规范的API设计

掌握SpringMVC请求处理的关键点:

  • 理解请求映射的各种配置方式
  • 熟练使用各种参数绑定注解
  • 正确选择数据传递方式
  • 设计符合RESTful规范的API
  • 处理好重定向和转发的使用场景

🔗 下一篇预告

下一篇文章将介绍SpringMVC数据绑定与验证,学习如何进行数据验证和类型转换。


相关文章:

相关推荐
中工钱袋38 分钟前
java后端如何实现下载功能
spring·maven
似水流年流不尽思念1 小时前
Spring Bean有哪些生命周期回调方法?有哪几种实现方式?
后端·spring·面试
猿java5 小时前
在 Spring中,用id和name命名Bean,究竟有什么区别?
后端·spring·架构
CPU NULL5 小时前
Spring拦截器中@Resource注入为null的问题
java·人工智能·后端·spring
你我约定有三1 天前
RabbitMQ--消费端异常处理与 Spring Retry
spring·rabbitmq·java-rabbitmq
shuair1 天前
07 - spring security基于数据库的账号密码
spring·spring security
Java水解1 天前
深度剖析【Spring】事务:万字详解,彻底掌握传播机制与事务原理
后端·spring
杨杨杨大侠1 天前
第3篇:配置管理的艺术 - 让框架更灵活
java·spring·log4j
Java码农田1 天前
springmvc源码分析全体流程图
spring·源码