跳转至
本文阅读量

1. 主要类

  • DispatcherServlet
  • WebApplicationContext

  • RequestContextUtils

preHandle postHandle afterCompletion

可以对 response 进行干预 ResponseBodyAdvice RequestMappingHandlerAdapter

HandlerExceptionResolver 异常处理程序的 Resolver * SimpleMappingExceptionResolver * DefaultHandlerExceptionResolver * ResponseStatusExceptionResolver * ExceptionHandlerExceptionResolver

FormattingConversionServiceFactoryBean

View Resovler

LocalValidatorFactoryBean

能够用于 MVC 配置的机制有 * 实现 WebMvcConfigurer 接口,可以添加 * addFormatters * addInterceptors * addResourceHandlers * addCorsMappings * addViewControllers * addArgumentResolvers * addReturnValueHandlers * 通过 @InitBinder 注解

上边的 addXXX 中有个 yyyRegistry 的概念

2. Context Hierarchy

3. web.xml 中可以配置的参数

3.1 MVC Config

都可以配置哪些内容

  • 使能 MVC 配置
  • MVC Config API
  • Type Conversion
  • Validation
  • Interceptors
  • Content Types
  • Message Converters
  • View Controllers
  • View Resolvers
  • Static Resources
  • Default Servlet
  • Path Matching
  • Advanced Java Config
  • Advance XML Config

3.1.1 配置静态资源

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("/public", "classpath:/static/")
                .setCacheControl(CacheControl.maxAge(Duration.ofDays(365)));
    }
}
@Configuration
@EnableWebMvc
public class WebConfig {
}
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
        registrar.setUseIsoFormat(true);
        registrar.registerFormatters(registry);
    }
}

3.1.2 错误处理

  • 错误处理调用链
  • 默认错误处理页

3.1.3 视图(View) 相关

核心类 * ViewResolver * View

ViewResolver * AbstractCachingViewResolver * UrlBasedViewResolver * InternalResourceViewResolver * FreeMarkerViewResolver * ContentNegotiatingViewResolver * BeanNameViewResolver

View 也可以多个组成 chain view resolvers

3.1.3.1 重定向*(Redirecting)

前缀 redirect:,对应的 View 为 RedirectView

3.1.3.2 (转发)Forwarding

前缀 forward:,

UrlBasedViewResolver RequestDispatcher.forward()

3.1.3.3 内容协商

3.1.3.4 本地化

RequestContext.getLocale()

org.springframework.web.servlet.i18n

可以根据以下纬度进行 locale 的解析 - Time Zone - Header Resolver - Cookie Resolver - Session Resolver - Locale Interceptor

3.1.3.5 主题

包: org.springframework.ui.context.ThemeSourc

ThemeResolver * FixedThemeResolver * SessionThemeResolver * CookieThemeResolver

org.springframework.ui.context.support.ResourceBundleThemeSource

3.1.3.6 Multipart Resolver

org.springframework.web.multipart

MultipartResolver * CommonsMultipartResolver * StandardServletMultipartResolver MultipartHttpServletRequest

3.2 CORS 跨域处理

  • 每个 HandlerMapping 均可以配置自己的 CorsConfiguration;但通常有一个全局的 CORS 配置即可
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {

        registry.addMapping("/api/**")
            .allowedOrigins("https://domain2.com")
            .allowedMethods("PUT", "DELETE")
            .allowedHeaders("header1", "header2", "header3")
            .exposedHeaders("header1", "header2")
            .allowCredentials(true).maxAge(3600);

        // Add more mappings...
    }
}

3.2.1 支持条件定义接口

如下示例: 判断请求参数中是否包含 https://xxx.com/pets/1234?myParam=myValue

@GetMapping(path = "/pets/{petId}", params = "myParam=myValue") 
public void findPet(@PathVariable String petId) {
    // ...
}

如下示例,判断是否 HTTP header 包含 myHeader: myValue

@GetMapping(path = "/pets", headers = "myHeader=myValue") 
public void findPet(@PathVariable String petId) {
    // ...
}

3.2.1.1 @RequestParam 不是必须的

Note that use of @RequestParam is optional (for example, to set its attributes). By default, any argument that is a simple value type (as determined by BeanUtils#isSimpleProperty) and is not resolved by any other argument resolver, is treated as if it were annotated with @RequestParam.

3.2.1.2 @RequestHeader 可以作用到通用集合类型上 Map, MultiValueMap, or HttpHeaders

When an @RequestHeader annotation is used on a Map, MultiValueMap, or HttpHeaders argument, the map is populated with all header values.

3.2.2 Data binding 和 Type conversion 的区别

  • @ModelAttribute 可以作用到方法上、参数上
  • @ModelAttribute(binding=false) 可以通过 binding=false 指定不进行参数绑定
  • 可以通过 Valid 指定对参数是否进行校验

ResponseEntity && RequestEntity 表示 HTTP 响应、请求的完整实体,包括请求头、方法、body 等

3.3 1.10 视图技术

3.4 1.11 MVC 配置

@Configuration
@EnableWebMvc
public class WebConfiguration implements WebMvcConfigurer {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder()
                .indentOutput(true)
                .dateFormat(new SimpleDateFormat("yyyy-MM-dd"))
                .modulesToInstall(new ParameterNamesModule());
        converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
        converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
    }
}

4. 2. REST 客户端 (REST Client)

4.1 2.1 RestTemplate

从 Spring 5.0 开始, RestTempalte 进入维护模式,后续可以使用 WebClient 提供的更加现代,且支持同步、异步、流场景的 API

5. 3. 测试(Testing)

  • Servlet API Mocks
  • TestContext Framework
  • Spring MVC Test
  • Client-side REST
  • WebTestClient

6. 4. Websockets

6.1 主要类

  • @EnableWebSocket 开启 Websocket
  • WebSocketHttpRequestHandler
  • TextWebSocketHandler
  • BinaryWebSocketHandler
  • ConcurrentWebSocketSessionDecorator
  • WebSocketConfigurer
  • WebSocketHandlerRegistry
  • HandshakeInterceptor
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myHandler(), "/myHandler");
    }

    @Bean
    public WebSocketHandler myHandler() {
        return new MyHandler();
    }

}

6.2 4.2 WeSocketHandler