👋 大家好,我是 阿问学长
!专注于分享优质开源项目
解析、毕业设计项目指导
支持、幼小初高
的教辅资料
推荐等,欢迎关注交流!🚀
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的请求处理和控制器使用:
- 请求处理流程:从请求接收到响应返回的完整过程
- 请求映射:@RequestMapping及其组合注解的使用
- 参数绑定:各种参数绑定方式和复杂对象绑定
- 数据传递:Model、Session、重定向等数据传递机制
- RESTful设计:符合REST规范的API设计
掌握SpringMVC请求处理的关键点:
- 理解请求映射的各种配置方式
- 熟练使用各种参数绑定注解
- 正确选择数据传递方式
- 设计符合RESTful规范的API
- 处理好重定向和转发的使用场景
🔗 下一篇预告
下一篇文章将介绍SpringMVC数据绑定与验证,学习如何进行数据验证和类型转换。
相关文章: