[关闭]
@javazjm 2017-10-30T02:27:30.000000Z 字数 13051 阅读 2484

SpringBoot系列学习五:Web支持之Web配置

Springboot 静态资源 拦截器 tomcat servlet


1. Web相关配置

1.1 Spring Boot的自动配置


WebMvcAutoConfiguration和WebMvcProperties提供自动配置。

1.1.1 自动配置的ViewResolver

ContentNegotiatingViewResolver

Spring MVC提供的一个特殊的ViewResolver,它不是自己处理View,而是代理给不同的ViewResolver来处理不同的View,优先级最高。
  1. @Bean
  2. @ConditionalOnBean({ViewResolver.class})
  3. @ConditionalOnMissingBean(
  4. name = {"viewResolver"},
  5. value = {ContentNegotiatingViewResolver.class}
  6. )
  7. public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
  8. ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
  9. resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));
  10. resolver.setOrder(-2147483648);
  11. return resolver;
  12. }

BeanNameViewResolver

控制器中一个方法返回的字符串为“index”(举例),根据BeanNameViewResolver去查找Bean的名称为index的视图来渲染视图。
  1. @Bean
  2. @ConditionalOnBean({View.class})
  3. @ConditionalOnMissingBean
  4. public BeanNameViewResolver beanNameViewResolver() {
  5. BeanNameViewResolver resolver = new BeanNameViewResolver();
  6. resolver.setOrder(2147483637);
  7. return resolver;
  8. }

InternalResourceViewResolver

比较常用,主要通过设置前缀和后缀以及控制器中的方法来返回视图名的字符串,以得到实际页面。
  1. @Bean
  2. @ConditionalOnMissingBean
  3. public InternalResourceViewResolver defaultViewResolver() {
  4. InternalResourceViewResolver resolver = new InternalResourceViewResolver();
  5. resolver.setPrefix(this.mvcProperties.getView().getPrefix());
  6. resolver.setSuffix(this.mvcProperties.getView().getSuffix());
  7. return resolver;
  8. }

1.1.2 自动配置的静态资源

类路径文件

