Model
或 ModelAndView
对象传递到 View 层。SpringMVC 中常用的注解可以分为以下几类,分别对应不同的功能和场景:
@Controller
public class MyController {
@RequestMapping("/hello")
public String hello() {
return "hello"; // 视图名
}
}
@Controller + @ResponseBody
,用于返回 JSON 或 XML 数据,而不是视图。@RestController
public class ApiController {
@GetMapping("/api/data")
public String getData() {
return "This is JSON response.";
}
}
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/profile")
public String userProfile() {
return "profile";
}
}
@RequestMapping(method = RequestMethod.GET/POST/PUT/DELETE/PATCH)
。@GetMapping("/getUser")
public String getUser() {
return "getUser";
}
在 SpringMVC 中,HTTP 请求中的参数通常是简单类型(如 String
、int
等),使用其他类型时,最好加上 @RequestParam,日期格式使用@DateTimeFormat
@GetMapping("/search")
public String search(@RequestParam("keyword") String keyword) {
return "Search for: " + keyword;
}
@GetMapping("/user/{id}")
public String getUserById(@PathVariable("id") String id) {
return "User ID: " + id;
}
@PostMapping("/addUser")
public String addUser(@RequestBody User user) {
return "User Name: " + user.getName();
}
@GetMapping("/header")
public String getHeader(@RequestHeader("Authorization") String auth) {
return "Auth: " + auth;
}
@GetMapping("/cookie")
public String getCookie(@CookieValue("sessionId") String sessionId) {
return "Session ID: " + sessionId;
}
@ResponseBody
@GetMapping("/json")
public String jsonResponse() {
return "{"key":"value"}";
}
@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("message", "Hello World");
}
@PostMapping("/save")
public String saveUser(@Valid @RequestBody User user, BindingResult result) {
if (result.hasErrors()) {
return "Validation failed";
}
return "Success";
}
@SessionAttributes("user")
@Controller
public class SessionController {
@GetMapping("/setSession")
public String setSession(Model model) {
model.addAttribute("user", "John");
return "session";
}
}
multipart/form-data
请求,常用于文件上传。@PostMapping("/upload")
public String handleFileUpload(@RequestPart("file") MultipartFile file) {
return "Uploaded: " + file.getOriginalFilename();
}
注解 | 功能描述 |
---|---|
@Controller | 标记类为控制器,用于返回视图 |
@RestController | 返回 JSON 或 XML 数据 |
@RequestMapping | 映射请求路径 |
@RequestParam | 获取请求参数 |
@PathVariable | 获取路径参数 |
@RequestBody | 获取请求体数据 |
@ResponseBody | 返回数据到响应体 |
@ModelAttribute | 绑定模型数据 |
@SessionAttributes | 保存会话属性 |
@Valid | 数据校验 |
@RequestHeader | 获取请求头参数 |
@CookieValue | 获取 Cookie 数据 |
在 SpringMVC 中,异常处理器用于集中处理控制器方法中发生的异常,避免将异常直接暴露给用户,同时可以返回友好的提示信息或进行日志记录。以下是常见的异常处理方式:
@ExceptionHandler
注解可以在控制器类中定义一个方法,通过 @ExceptionHandler
注解指定要捕获的异常类型。
@Controller
public class MyController {
@RequestMapping("/test")
public String test() {
throw new RuntimeException("测试异常");
}
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public String handleRuntimeException(RuntimeException e) {
return "捕获到异常: " + e.getMessage();
}
}
@ResponseBody
返回 JSON 数据)。@ControllerAdvice
@ControllerAdvice
是一个全局异常处理器,适用于所有控制器。
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public String handleGlobalRuntimeException(RuntimeException e) {
return "全局异常处理器捕获: " + e.getMessage();
}
}
HandlerExceptionResolver
接口可以自定义异常处理器,通过实现 HandlerExceptionResolver
接口来捕获和处理异常。
@Component
public class MyExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("error", ex.getMessage());
modelAndView.setViewName("error"); // 指向 error.jsp
return modelAndView;
}
}
ResponseStatusExceptionResolver
通过在异常类上添加 @ResponseStatus
注解,指定 HTTP 状态码和原因。
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "资源未找到")
public class ResourceNotFoundException extends RuntimeException {
}
在控制器中抛出该异常时,会返回对应的 HTTP 状态码和原因。
@RestControllerAdvice
@RestControllerAdvice
是 @ControllerAdvice
的变体,返回值默认是 JSON 格式(结合 @ResponseBody
的功能)。
@RestControllerAdvice
public class RestGlobalExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public Map handleRuntimeException(RuntimeException e) {
Map response = new HashMap();
response.put("code", 500);
response.put("message", e.getMessage());
return response;
}
}
@ResponseStatus
或自定义异常处理器返回。@Valid
或 @Validated
):MethodArgumentNotValidException
或 BindException
捕获。@ExceptionHandler(MethodArgumentNotValidException.class)
public Map handleValidationException(MethodArgumentNotValidException e) {
Map errors = new HashMap();
e.getBindingResult().getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage())
);
return errors;
}
@ExceptionHandler
。@ControllerAdvice
或 @RestControllerAdvice
。HandlerExceptionResolver
接口。@RestControllerAdvice
。通过合理设计异常处理器,可以提高系统的健壮性和用户体验。
REST(Representational State Transfer,表述性状态转移)是一种基于资源的网络架构风格,由 Roy Fielding 在他的博士论文中提出。它是一种设计 API 的方法,使客户端和服务端之间的交互更加简单、灵活和高效。
/users
表示用户资源集合。/users/123
表示具体用户资源。Content-Type
和 Accept
标头实现内容协商。Cache-Control
)指示客户端是否可以缓存响应数据。HTTP 方法 | 操作 | 示例 URL |
---|---|---|
GET | 获取资源 | /users 获取所有用户 |
POST | 创建资源 | /users 创建新用户 |
PUT | 更新资源(全量更新) | /users/123 更新用户 |
PATCH | 更新资源(部分更新) | /users/123 更新部分信息 |
DELETE | 删除资源 | /users/123 删除用户 |
状态码 | 描述 | 示例 |
---|---|---|
200 | 成功 | 请求成功,返回资源数据 |
201 | 已创建 | 成功创建资源,通常用于 POST |
204 | 无内容 | 操作成功,但不返回任何内容(如 DELETE) |
400 | 客户端错误 | 请求参数有误 |
401 | 未授权 | 缺少或无效的认证信息 |
403 | 禁止访问 | 客户端无权访问资源 |
404 | 资源未找到 | 请求的资源不存在 |
500 | 服务器内部错误 | 服务端处理请求时发生错误 |
GET /users HTTP/1.1
Host: example.com
Accept: application/json
响应:
[
{
"id": 1,
"name": "Alice",
"email": "alice@example.com"
},
{
"id": 2,
"name": "Bob",
"email": "bob@example.com"
}
]
POST /users HTTP/1.1
Host: example.com
Content-Type: application/json
{
"name": "Charlie",
"email": "charlie@example.com"
}
响应:
HTTP/1.1 201 Created
Location: /users/3
PUT /users/3 HTTP/1.1
Host: example.com
Content-Type: application/json
{
"name": "Charlie",
"email": "charlie.new@example.com"
}
响应:
HTTP/1.1 200 OK
DELETE /users/3 HTTP/1.1
Host: example.com
响应:
HTTP/1.1 204 No Content
Rest 风格是一种通用的、灵活的 API 设计模式,广泛应用于 Web 服务和微服务架构。通过严格遵守其原则,开发者可以构建出高效、易维护的系统。
在 SpringMVC 中,拦截器(Interceptor)是一种动态拦截请求并对其进行预处理和后处理的机制,类似于 Servlet 的过滤器(Filter),但功能更强大且更精细化。拦截器的核心是实现 HandlerInterceptor
接口或继承其实现类,并通过配置注册到应用程序中。
HandlerInterceptor
接口定义了拦截器的三个核心方法,分别在不同的生命周期阶段调用。
public interface HandlerInterceptor {
// 在处理请求之前调用
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
// 在处理请求之后,渲染视图之前调用
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
// 在整个请求完成之后调用
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
preHandle
:false
,阻止请求继续进入控制器。preHandle
返回 false
,表示请求被拦截,Spring MVC 不会继续调用后续拦截器、控制器方法和视图渲染逻辑。postHandle
:ModelAndView
对返回的数据或视图名称进行修改。ModelAndView
中添加全局变量(如用户信息、系统时间等)。afterCompletion
:preHandle
或 postHandle
中分配的资源(如数据库连接、线程资源等)。ThreadLocal
中绑定的变量,防止内存泄漏。Exception ex
不为 null
,可以记录错误日志或报警。preHandle
中记录请求开始时间,在 afterCompletion
中记录请求结束时间,计算整个请求的耗时。ex
是否存在,根据异常类型执行补偿逻辑。实现 HandlerInterceptor
接口或继承其默认实现类 HandlerInterceptorAdapter
。
@Component
public class LoggingInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle: 请求路径是 " + request.getRequestURI());
return true; // 返回 true 表示继续执行
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle: 处理完成,但视图还未渲染");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion: 请求已完成,视图已渲染");
}
}
拦截器需要注册到 SpringMVC 的拦截器链中,通过实现 WebMvcConfigurer
来完成。
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggingInterceptor())
.addPathPatterns("/**") // 拦截所有路径
.excludePathPatterns("/login", "/error"); // 排除路径
}
}
addPathPatterns
:指定拦截的路径模式。excludePathPatterns
:指定不拦截的路径模式。多个拦截器按注册顺序执行:
preHandle
:按注册顺序执行。postHandle
和 afterCompletion
:按注册顺序的逆序执行。@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new FirstInterceptor());
registry.addInterceptor(new SecondInterceptor());
}
执行顺序:
FirstInterceptor.preHandle
SecondInterceptor.preHandle
SecondInterceptor.postHandle
FirstInterceptor.postHandle
SecondInterceptor.afterCompletion
FirstInterceptor.afterCompletion
小结:
X
的 preHandle
返回 true
,Spring MVC 会确保在请求生命周期结束时调用拦截器 X
的 afterCompletion()
,无论后续的处理是正常结束还是发生异常。preHandler
执行顺序类似队列,postHandler
与 afterCompletion
类似栈。特性 | 拦截器(Interceptor) | 过滤器(Filter) |
---|---|---|
工作层级 | SpringMVC 层 | Servlet 容器层 |
拦截对象 | 控制器(Handler) | 所有请求(静态资源也可拦截) |
功能扩展 | 可以访问 Spring 上下文,支持依赖注入 | 无法直接访问 Spring 上下文 |
配置方式 | Spring 配置类 | web.xml 或 @WebFilter 注解 |
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
if (session.getAttribute("user") == null) {
response.sendRedirect("/login");
return false; // 阻止后续处理
}
return true;
}
}
通过合理设计和注册拦截器,可以显著提升应用的扩展性和灵活性。
参与评论
手机查看
返回顶部