Managing HTML resources (CSS, JS files) in Spring

2020-06-28 01:31发布

问题:

Is it possible to manage HTML resources in Spring MVC similar to grails-resources?

Similar to this : http://www.anyware.co.uk/2005/2011/09/12/optimising-your-application-with-grails-resources-plugin/

For example : In Grails, modules is specified as

modules = {  
     common {  
        resource url:"css/main.css"  
        resource url:"js/jquery.js"  
     }  
}

and in HTML, this tag is specified with module name to load all files.

<r:require module="common"/>

So I was wondering is there any way I can do similar kind of stuff in Spring MVC with <mvc:resources> or any other option?

回答1:

Short answer: surely. But I think the real question is "how?" :)

Spring MVC is the base that Grails built on, so it can do what Grails can do. Grails-resources is just an utility that Grails make to help developing works easier. If you want to do the same in Spring, you must do some work.

Firstly, Spring MVC has a way to expose resources (reference, Chapter 17.15.6, "Configuring Serving of Resources"); for example:

<mvc:resources mapping="/images/**" location="/images/"/>

The above line expose every files in [Web folder]/images/ as resource and can be requested by web browsers.

Second, to embed the resource into HTMLs as easy like Grails, you must combine Spring with some other view technologies, like sitemesh, freemarker/velocity/JSP... (which Grails do behind the scene for you). Instead of grails tag, now you have freemarker's or Velocity's macros. But I would recommend writing some of your own custom macros, since the built-in one is not always good.

I have used both Grails and Spring MVC. I appreciate Grails' effort to make developer life easier, but with Spring things are a bit different. With Spring, you'll get to write some more code, make some more choices (in Grails they were chosen for you as "default", and is "invisible" if you don't want to customize). As the pay-off, you are forced to be more awared with the under-lying mechanism, which is a good thing.

I have used sitemesh for layout, and freemarker as a HTML-rendering engine for several web projects, and they works pretty well.


UPDATE:

I want to make clear that mvc:resources is not the full answer to your problem. It's just the part of exposing the web resources out for browsers to get. With Grails, this is already made by default, but it's not true for Spring. You must specify that the content in folder 'images' are resources, and they can be accessed by the url http://your-domain-name/context-name/images/image-name . As saying, Spring is a lot more explicit than Grails.

Another thing is template engine. Library Sitemesh is a popular choice when working with Spring (it's also the default for Grails), so it isn't a lot different (mostly it's about syntax). The main purpose of template engine is to "fill in" your htmls with dynamic data, and I'm going to show you... a bit of it.

Please be aware that, to make a tutorial that fulfill your example is exceed the scope of an answer. Also, Spring enable many relevant solutions, which means different developers may have different way of organization/ config. But to give you a feeling, I'll make a quick example (I'm using freemarker to make this example):

In file: common.ftl, I have:

<#macro commonInclude>
<script type="text/javascript" src="${rc.getContextUrl('/js/jquery.js')}"></script>     
<link rel="stylesheet" type="text/css" href="${rc.getContextUrl('css/main.css')}" />
</#macro>

With a little more config, then in view files I can call:

<@common.commonInclude />

And it will render the code you want.

As you see, the main difference is their syntax. Grails allow a cleaner style, while Spring give you a more "explicit" style which will benefit if you want to customize things.

  • Bonus: If you are looking for a replacement for Grails layout, take a quick search for "Spring and Sitemesh" and you may find it.


回答2:

grails-app/conf/spring/resources.groovy

import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler

// Place your Spring DSL code here
beans = {

    resourceHttpRequestHandler(ResourceHttpRequestHandler) {
        locations = ['file:/D:/fupload/']
    }

    resourceHandlerAdapter(HttpRequestHandlerAdapter)

    resourceHandlerMapping(SimpleUrlHandlerMapping) {
        urlMap = ['/fupload/**':'resourceHttpRequestHandler']
    }
}