把类路径下的/static、/public、/resources和/META-INF/resources文件夹下的静态文件直接映射为/*,可以通过http://localhost:8080/* 来访问。

Spring Boot的默认配置方式,提供的静态资源映射如下:

classpath:/META-INF/resources
classpath:/resources
classpath:/static
classpath:/public

![在工程里面路径是这样:][1]
优先级顺序为:META-INF/resources > resources > static > public
随机在上面一个路径下面放上index.html,当我们访问应用根目录http://lcoalhost:8080 时,会直接映射到index.html页面。

对应的配置文件配置如下:

  1. # 默认值为 /**
  2. spring.mvc.static-path-pattern=
  3. # 默认值为 classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
  4. spring.resources.static-locations=这里设置要指向的路径,多个使用英文逗号隔开

可以通过修改spring.mvc.static-path-pattern来修改默认的映射,例如我改成/didi/**,那运行的时候访问 http://lcoalhost:8080/didi/index.html 才对应到index.html页面。

webjar

将我们常用的脚本框架封装在jar中的jar,把webjar的/META-INF/resources/webjars下的静态文件映射为/webjar/**,可通过http://localhost:8080/webjar/**来访问。

1.1.3 自动配置的Formatter和Converter

WebMvcAutoConfiguration中的定义:
  1. public void addFormatters(FormatterRegistry registry) {
  2. Iterator var2 = this.getBeansOfType(Converter.class).iterator();
  3. while(var2.hasNext()) {
  4. Converter formatter = (Converter)var2.next();
  5. registry.addConverter(formatter);
  6. }
  7. var2 = this.getBeansOfType(GenericConverter.class).iterator();
  8. while(var2.hasNext()) {
  9. GenericConverter formatter1 = (GenericConverter)var2.next();
  10. registry.addConverter(formatter1);
  11. }
  12. var2 = this.getBeansOfType(Formatter.class).iterator();
  13. while(var2.hasNext()) {
  14. Formatter formatter2 = (Formatter)var2.next();
  15. registry.addFormatter(formatter2);
  16. }
  17. }
只要定义了Converter、GenericConverter、Formatter接口的实现类Bean,这些Bean就会自动注册到Spring MVC中。

1.1.4 自动配置的HttpMessageConverters

在WebMvcAutoConfiguration中,注册了messageConverters:
  1. private final HttpMessageConverters messageConverters;
  2. public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  3. converters.addAll(this.messageConverters.getConverters());
  4. }
直接注入HttpMessageConverter的Bean,而这个Bean是在HttpMessageConvertersAutoConfiguration中定义的,自动注册的HttpMessageConverter除了Spring MVC默认的ByteArrayHttpMessageConverter、StringHttpMessageConverter、ResourceHttpMessageConverter、SourceHttpMessageConverter、AllEncompassingFormHttpMessageConverter外,还引入了JacksonHttpMessageConvertersConfiguration和GsonHttpMessageConvertersConfiguration:
  1. @Configuration
  2. @ConditionalOnClass({HttpMessageConverter.class})
  3. @AutoConfigureAfter({GsonAutoConfiguration.class, JacksonAutoConfiguration.class})
  4. @Import({JacksonHttpMessageConvertersConfiguration.class, GsonHttpMessageConvertersConfiguration.class})
  5. public class HttpMessageConvertersAutoConfiguration {
  6. static final String PREFERRED_MAPPER_PROPERTY = "spring.http.converters.preferred-json-mapper";
  7. private final List<HttpMessageConverter<?>> converters;
  8. public HttpMessageConvertersAutoConfiguration(ObjectProvider<List<HttpMessageConverter<?>>> convertersProvider) {
  9. this.converters = (List)convertersProvider.getIfAvailable();
  10. }

1.2 自定义MVC配置


1.2.1 自定义资源映射addResourceHandlers

若Spring Boot提供的MVC不符合要求,可自定义一个配置类来自己控制,注解有@Configuration并加上@EnableWebMvc;
若既需要默认的配置还需要扩展,则定义一个配置类直接继承WebMvcConfigurerAdapter,无须使用@EnableWebMvc,按照Spring MVC添加配置的方法来写。
  1. @Configuration
  2. public class MyWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {
  3. /**
  4. * 配置静态访问资源
  5. * @param registry
  6. */
  7. @Override
  8. public void addResourceHandlers(ResourceHandlerRegistry registry) {
  9. registry.addViewController("/xxx").setViewName("/xx"); // 页面名称
  10. registry.addResourceHandler("/my/**").addResourceLocations("classpath:/my/");
  11. registry.addResourceHandler("/my/**").addResourceLocations("file:E:/my/");// 指定外部路径
  12. super.addResourceHandlers(registry);
  13. }
  14. }

注: 不会覆盖原有的addViewControllers("/"映射到index.html),既自定义配置和Spring Boot的自动配置同时有效。

比如访问my文件夹下的123.jpg: http://localhost:8080/my/123.jpg
通过addResourceHandler添加映射路径,然后通过addResourceLocations来指定路径。
addResourceLocations指的是文件放置的目录,addResoureHandler指的是对外暴露的访问路径

1.2.2 页面跳转addViewControllers

只访问一个页面的话,重写WebMvcConfigurerAdapter中的addViewControllers方法即可。

  1. /**
  2. * 以前要访问一个页面需要先创建个Controller控制类,再写方法跳转到页面
  3. * 在这里配置后就不需要那么麻烦了,直接访问http://localhost:8080/client就跳转到client页面了
  4. * @param registry
  5. */
  6. @Override
  7. public void addViewControllers(ViewControllerRegistry registry) {
  8. registry.addViewController("/client").setViewName("test/client");
  9. registry.addViewController("/manage").setViewName("test/manage");
  10. super.addViewControllers(registry);
  11. }

在这里重写addViewControllers方法,并不会覆盖WebMvcAutoConfiguration中的addViewControllers(在此方法中,Spring Boot将“/”映射至index.html),我们自己的配置和SpringBoot的自动配置同时有效,所以,提倡添加自己的MVC配置的方式。

1.2.3 拦截器addInterceptors

判断是否登录:

  1. public class MyInterceptor implements HandlerInterceptor {
  2. @Override
  3. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  4. boolean flag =true;
  5. User user=(User)request.getSession().getAttribute("user");
  6. if(null==user){
  7. response.sendRedirect("toLogin");
  8. flag = false;
  9. }else{
  10. flag = true;
  11. }
  12. return flag;
  13. }
  14. @Override
  15. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  16. }
  17. @Override
  18. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  19. }
  20. }

