侧边栏壁纸
博主头像
浅醉谷博主等级

行动起来,活在当下

  • 累计撰写 6 篇文章
  • 累计创建 10 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

SpringMvc静态资源访问

浅醉
2024-06-01 / 0 评论 / 1 点赞 / 49 阅读 / 7995 字 / 正在检测是否收录...

问题

1 springboot中无法访问到静态资源

2 springboot中/favicon.ico 这个静态资源无法访问到,报错500

背景介绍

在项目时,由于权限问题,所以给项目添加了登录验证拦截器:导致静态资源方式失败。

拦截器代码如下:

public class LoginHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截路径:" + request.getRequestURI());
        //登录成功后,应该有用户的session
        Object loginUser = request.getSession().getAttribute("loginUser");
        if (loginUser == null) {//没有登录
            request.setAttribute("msg", "没有权限,请先登录");
            request.getRequestDispatcher("/login").forward(request, response);
            return false;
        } else {
            return true;
        }
    }
}

配置类引入方式如下:

@Component
@Configuration
public class CustomWebMvcConfigSupport extends WebMvcConfigurationSupport {

    /**
     * //为什么以继承 WebMvcConfigurationSupport 的方式会拦截静态资源,而实现WebMvcConfigurer的接口方式不会拦截?
     * 1 springmvc的自动配置类 WebMvcAutoConfiguration 中会添加一些默认配置,其中就包含:
     *  默认的静态资源位置路径:spring.resources.static-locations=classpath:/static/
     *  默认的静态资源请求匹配路径:spring.mvc.static-path-pattern=/**
     * 2 但是看其源码上有个条件配置注解为: @ConditionalOnMissingBean(WebMvcConfigurationSupport.class),当
     *  上下文中不存在WebMvcConfigurationSupport时,该自动配置才生效,如果我们自己继承并实现了该类,则所有springmvc
     *  的默认配置失效。
     * 3 一旦springmvc默认配置失效,就不知道静态资源的位置路径和请求匹配路径了,此时就需要实现其addResourceHandlers 和 addInterceptors
     *  分别设置静态资源位置路径和请求是匹配放行路径。
     * @param registry 拦截器注册
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginHandlerInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns(
                        "/","/login/**","/error/**","/page/**",
                        "/css/**", "/js/**", "/images/**", "/iconfont/**","/effect/**","/favicon.ico");
        super.addInterceptors(registry);
    }
}

页面访问静态资源情况:

所有的静态资源都被拦截了

但是查看项目目录是可以看到资源位置没有错误:

原因分析

路径404,说明找不到静态资源的位置,但是在WebMvcAutoConfiguration这个自动配置类中,不是有静态资源路径的默认配置吗?

继续查看WebMvcAutoConfiguration这个类的注解发现:有个条件配置为,该自动配置类只有在WebMvcConfigurationSupport.class

不存在时才会生效,那问题就清晰了,由于我自己实现了WebMvcConfigurationSupport,导致springboot的这个自动配置类失效了,从而不会自动配置静态资源的路径了。那就需要自己添加配置告知静态资源的位置在哪?


处理方式:

修改自定义配置类代码如下:实现addResourceHandlers(ResourceHandlerRegistry registry) 接口,配置资源路径:

@Component
@Configuration
public class CustomWebMvcConfigSupport extends WebMvcConfigurationSupport {

    /**
     * //为什么以继承 WebMvcConfigurationSupport 的方式会拦截静态资源,而实现WebMvcConfigurer的接口方式不会拦截?
     * 1 springmvc的自动配置类 WebMvcAutoConfiguration 中会添加一些默认配置,其中就包含:
     *  默认的静态资源位置路径:spring.resources.static-locations=classpath:/static/
     *  默认的静态资源请求匹配路径:spring.mvc.static-path-pattern=/**
     * 2 但是看其源码上有个条件配置注解为: @ConditionalOnMissingBean(WebMvcConfigurationSupport.class),当
     *  上下文中不存在WebMvcConfigurationSupport时,该自动配置才生效,如果我们自己继承并实现了该类,则所有springmvc
     *  的默认配置失效。
     * 3 一旦springmvc默认配置失效,就不知道静态资源的位置路径和请求匹配路径了,此时就需要实现其addResourceHandlers 和 addInterceptors
     *  分别设置静态资源位置路径和请求是匹配放行路径。
     * @param registry 拦截器注册
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginHandlerInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns(
                        "/","/login/**","/error/**","/page/**",
                        "/css/**", "/js/**", "/images/**", "/iconfont/**","/effect/**","/favicon.ico",
                        "/hystrix/**");
        super.addInterceptors(registry);
    }

    /**
     * 添加静态资源处理器路径匹配和资源位置路径
     * @param registry 资源处理器注册
     */
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/resource/")
                .addResourceLocations("classpath:/static/")
                .addResourceLocations("classpath:/public/");
        super.addResourceHandlers(registry);
    }
}

再次访问页面:静态资源获取正常

另一种处理方式:直接实现WebMvcConfigurer

实现该接口不会导致WebMvcAutoConfiguration的自动配置失效,所以只需要配置需要排除哪些路径不拦截即可。


@Component
@Configuration
public class CustomWebMvcConfig implements WebMvcConfigurer {

    /**
     * //为什么以继承 WebMvcConfigurationSupport 的方式会拦截静态资源,而实现WebMvcConfigurer的接口方式不会拦截?
     * 1 springmvc的自动配置类 WebMvcAutoConfiguration 中会添加一些默认配置,其中就包含:
     *  默认的静态资源位置路径:spring.resources.static-locations=classpath:/static/
     *  默认的静态资源请求匹配路径:spring.mvc.static-path-pattern=/**
     * 2 但是看其源码上有个条件配置注解为: @ConditionalOnMissingBean(WebMvcConfigurationSupport.class),当
     *  上下文中不存在WebMvcConfigurationSupport时,该自动配置才生效,如果我们自己继承并实现了该类,则所有springmvc
     *  的默认配置失效。
     * 3 一旦springmvc默认配置失效,就不知道静态资源的位置路径和请求匹配路径了,此时就需要实现其addResourceHandlers 和 addInterceptors
     *  分别设置静态资源位置路径和请求是匹配放行路径。
     *
     * @param registry 拦截器注册
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginHandlerInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns(
                        "/","/login/**","/error/**","/page/**",
                        "/css/**", "/js/**", "/images/**", "/iconfont/**","/effect/**","/favicon.ico",
                        "/hystrix/**");
    }
}

小插曲:

大家义看到我在排除的路径中有个/favicon.ico这个,但是页面访问该路径时却报错500了?

原因分析:

找了好久没找到原因,后来直接打开了日志的root的debug等级。

logging.level.root=DEBUG

再一次请求的时时候,看日志发现:服务器把这个请求到当做是一个访问页面被路由到了我的PageController里(具体的日志信息没有复现出来☹,可能是中间修改的东西太多了),然后调整这个路径模式加了前缀@RequestMapping("/page/{page}")

修改后访问正常:

1

评论区