@javazjm
2017-10-30T02:27:30.000000Z
字数 13051
阅读 2791
Springboot 静态资源 拦截器 tomcat servlet
WebMvcAutoConfiguration和WebMvcProperties提供自动配置。
ContentNegotiatingViewResolver
Spring MVC提供的一个特殊的ViewResolver,它不是自己处理View,而是代理给不同的ViewResolver来处理不同的View,优先级最高。
@Bean@ConditionalOnBean({ViewResolver.class})@ConditionalOnMissingBean(name = {"viewResolver"},value = {ContentNegotiatingViewResolver.class})public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));resolver.setOrder(-2147483648);return resolver;}
BeanNameViewResolver
控制器中一个方法返回的字符串为“index”(举例),根据BeanNameViewResolver去查找Bean的名称为index的视图来渲染视图。
@Bean@ConditionalOnBean({View.class})@ConditionalOnMissingBeanpublic BeanNameViewResolver beanNameViewResolver() {BeanNameViewResolver resolver = new BeanNameViewResolver();resolver.setOrder(2147483637);return resolver;}
InternalResourceViewResolver
比较常用,主要通过设置前缀和后缀以及控制器中的方法来返回视图名的字符串,以得到实际页面。
@Bean@ConditionalOnMissingBeanpublic InternalResourceViewResolver defaultViewResolver() {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix(this.mvcProperties.getView().getPrefix());resolver.setSuffix(this.mvcProperties.getView().getSuffix());return resolver;}
把类路径下的/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页面。
对应的配置文件配置如下:
# 默认值为 /**spring.mvc.static-path-pattern=# 默认值为 classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/spring.resources.static-locations=这里设置要指向的路径,多个使用英文逗号隔开
可以通过修改spring.mvc.static-path-pattern来修改默认的映射,例如我改成/didi/**,那运行的时候访问 http://lcoalhost:8080/didi/index.html 才对应到index.html页面。
将我们常用的脚本框架封装在jar中的jar,把webjar的/META-INF/resources/webjars下的静态文件映射为/webjar/**,可通过http://localhost:8080/webjar/**来访问。
WebMvcAutoConfiguration中的定义:
public void addFormatters(FormatterRegistry registry) {Iterator var2 = this.getBeansOfType(Converter.class).iterator();while(var2.hasNext()) {Converter formatter = (Converter)var2.next();registry.addConverter(formatter);}var2 = this.getBeansOfType(GenericConverter.class).iterator();while(var2.hasNext()) {GenericConverter formatter1 = (GenericConverter)var2.next();registry.addConverter(formatter1);}var2 = this.getBeansOfType(Formatter.class).iterator();while(var2.hasNext()) {Formatter formatter2 = (Formatter)var2.next();registry.addFormatter(formatter2);}}
只要定义了Converter、GenericConverter、Formatter接口的实现类Bean,这些Bean就会自动注册到Spring MVC中。
在WebMvcAutoConfiguration中,注册了messageConverters:
private final HttpMessageConverters messageConverters;public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {converters.addAll(this.messageConverters.getConverters());}
直接注入HttpMessageConverter的Bean,而这个Bean是在HttpMessageConvertersAutoConfiguration中定义的,自动注册的HttpMessageConverter除了Spring MVC默认的ByteArrayHttpMessageConverter、StringHttpMessageConverter、ResourceHttpMessageConverter、SourceHttpMessageConverter、AllEncompassingFormHttpMessageConverter外,还引入了JacksonHttpMessageConvertersConfiguration和GsonHttpMessageConvertersConfiguration:
@Configuration@ConditionalOnClass({HttpMessageConverter.class})@AutoConfigureAfter({GsonAutoConfiguration.class, JacksonAutoConfiguration.class})@Import({JacksonHttpMessageConvertersConfiguration.class, GsonHttpMessageConvertersConfiguration.class})public class HttpMessageConvertersAutoConfiguration {static final String PREFERRED_MAPPER_PROPERTY = "spring.http.converters.preferred-json-mapper";private final List<HttpMessageConverter<?>> converters;public HttpMessageConvertersAutoConfiguration(ObjectProvider<List<HttpMessageConverter<?>>> convertersProvider) {this.converters = (List)convertersProvider.getIfAvailable();}
若Spring Boot提供的MVC不符合要求,可自定义一个配置类来自己控制,注解有@Configuration并加上@EnableWebMvc;
若既需要默认的配置还需要扩展,则定义一个配置类直接继承WebMvcConfigurerAdapter,无须使用@EnableWebMvc,按照Spring MVC添加配置的方法来写。
@Configurationpublic class MyWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {/*** 配置静态访问资源* @param registry*/@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addViewController("/xxx").setViewName("/xx"); // 页面名称registry.addResourceHandler("/my/**").addResourceLocations("classpath:/my/");registry.addResourceHandler("/my/**").addResourceLocations("file:E:/my/");// 指定外部路径super.addResourceHandlers(registry);}}
注: 不会覆盖原有的addViewControllers("/"映射到index.html),既自定义配置和Spring Boot的自动配置同时有效。
比如访问my文件夹下的123.jpg: http://localhost:8080/my/123.jpg
通过addResourceHandler添加映射路径,然后通过addResourceLocations来指定路径。
addResourceLocations指的是文件放置的目录,addResoureHandler指的是对外暴露的访问路径
只访问一个页面的话,重写WebMvcConfigurerAdapter中的addViewControllers方法即可。
/*** 以前要访问一个页面需要先创建个Controller控制类,再写方法跳转到页面* 在这里配置后就不需要那么麻烦了,直接访问http://localhost:8080/client就跳转到client页面了* @param registry*/@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/client").setViewName("test/client");registry.addViewController("/manage").setViewName("test/manage");super.addViewControllers(registry);}
在这里重写addViewControllers方法,并不会覆盖WebMvcAutoConfiguration中的addViewControllers(在此方法中,Spring Boot将“/”映射至index.html),我们自己的配置和SpringBoot的自动配置同时有效,所以,提倡添加自己的MVC配置的方式。
判断是否登录:
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {boolean flag =true;User user=(User)request.getSession().getAttribute("user");if(null==user){response.sendRedirect("toLogin");flag = false;}else{flag = true;}return flag;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}}
重写WebMvcConfigurerAdapter中的addInterceptors方法:
/*** 拦截器* @param registry*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {// addPathPatterns 用于添加拦截规则// excludePathPatterns 用户排除拦截registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/toLogin","/login");super.addInterceptors(registry);}
addPathPatterns("/**")对所有请求都拦截,但是排除了/toLogin和/login请求的拦截
自定义servlet:
public class MyServlet1 extends HttpServlet{@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(">>>>>>>>>>>>>>>>>>>>>>>doGet>>>>>>");PrintWriter out = resp.getWriter();out.print("success");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(">>>>>>>>>>>>>>>>>>>>>>>doPost>>>>>>");doGet(req,resp);}}
1.通过RegistrationBean
@Beanpublic ServletRegistrationBean servletRegistrationBean(){return new ServletRegistrationBean(new MyServlet1(),"/servlet1/*");}@Beanpublic FilterRegistrationBean filterRegistrationBean(){FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();filterRegistrationBean.setFilter(new MyFilter1());filterRegistrationBean.setOrder(2);return filterRegistrationBean;}@Beanpublic ServletListenerRegistrationBean<MyListener1> myListener1ServletListenerRegistrationBean(){return new ServletListenerRegistrationBean<>(new MyListener1());}
2.直接注册为Bean
@Beanpublic MyServlet1 myServlet1(){return new MyServlet1();}@Beanpublic MyFilter1 myFilter1(){return new MyFilter1();}@Beanpublic MyListener1 myListener1(){return new MyListener1();}
3.使用注解
在SpringBootThymeleafApplication启动类中,使用@ServletComponentScan注解,直接使用@WebServlet、
@WebFilter、@WebListener 注解自动注册,无需其他代码。
@WebServlet(urlPatterns = "/servlet2/*",description = "servlet2")public class MyServlet2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(">>>>>>>>>>>>>>>>>>>>>>>doGet>>>>>>");PrintWriter out = resp.getWriter();out.print("success");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(">>>>>>>>>>>>>>>>>>>>>>>doPost>>>>>>");doGet(req, resp);}}
见项目SpringBoot-Thymeleaf
即servlet容器的配置。
Tomcat的所有属性在org.springframework.boot.autoconfigure.web.ServerProperties配置类中做了定义,只需要在application.properities中配置即可,通用的Servlet容器以“server”作为前缀,tomcat以“server.tomcat”作为前缀。
#配置Servlet容器server.port= #默认端口8080server.session.timeout= #session过期时间,以秒为单位server.context-path= #配置访问路径,默认/#配置Tomcatserver.tomcat.uri-encoding= #Tomcat编码,默认UTF-8server.tomcat.compression= #是否开启压缩,默认off
通过代码配置Servlet容器,注册一个实现EmdeddedServletContainerCustomizer接口的bean;直接配置Tomcat、Jetty、Undertow,可直接定义TomcatEmbeddedServletContainerFactory、JettyEmbeddedServletContainerFactory、UndertowEmbeddedServletContainerFactory。
详见:7.4.2
1、替换为Jetty
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jetty</artifactId></dependency></dependencies>
2、替换为Undertow
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-undertow</artifactId></dependency>
4、SSL配置
1、生成证书:
jdk下的bin中有keytool.exe,它是一个证书管理工具,可生成自签名的证书。
cmd下:
C:\Users\admin>keytool -genkey -alias tomcat输入密钥库口令:密钥库口令太短 - 至少必须为 6 个字符输入密钥库口令:再次输入新口令:您的名字与姓氏是什么?[Unknown]: jinmiaozhang您的组织单位名称是什么?[Unknown]: zhx您的组织名称是什么?[Unknown]: zhx您所在的城市或区域名称是什么?[Unknown]: beijing您所在的省/市/自治区名称是什么?[Unknown]: beijing该单位的双字母国家/地区代码是什么?[Unknown]: CHINACN=jinmiaozhang, OU=zhx, O=zhx, L=beijing, ST=beijing, C=CHINA是否正确?[否]:您的名字与姓氏是什么?[jinmiaozhang]:您的组织单位名称是什么?[zhx]:您的组织名称是什么?[zhx]:您所在的城市或区域名称是什么?[beijing]:您所在的省/市/自治区名称是什么?[beijing]:该单位的双字母国家/地区代码是什么?[CHINA]: 86CN=jinmiaozhang, OU=zhx, O=zhx, L=beijing, ST=beijing, C=86是否正确?[否]: y输入 <tomcat> 的密钥口令(如果和密钥库口令相同, 按回车):C:\Users\admin>
在当前目录下可以看到生成了.keystore文件。
2、Springboot配置SSL
添加index.html到src/main/resources/static下,作为测试。
将.keystore文件复制到项目根目录,在application.properties中做如下SSL配置:
server.port=8443server.ssl.key-store=.keystoreserver.ssl.key-store-password=123456server.ssl.key-store-type=JKSserver.ssl.key-alias=tomcat
启动:Tomcat started on port(s): 8443 (https)
访问:https://localhost:8443/
3、http转向https
输入http地址栏会自动转向HTTPS,实现此功能需配置TomcatEmbeddedServletContainerFactory,并添加Tomcat的connector来实现。
@SpringBootApplicationpublic class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);System.out.println("启动成功");}@Beanpublic EmbeddedServletContainerFactory servletContainer() {TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {@Overrideprotected void postProcessContext(Context context) {SecurityConstraint securityConstraint = new SecurityConstraint();securityConstraint.setUserConstraint("CONFIDENTIAL");SecurityCollection collection = new SecurityCollection();collection.addPattern("/*");securityConstraint.addCollection(collection);context.addConstraint(securityConstraint);}};tomcat.addAdditionalTomcatConnectors(httpConnector());return tomcat;}@Beanpublic Connector httpConnector() {Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");connector.setScheme("http");connector.setPort(8080);connector.setSecure(false);connector.setRedirectPort(8443);return connector;}}
控制台: Tomcat started on port(s): 8443 (https) 8080 (http)
此时访问:http://localhost:8080/ 会跳转到 https://localhost:8443
#关闭favicon,默认开启
spring.mvc.favicon.enabled=false
1、自定义Favicon
将favicon.ico(文件名固定不能变)放到类路径根目录下、类路径META-INF/resources/下、类路径resources/下、类路径static/下或类路径public/下。
为浏览器和服务端提供了双工异步通信的功能,即浏览器可以向服务器发送消息,服务器也可以向浏览器发送消息。