7 Advanced Spring MVC

7.1 Alternate Spring MVC configuration

7.1.1 Customizing DispatcherServlet configuration

可以覆盖 AbstractAnnotationConfigDispatcherServletInitializer 的 customizeRegistration() 方法来自定义配置,该方法在注册完DispatcherServlet之后被调用,比如你可以配置 Servlet 3.0 multipart support :

@Override
protected void customizeRegistration(Dynamic registration) {
  registration.setMultipartConfig(
      new MultipartConfigElement("/tmp/spittr/uploads"));
}

7.1.2 Adding additional servlets and filters

To register one or more filters and map them to DispatcherServlet, all you need to do is override the getServletFilters() method of AbstractAnnotationConfigDispatcherServletInitializer:

@Override
protected Filter[] getServletFilters() {
  return new Filter[] { new MyFilter() };
}

7.1.3 Declaring DispatcherServlet in web.xml

略。

7.2 Processing multipart form data

7.2.1 Configuring a multipart resolver

DispatcherServlet没有实现 multipart 请求的解析逻辑,而是代理给 Spring’s MultipartResolver 接口,从Spring 3.1开始,Spring提供了两个开箱即用的实现:

  • CommonsMultipartResolver—Resolves multipart requests using Jakarta Commons FileUpload
  • StandardServletMultipartResolver—Relies on Servlet 3.0 support for multipart requests (since Spring 3.1)

一般来讲,你应该优先选择 StandardServletMultipartResolver ,因为Servlet容器本身支持,不需要额外的依赖。如果你部署到Servlet 3.0以前的容器或者使用Spring 3.1以前的版本,就只能使用 CommonsMultipartResolver 了。

RESOLVING MULTIPART REQUESTS WITH SERVLET 3.0

@Bean
public MultipartResolver multipartResolver() throws IOException {
  return new StandardServletMultipartResolver();
}

如果你想指定最大文件大小或者临时保存路径,你只能在servlet配置中指定,More specifically, you must configure multipart details as part of DispatcherServlet’s configuration in web.xml or in the servlet initializer class.(见7.1.1)

除了路径,你还可以指定:

  • The maximum size (in bytes) of any file uploaded. By default there is no limit.
  • The maximum size (in bytes) of the entire multipart request, regardless of how many parts or how big any of the parts are. By default there is no limit.
  • The maximum size (in bytes) of a file that can be uploaded without being written to the temporary location. The default is 0, meaning that all uploaded files will be written to disk.
@Override
protected void customizeRegistration(Dynamic registration) {
  registration.setMultipartConfig(
      new MultipartConfigElement("/tmp/spittr/uploads",
          2097152, 4194304, 0));
}

CONFIGURING A JAKARTA COMMONS FILEUPLOAD MULTIPART RESOLVER

@Bean
public MultipartResolver multipartResolver() throws IOException {
  CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
  multipartResolver.setUploadTempDir(new FileSystemResource("/tmp/spittr/uploads"));
  multipartResolver.setMaxUploadSize(2097152);
  multipartResolver.setMaxInMemorySize(0);
  return multipartResolver;
}

7.2.2 Handling multipart requests

@RequestPart("profilePicture") byte[] profilePicture

RECEIVING A MULTIPARTFILE

使用byte[]不太方便,使用MultipartFile:

RECEIVING THE UPLOADED FILE AS A PART

注意:如果你使用Part来接收参数,你就不需要配置 StandardServletMultipartResolver bean了,当你使用 MultipartFile 的时候才需要它。

7.3 Handling exceptions

在处理请求的过程中,不管发生什么,结果都是Servlet response,因此,异常必须转换成response,Spring提供了几种异常转换的方式:

  • Certain Spring exceptions are automatically mapped to specific HTTP status codes.
  • An exception can be annotated with @ResponseStatus to map it to an HTTP status code.
  • A method can be annotated with @ExceptionHandler to handle the exception.

7.3.1 Mapping exceptions to HTTP status codes

上面的异常基本上都是DispatcherServlet或者处理验证的时候抛出的,但是应用抛出的异常,默认会导致 a response with a 500 (Internal Server Error) status code,可以使用@ResponseStatus注解来改变:

7.3.2 Writing exception-handling methods

如果你想像处理正常请求一样来处理异常,一种方法是在controller方法中捕获它,另一种更好的方法是使用@ExceptionHandler:

@ExceptionHandler(DuplicateSpittleException.class)
public String handleDuplicateSpittle() {
  return "error/duplicate";
}

这样,在同一个Controller中的任何一个处理方法抛出的异常,都会被该方法处理。

7.4 Advising controllers

Spring 3.2 提供了 controller advice ,它是被标注了 @ControllerAdvice 并且拥有一个或多个如下方法的类:

  • @ExceptionHandler-annotated
  • @InitBinder-annotated
  • @ModelAttribute-annotated

这些方法会被应用在所有控制器的@RequestMapping-annotated的方法中。

results matching ""

    No results matching ""