一种解决SpringBoot无法读取js/css静态资源的新方法

作为依赖使用的SpringBoot工程很容易出现自身静态资源被主工程忽略的情况。但是作为依赖而存在的Controller方法却不会失效,我们知道,Spring MVC对于静态资源的处理也不外乎是路径匹配,读取资源封装到Response中响应给浏览器,所以,解决的途径就是自己写一个读取Classpath下静态文件并响应给客户端的方法。

对于ClassPath下文件的读取,最容易出现的就是IDE运行ok,打成jar包就无法访问了,该问题的原因还是在于getResources()不如getResourceAsStream()方法靠谱。

本就是SpringBoot的问题场景,何不用Spring现成的ClassPathResource类呢?

ReadClasspathFile.java

public class ReadClasspathFile {
    public static String read(String classPath) throws IOException {
        ClassPathResource resource = new ClassPathResource(classPath);
        BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream(),"UTF-8"));
        StringBuilder builder = new StringBuilder();
        String line;
        while ((line = reader.readLine())!=null){
            builder.append(line+"\n");
        }
        return builder.toString();
    }
}

接下来就是Controller层进行映射匹配响应了,这里利用Spring MVC取个巧,代码如下:

    @ResponseBody
    @RequestMapping(value = "view/{path}.html",produces = {"text/html; charset=UTF-8"})
    public String view_html(@PathVariable String path) throws IOException {
        return ReadClasspathFile.read("view/"+path+".html");
    }

    @ResponseBody
    @RequestMapping(value = "view/{path}.js",produces = {"application/x-javascript; charset=UTF-8"})
    public String view_js(@PathVariable String path) throws IOException {
        return ReadClasspathFile.read("view/"+path+".js");
    }

通过后戳(html、js)进行判断,以应对不同的Content-Type类型,静态资源的位置也显而易见,位于resources/view下。

最后就是使用缓存进行优化了,如果不加缓存,那么每次请求都涉及IO操作,开销也比较大。关于缓存的设计,这里使用WeakHashMap,代码如下:

public class ReadClasspathFile {
    
    private static WeakHashMap<String,String> map = new WeakHashMap<>();
    
    public static String read(String classPath) throws IOException {
        //考虑到数据的一致性,这里没有使用map的containsKey()
        String s = map.get(classPath);
        if (s!=null){
            return s;
        }
        ClassPathResource resource = new ClassPathResource(classPath);
        BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream(),"UTF-8"));
        StringBuilder builder = new StringBuilder();
        String line;
        while ((line = reader.readLine())!=null){
            builder.append(line+"\n");
        }
        //DCL双检查锁
        if (!map.containsKey(classPath)){
            synchronized (ReadClasspathFile.class){
                if (!map.containsKey(classPath)){
                    map.put(classPath,builder.toString());
                }
            }
        }
        return builder.toString();
    }
}
posted @ 2019-05-07 11:36 像风一样i 阅读(...) 评论(...) 编辑 收藏