最近在学习spring boot,刚好遇到一个需求比较简单的项目,就拿新搭好的框架(springboot + druid + mybatis + mybatis-generator)来练手,因为有前端接口和后台管理两个部分,按照以前使用springmvc的习惯,我想设置多个dispatcherservlet实现前端接口和后台管理端路径规则的分离,并分别添加拦截器,在这个过程中遇到了一些问题,折腾好久后终于解决,特此记录。
1、配置多个DispatcherServlet:spring boot 提供了ServletRegistrationBean这个bean专门来注册servlet,可以像注册bean一样注册servlet,具体的在启动类Application中注册即可,如下:
@Bean
public ServletRegistrationBean backServlet() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.scan("com.wc.h5case.controller.back");
applicationContext.register(BackServletConfig.class);
dispatcherServlet.setApplicationContext(applicationContext);
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet, "/manager/admin/*");
servletRegistrationBean.setLoadOnStartup(1);
// 这一句很关键,因为name相同的只有一个会生效,后面注册的会覆盖前面的
servletRegistrationBean.setName("back");
return servletRegistrationBean;
}
2、添加拦截器,为后台管理添加登录拦截器,中间遇到个小插曲,就是自定义了配置文件,在注入拦截器的时候报错空指针,查了资料发现需要将自定义的拦截器注册到spring bean中,启动时拦截器才能取到配置的值。
/**
* 将自定义拦截器注册到spring bean中
* 解决拦截器中Bean无法注入的问题(配置信息无法注入AdminProperties)
*/
@Bean
public AdminLoginInterceptor adminLoginInterceptor() {
return new AdminLoginInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 拦截器按照顺序执行
registry.addInterceptor(adminLoginInterceptor()).addPathPatterns("/manager/admin/*");
}
3、以上两步完成在测试的时候发现一件很神奇的事情,controller.back包中增加了个测试类,我以为只有/manager/admin/test/index.do才能访问,结果发现直接/test/index.do也可以,这就不好玩了,达不到效果,这时候可以把默认的DispatcherServlet禁用掉
// exclude 把默认的匹配规则/去掉
@SpringBootApplication(exclude=DispatcherServletAutoConfiguration.class)
4、这一设置,上面的目的是达到了,但又出现个新问题,静态资源访问不到了,于是按照网上的做法开始折腾,重写了addResourceHandlers方法,如下:
/**
* 配置类,自定义拦截器
*/
@Configuration
public class RunWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
WebMvcConfigurer.super.addResourceHandlers(registry);
}
}
结果直接访问/css/index.css还是访问不到,/manager/admin/css/index.css倒是可以,这还是有点逼死强迫症的,如鲠在喉,后面想想是不是再加个专门访问静态资源的DispatcherServlet就可以解决问题了,于是乎试了一波:
@Bean
public ServletRegistrationBean resourceServlet() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
dispatcherServlet.setApplicationContext(applicationContext);
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet);
servletRegistrationBean.addUrlMappings("*.css", "*.js", "*.ttf", "*.png", "*.jpg", "*.gif", "*.woff", "*.woff2");
servletRegistrationBean.setLoadOnStartup(1);
servletRegistrationBean.setName("resource");
return servletRegistrationBean;
}
到这里,确实可以实现我最初的设想和需求,但总觉得有些麻烦,哪位大佬若有其他解决方式,欢迎留言探讨。