Show jsp page inside jar file using Spring MVC

2019-03-11 12:37发布

问题:

I'm developing a web application in java using Spring MVC 3.2.2. I'm having problems loading jsp page from within the jar file.

The Sring MVC web application that the following structure:

|-META-INF
|-WEB-INF
    |-spring
    |    |- app-config.xml
    |-classes
    |-lib
    |   |-external.jar
    |       |-WEB-INF
    |       |   |-views
    |       |       |-external.jsp
    |       |-classes
    |            |-controller-for-external.class
    |-views
        |-... jsp

Config in app-config.xml

    <context:annotation-config />
<context:component-scan base-package="com" />

<bean id="viewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass"
        value="org.springframework.web.servlet.view.JstlView"></property>
    <property name="prefix" value="/WEB-INF/views/"></property>
    <property name="suffix" value=".jsp"></property>
</bean>
<mvc:resources mapping="/views/**" location="classpath:/WEB-INF/views/" />
<mvc:annotation-driven />

Controller for external.jsp

   @Controller
    public class ExternalController {
protected final Log logger = LogFactory.getLog(getClass());

@RequestMapping(value="/external.htm")
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    Map<String, Object> myModel = new HashMap<String, Object>();
    myModel.put("msg", "External page loaded");
    return new ModelAndView("external", "model", myModel);
}

}

web.xml file

    <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

<display-name>Springapp</display-name>
<servlet>
    <servlet-name>springapp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/app-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/app-config.xml</param-value>
</context-param>

<servlet-mapping>
    <servlet-name>springapp</servlet-name>
    <url-pattern>*.htm</url-pattern>
</servlet-mapping>
</web-app>

When a try to show external.jsp page, spring don't want search it and show error HTTP 404 - /springapp/WEB-INF/views/external.jsp

回答1:

You can do this if you are using Servlet 3.0. However, it won't work with the way you have your JSPs packaged. You have to package resources into a JAR file in a specific way:

  • Put all your JSPs in the META-INF/resources directory of your JAR.
  • Include a web-fragment.xml file in META-INF. This is similar to a typical web.xml with some differences. See here for some details. There is also an example I found here. This is optional.
  • Put your JAR in WEB-INF/lib of your WAR.

Now you should be able to refer to those JSPs within your app's context. Basically META-INF/resources is mapped to the document root of your webapp. Look at this for more details. Keep in mind that this is not limited to JSPs. You can put images, JavaScript, or even CSS in there.



回答2:

Thanks Vivin for your solution. It worked for me.

In my case, I had:

testModule.jar

    test/
        TestModule.class
    META-INF/
        resources/
            WEB-INF/
                views/
                    testModule.jsp
        MANIFEST.MF
        web-fragment.xml (empty)
    WEB-INF/
        lib/

testProject.war

    test/
        ...
    META-INF/
        MANIFEST.MF
    WEB-INF/
        spring/
            ... spring configs ...
        views/
            test.jsp
        lib/
            testModule.jar
        web.xml

It may be important to say that Servlet 3.0 do not handle fragments on an Eclipse deployment scenario in Glassfish 3.1.2 (it maybe works in JBoss or others, to be confirmed). Actually, I set testModule.jar in deployment assembly of testProject.war and when I deploy through Eclipse, it generates a folder testModule.jar instead of a JAR file.

But it's working when exporting as a WAR.

EDIT:

To get it working with Eclipse deployment, you have to check an option in Glassfish 3.1.2 properties : Deploy as jar. I think it's a recent option implemented in the last plugin version. Visible on Kepler but not on Juno.



回答3:

I did it using Vivin's solution. Here's the folder structure of my JAR in Eclipse.

Included the jar in the WEB-INF/lib folder of my WAR:

Also added the following in my pom.xml of WAR:

 <configuration><packagingIncludes>WEB-INF/lib/*.jar</packagingIncludes>
 </configuration>

Included the jsp in my Web Project using :

<jsp:include page="/myService.jsp" flush="true" />


回答4:

Structure works for me

jar module (jar)

main web app module (war)

And ViewResolver config (I'm using Thymeleaf):

@Bean
public ServletContextTemplateResolver templateResolver() {
    ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
    resolver.setPrefix("/WEB-INF/template/");
    resolver.setSuffix(".html");
    resolver.setTemplateMode("HTML5");
    resolver.setOrder(1);
    return resolver;
}