重写WebMvcConfigurerAdapter中的addInterceptors方法:

  1. /**
  2. * 拦截器
  3. * @param registry
  4. */
  5. @Override
  6. public void addInterceptors(InterceptorRegistry registry) {
  7. // addPathPatterns 用于添加拦截规则
  8. // excludePathPatterns 用户排除拦截
  9. registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/toLogin","/login");
  10. super.addInterceptors(registry);
  11. }

addPathPatterns("/**")对所有请求都拦截,但是排除了/toLogin和/login请求的拦截

3.1 注册Servlet、Filter、Listener


自定义servlet:
  1. public class MyServlet1 extends HttpServlet{
  2. @Override
  3. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  4. System.out.println(">>>>>>>>>>>>>>>>>>>>>>>doGet>>>>>>");
  5. PrintWriter out = resp.getWriter();
  6. out.print("success");
  7. }
  8. @Override
  9. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  10. System.out.println(">>>>>>>>>>>>>>>>>>>>>>>doPost>>>>>>");
  11. doGet(req,resp);
  12. }
  13. }

1.通过RegistrationBean

  1. @Bean
  2. public ServletRegistrationBean servletRegistrationBean(){
  3. return new ServletRegistrationBean(new MyServlet1(),"/servlet1/*");
  4. }
  5. @Bean
  6. public FilterRegistrationBean filterRegistrationBean(){
  7. FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
  8. filterRegistrationBean.setFilter(new MyFilter1());
  9. filterRegistrationBean.setOrder(2);
  10. return filterRegistrationBean;
  11. }
  12. @Bean
  13. public ServletListenerRegistrationBean<MyListener1> myListener1ServletListenerRegistrationBean(){
  14. return new ServletListenerRegistrationBean<>(new MyListener1());
  15. }

2.直接注册为Bean

  1. @Bean
  2. public MyServlet1 myServlet1(){
  3. return new MyServlet1();
  4. }
  5. @Bean
  6. public MyFilter1 myFilter1(){
  7. return new MyFilter1();
  8. }
  9. @Bean
  10. public MyListener1 myListener1(){
  11. return new MyListener1();
  12. }

3.使用注解
在SpringBootThymeleafApplication启动类中,使用@ServletComponentScan注解,直接使用@WebServlet、
@WebFilter、@WebListener 注解自动注册,无需其他代码。

  1. @WebServlet(urlPatterns = "/servlet2/*",description = "servlet2")
  2. public class MyServlet2 extends HttpServlet {
  3. @Override
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  5. System.out.println(">>>>>>>>>>>>>>>>>>>>>>>doGet>>>>>>");
  6. PrintWriter out = resp.getWriter();
  7. out.print("success");
  8. }
  9. @Override
  10. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  11. System.out.println(">>>>>>>>>>>>>>>>>>>>>>>doPost>>>>>>");
  12. doGet(req, resp);
  13. }
  14. }
见项目SpringBoot-Thymeleaf

2. Tomcat配置

即servlet容器的配置。

2.1 配置Tomcat


Tomcat的所有属性在org.springframework.boot.autoconfigure.web.ServerProperties配置类中做了定义,只需要在application.properities中配置即可,通用的Servlet容器以“server”作为前缀,tomcat以“server.tomcat”作为前缀。
  1. #配置Servlet容器
  2. server.port= #默认端口8080
  3. server.session.timeout= #session过期时间,以秒为单位
  4. server.context-path= #配置访问路径,默认/
  5. #配置Tomcat
  6. server.tomcat.uri-encoding= #Tomcat编码,默认UTF-8
  7. server.tomcat.compression= #是否开启压缩,默认off

2.2 代码配置Tomcat


通过代码配置Servlet容器,注册一个实现EmdeddedServletContainerCustomizer接口的bean;直接配置Tomcat、Jetty、Undertow,可直接定义TomcatEmbeddedServletContainerFactory、JettyEmbeddedServletContainerFactory、UndertowEmbeddedServletContainerFactory。

详见:7.4.2

3.2 替换Tomcat


1、替换为Jetty

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-web</artifactId>
  4. <exclusions>
  5. <exclusion>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-tomcat</artifactId>
  8. </exclusion>
  9. </exclusions>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-jetty</artifactId>
  14. </dependency>
  15. </dependencies>

