处理类型
- 视图名称
- 当方法返回一个字符串,且该字符串不是ResponseEntity或@ResponseBody注解的返回值时,它通常被视为视图名称。Spring MVC将使用配置的ViewResolver来解析这个视图名称,并生成视图
@Controller public class ViewController {@GetMapping("/viewName")public String viewName() {return "myView"; // 视图解析器将解析为 /WEB-INF/views/myView.jsp} }
- ModelAndView对象
- 当方法返回一个ModelAndView对象时,Spring MVC会使用该对象中的数据来渲染视图
@Controller public class ModelAndViewController {@GetMapping("/modelAndView")public ModelAndView modelAndView() {ModelAndView mav = new ModelAndView();mav.setViewName("myView");mav.addObject("message", "Hello, ModelAndView!");return mav;} }
- Map或Model对象
- 返回的Map或Model对象包含了要传递给视图的属性。Spring MVC会将这些属性添加到模型中,并使用默认或指定的视图名称来渲染视图
@Controller public class ModelController {@GetMapping("/model")public String model(Model model) {model.addAttribute("message", "Hello, Model!");return "myView";} }
- 域对象
- 返回的域对象(如DTOs或Entity对象)通常会通过消息转换器(如Jackson)转换为JSON或XML格式的响应体,并标注为@ResponseBody
@RestController public class DomainObjectController {@GetMapping("/domainObject")public User getUser() {User user = new User("John Doe");return user; // Jackson会自动将其转换为JSON} }
- @ResponseBody注解
- 当方法的返回值被@ResponseBody注解时,Spring MVC会将返回值转换为HTTP响应体。这通常用于RESTful服务
@RestController public class ResponseBodyController {@GetMapping("/responseBody")public @ResponseBody String responseBody() {return "Hello, @ResponseBody!";} }
- ResponseEntity对象
- 当方法返回一个ResponseEntity对象时,Spring MVC会使用该对象中的HTTP状态码、头部信息和响应体来构建HTTP响应
@RestController public class ResponseEntityController {@GetMapping("/responseEntity")public ResponseEntity<String> responseEntity() {HttpHeaders headers = new HttpHeaders();headers.add("Custom-Header", "Value");return new ResponseEntity<>("Hello, ResponseEntity!", headers, HttpStatus.OK);} }
- HttpEntity对象
- 类似于ResponseEntity,但通常用于只包含响应体和头部信息,而不设置状态码
@RestController public class HttpEntityController {@GetMapping("/httpEntity")public HttpEntity<String> httpEntity() {HttpHeaders headers = new HttpHeaders();headers.add("Custom-Header", "Value");return new HttpEntity<>("Hello, HttpEntity!", headers);} }
- void或null
- 当方法返回void或null时,Spring MVC不会向客户端发送响应体,但可以设置响应的头部信息
@Controller
public class VoidController {@GetMapping("/void")public void voidMethod(HttpServletResponse response) {response.setStatus(HttpStatus.NO_CONTENT.value());}
}
- HTTP状态码
- 有时,你可能想要直接返回一个HTTP状态码,而不是数据。这可以通过抛出异常(如ResponseStatusException)来实现
@RestController
public class StatusCodeController {@GetMapping("/status")public ResponseEntity<String> status() {return ResponseEntity.status(HttpStatus.CREATED).body("Resource created successfully");}
}
- 异常
- 如果Controller方法抛出了异常,Spring MVC会使用异常处理器(@ExceptionHandler)来处理这些异常,并生成相应的响应
@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(ArithmeticException.class)public ResponseEntity<String> handleArithmeticException(ArithmeticException ex) {return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Math error: " + ex.getMessage());}
}
- 异步处理
- 对于异步处理,你可以返回Callable、DeferredResult或CompletableFuture等类型的对象,Spring MVC会等待异步操作完成后再发送响应
@RestController
public class AsyncController {@GetMapping("/async")public CompletableFuture<String> asyncMethod() {return CompletableFuture.supplyAsync(() -> {// 模拟长时间运行的任务try {Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}return "Hello, Async!";});}
}
- 文件下载
- 如果需要处理文件下载,可以返回Resource对象或使用ResponseEntity与Resource对象一起,来提供文件内容和必要的头部信息
@RestController
public class FileDownloadController {@GetMapping("/download")public ResponseEntity<Resource> downloadFile() {Resource resource = new ClassPathResource("static/files/sample.txt");return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"").body(resource);}
}
源码分析
-
HandlerAdapter接口:
HandlerAdapter接口定义了处理请求的方法,handle方法用于处理请求并返回一个ModelAndView对象。 -
RequestMappingHandlerAdapter类:
RequestMappingHandlerAdapter是HandlerAdapter的一个实现,它负责处理用@RequestMapping注解的方法。
它使用了HandlerMethodReturnValueHandler接口的实现来处理Controller方法的返回值。 -
HandlerMethodReturnValueHandler接口:
这个接口定义了handleReturnValue方法,用于处理Controller方法的返回值。
Spring MVC提供了多种默认的返回值处理器,例如ModelAndViewMethodReturnValueHandler、
ViewMethodReturnValueHandler、ResponseEntityMethodReturnValueHandler等。 -
处理视图名称和ModelAndView对象:
如果方法返回一个String,它通常被视为视图名称,ViewMethodReturnValueHandler会处理这个返回值。
如果方法返回一个ModelAndView对象,ModelAndViewMethodReturnValueHandler会处理这个返回值。 -
处理@ResponseBody和域对象:
当方法返回一个域对象且没有@ResponseBody注解时,Spring MVC会使用ServletModelAttributeMethodProcessor来处理返回值。
如果方法返回的域对象上有@ResponseBody注解,ServletInvocableHandlerMethod会直接将对象写入响应体,通常使用消息转换器(如Jackson)将对象转换为JSON。 -
处理ResponseEntity对象:
ResponseEntityMethodProcessor处理器会处理返回ResponseEntity对象的情况,它允许你完全控制响应的头部、状态码和体。 -
处理void或null:
如果方法返回void或null,EmptyReturnValueHandler处理器会被调用来处理这种情况,通常不会向客户端发送任何响应体。 -
处理异常:
ExceptionMethodReturnValueHandler处理器会处理抛出的异常,它通常会将异常转换为错误页面或JSON响应。 -
异步处理:
对于异步返回类型(如Callable、DeferredResult、CompletableFuture),ServletAsyncHandlerMethodReturnValueHandler处理器会处理这些返回值,并在异步操作完成后发送响应。 -
文件下载:
ResourceMethodReturnValueHandler处理器会处理返回Resource对象的情况,它负责处理文件下载。
在RequestMappingHandlerAdapter的invokeHandlerMethod方法中,会调用extendInterceptors方法来获取返回值处理器链,并根据Controller方法的返回值类型选择合适的处理器来处理返回值。
这些处理器的注册通常发生在RequestMappingHandlerAdapter的初始化过程中,通过afterPropertiesSet方法或通过实现BeanFactoryPostProcessor接口的RequestResponseBodyAdviceAdapterRegistry类来完成。