SpringBoot的默认启动时,对资源拦截的控制台信息如下:
2018-04-13 10:02:30.090 INFO 78908 --- [ restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-04-13 10:02:30.090 INFO 78908 --- [ restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-04-13 10:02:30.157 INFO 78908 --- [ restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
其中Spring Boot 默认将 /** 所有访问映射到以下目录:
classpath:/static
classpath:/public
classpath:/resources
classpath:/META-INF/resources
其中默认配置的 /webjars/** 映射到 classpath:/META-INF/resources/webjars/
那么当我们自己来实现对静态资源进行拦截控制的时候,就需要在控制类中进行@Configuration注解的配置,与此同时增加@EnableWebMvc,增加该注解之后,默认的WebMvcAutoConfiguration中配置就不会生效,就需要自己完成每一项的控制。当然如果你要更加细粒度以及控制的更精确,那肯定是要对WebMvcAutoConfiguration类了解的更加深入。
控制类代码如下:
@Configuration
@EnableWebMvc //这个注解使得默认配置失效
public class DefineAdapter extends WebMvcConfigurerAdapter implements ApplicationContextAware {
private static final Log logger = LogFactory.getLog(DefineAdapter.class);
private ApplicationContext applicationContext;
public DefineAdapter(){
super();
}
@Bean
public ViewResolver viewResolver() {
logger.info("ViewResolver");
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
@Override
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
System.out.println("setApplicationContext方法");
this.applicationContext = applicationContext;
}
//这里是实现用户拦截的具体操作,类LoginInterceptor是用户登录拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
System.out.println("addInterceptors方法");
/*
* 多个拦截器组成一个拦截器链
* excludePathPatterns 用户排除拦截
* addPathPatterns 用于添加拦截规则
* 拦截规则:除了"/show/getLogin" 其他都拦截
* */
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/show/getLogin");//多个排除拦截的话,只需要用逗号隔开即可
//这边还可以加好几个拦截器组成拦截器链
super.addInterceptors(registry);
}
//可以方便的将一个请求映射成视图,无需书写控制器,addViewCOntroller("请求路径").setViewName("请求页面文件路径")
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/show/getLogin").setViewName("login");
}
//自定义资源拦截路径可以和springBoot默认的资源拦截一起使用,但是我们如果自己定义的路径与默认的拦截重复,那么我们该方法定义的就会覆盖默认配置
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//这里也可以采用ResourceUtils.CLASSPATH_URL_PREFIX 它是:classpath:
registry.addResourceHandler("/images/**").addResourceLocations("classpath:/WEB-INF/resources/images/");
registry.addResourceHandler("/js/**").addResourceLocations("classpath:./WEB-INF/resources/js/");
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/WEB-INF/resources/css/");
super.addResourceHandlers(registry);
}
}
用户登录拦截器:LoginInterceptor
@Service
public class LoginInterceptor extends HandlerInterceptorAdapter{
protected static final Log logger = LogFactory.getLog(LoginInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException{
logger.info("------preHandle------");
//获取session
HttpSession session = request.getSession(true);
//判断用户Name是否存在,不存在就跳转到登录界面
if(request.getParameter("userName") == null){
//System.out.println("这是路径地址:"+request.getRequestURI());
response.sendRedirect("/show/getLogin");
return false;
}else{
session.setAttribute("userName", session.getAttribute("name"));
return true;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println(">>>LoginInterceptor>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println(">>>LoginInterceptor>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)");
}
}
界面访问的控制器:PageController
@Controller
@RequestMapping(value = "/show")
public class PageController {
@RequestMapping("/getEditJsp")
public String editJsp(ModelMap map) {
return "editUser";
}
@RequestMapping(value = "/getLogin")
public String loginJsp(ModelMap map) {
return "login";
}
}
当我输入localhost:端口号/show/getEditJsp时候会被拦截,进行判断Session中的内容是否为空,空就跳转到登录界面,此时这边还涉及到了重定向带来的js,css等静态资源无法显示的问题:
配置文件中请如下配置:
resources:
#静态资源扫描
static-locations: classpath:/WEB-INF/resources/
当然这个要和原本DefineAdapter中的静态资源拦截一起配合使用,这是我的项目界面和静态资源存放目录:
那么界面中静态资源的引用如下:
<script src="../js/jquery/jquery-2.1.3.min.js"></script>
<script src="../js/bootstrap/bootstrap.js"></script>
<script src="../js/bootstrap/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="../css/bootstrap.min.css"/> <script type="text/javascript" src="../js/hello.js"></script>
那好,用户拦截以及重定向静态资源都已解决,但是如果你看我上一章搭配BootStrap使用会发现,原本我使用bootStarp和jquery都是使用maven进行版本管理的,为何现在是手动将js,css文件放置在文件夹下。这个问题是这样的,原本我采用maven进行管理的时候,当用户被拦截重定向到登陆界面之后,我的静态资源一直无法正常显示,试了很多方式,但是好像都没有很好的解决方式,我也不知道怎么解决,如果哪位同志能很好的解决这个问题,欢迎在下面评论以及私聊。
springBoot管理的bootStrap和jquery默认放在resources文件夹下的static的webjars文件夹中,在界面的引用如下:
<script src="/webjars/jquery/jquery.min.js"></script>
<script src="/webjars/bootstrap/js/bootstrap.min.js"></script><link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.min.css"/>
我在DefineAdapter中的静态资源拦截是如下配置:
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/static/webjars/");
在application.yml中,我也尝试了资源的路径配置,也尝试过没去配置,反正都没有显示,试了两天了也没出效果,所以在此集思广益