2、替换为Undertow

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-web</artifactId>
  4. <exclusions>
  5. <exclusion>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-tomcat</artifactId>
  8. </exclusion>
  9. </exclusions>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-undertow</artifactId>
  14. </dependency>

4、SSL配置


1、生成证书:

jdk下的bin中有keytool.exe,它是一个证书管理工具,可生成自签名的证书。

cmd下:

  1. C:\Users\admin>keytool -genkey -alias tomcat
  2. 输入密钥库口令:
  3. 密钥库口令太短 - 至少必须为 6 个字符
  4. 输入密钥库口令:
  5. 再次输入新口令:
  6. 您的名字与姓氏是什么?
  7. [Unknown]: jinmiaozhang
  8. 您的组织单位名称是什么?
  9. [Unknown]: zhx
  10. 您的组织名称是什么?
  11. [Unknown]: zhx
  12. 您所在的城市或区域名称是什么?
  13. [Unknown]: beijing
  14. 您所在的省/市/自治区名称是什么?
  15. [Unknown]: beijing
  16. 该单位的双字母国家/地区代码是什么?
  17. [Unknown]: CHINA
  18. CN=jinmiaozhang, OU=zhx, O=zhx, L=beijing, ST=beijing, C=CHINA是否正确?
  19. [否]:
  20. 您的名字与姓氏是什么?
  21. [jinmiaozhang]:
  22. 您的组织单位名称是什么?
  23. [zhx]:
  24. 您的组织名称是什么?
  25. [zhx]:
  26. 您所在的城市或区域名称是什么?
  27. [beijing]:
  28. 您所在的省/市/自治区名称是什么?
  29. [beijing]:
  30. 该单位的双字母国家/地区代码是什么?
  31. [CHINA]: 86
  32. CN=jinmiaozhang, OU=zhx, O=zhx, L=beijing, ST=beijing, C=86是否正确?
  33. [否]: y
  34. 输入 <tomcat> 的密钥口令
  35. (如果和密钥库口令相同, 按回车):
  36. C:\Users\admin>

在当前目录下可以看到生成了.keystore文件。

2、Springboot配置SSL
添加index.html到src/main/resources/static下,作为测试。
将.keystore文件复制到项目根目录,在application.properties中做如下SSL配置:

  1. server.port=8443
  2. server.ssl.key-store=.keystore
  3. server.ssl.key-store-password=123456
  4. server.ssl.key-store-type=JKS
  5. server.ssl.key-alias=tomcat

启动:Tomcat started on port(s): 8443 (https)
访问:https://localhost:8443/

3、http转向https
输入http地址栏会自动转向HTTPS,实现此功能需配置TomcatEmbeddedServletContainerFactory,并添加Tomcat的connector来实现。

  1. @SpringBootApplication
  2. public class DemoApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(DemoApplication.class, args);
  5. System.out.println("启动成功");
  6. }
  7. @Bean
  8. public EmbeddedServletContainerFactory servletContainer() {
  9. TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
  10. @Override
  11. protected void postProcessContext(Context context) {
  12. SecurityConstraint securityConstraint = new SecurityConstraint();
  13. securityConstraint.setUserConstraint("CONFIDENTIAL");
  14. SecurityCollection collection = new SecurityCollection();
  15. collection.addPattern("/*");
  16. securityConstraint.addCollection(collection);
  17. context.addConstraint(securityConstraint);
  18. }
  19. };
  20. tomcat.addAdditionalTomcatConnectors(httpConnector());
  21. return tomcat;
  22. }
  23. @Bean
  24. public Connector httpConnector() {
  25. Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
  26. connector.setScheme("http");
  27. connector.setPort(8080);
  28. connector.setSecure(false);
  29. connector.setRedirectPort(8443);
  30. return connector;
  31. }
  32. }

控制台: Tomcat started on port(s): 8443 (https) 8080 (http)
此时访问:http://localhost:8080/ 会跳转到 https://localhost:8443

3. Favicon配置

#关闭favicon,默认开启
spring.mvc.favicon.enabled=false

1、自定义Favicon
将favicon.ico(文件名固定不能变)放到类路径根目录下、类路径META-INF/resources/下、类路径resources/下、类路径static/下或类路径public/下。

4. WebSocket

为浏览器和服务端提供了双工异步通信的功能,即浏览器可以向服务器发送消息,服务器也可以向浏览器发送消息。

1

5. REST

1. HATEOAS 应用

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注