简体   繁体   中英

Servlets and JSPs. A simple request?

I have a number of Java Server Pages set up already and I would like to use a Controller/View system by adding a Process Servlet (which extends HttpServlet).

I just want to basically process the requested JSPs as normal after the ProcessServlet has added some attributes.

Say all my JSPs are in a directory called /content/ and my web.xml file has a rule to map /content/*.jsp to my ProcessServlet

I have not been able to find a way short of moving all of my JSPs into a different directory (/content-JSPs/) so that they can be dispatched to without having to go through the ProcessServlet endlessly.

Is there a way to basically dispatch#forward() (some other method?) to the requested JSP without having it go through the ProcessServlet again?

It's a bit hard to believe that this lack of flexibility exists. Why can't the Servlet just act as a pass through to the JSP?

My goal here is to set everything up so that the web server does not have to have a separate directory for all JSPs and another directory for everything else ie CSS, JavaScript and images. I would like to keep the directory structure (and URL structure) as it is.

Put them in /WEB-INF folder. This also effectively hides JSPs away from direct access. You only need to change the RequestDispatcher#forward() call to include /WEB-INF in the path.

request.getRequestDispatcher("/WEB-INF/content" + request.getPathInfo()).forward(request, response);

Please note that the URL pattern of /content/*.jsp is syntactically invalid. It should be /content/* . Perhaps you have also really used that. To skip static resources like images/css/JS, you should just not put them in /content , but in for example /resources , /static , etc.

Related:

You can also use Sevlet Filter instead of Servet. This is a good option if your servlet only adds some parameters to request. And you don't have to manually dispatch your request to JSP.

Why not, instead of mapping to *.jsp, map to something like *.page (or whatever term you like), and then your process servlet can do its processing, and replace the .page with .jsp and instruct the RequestDispatcher to forward() to that page.

As long as all links on the pages, that you wish to go through the ProcessServlet, use the .page name, then it will probably work.

As many have suggested its better to use Filters in this case.

Put following snippet into web.xml

Filter definition

<filter>
    <filter-name>ProcessFilter</filter-name>
    <filter-class>my.filter.ProcessFilter</filter-class>
</filter>

Filter mapping

<!-- Map all ".jsp" that should go through the filter-->
<filter-mapping>
    <filter-name>ProcessFilter</filter-name>
    <url-pattern>/content/*.jsp</url-pattern>
</filter-mapping>

<!-- If you have Any servlets that needs to go through ProcessFilter -->
<filter-mapping>
    <filter-name>ProcessFilter</filter-name>
    <servlet-name>MyServlet</servlet-name>
</filter-mapping>

OncePerRequestFilter

If you would want to execute the filter only once you could store an attribute in request scope for the first time, and next time you could check if the attribute is set in which case do not process further.

If you are using Spring framework you can either use one of the sub classes of OncePerRequestFilter or extend it and just implement doFilterInternal() .

Otherwise you could refer to OncePerRequestFilter.java : raw and implement/extend your filter.

Here is a simplified version of it.

 public class ProcessFilter extends Filter {

public final void doFilter(ServletRequest request, ServletResponse response, 
           FilterChain filterChain)
        throws ServletException, IOException {

    if (!(request instanceof HttpServletRequest) || 
                !(response instanceof HttpServletResponse)) {
        throw new ServletException("OncePerRequestFilter just supports HTTP requests");
    }
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;

    String alreadyFilteredAttributeName = "ALREADY_PROCESSED_BY_PROCESS_FILTER";
    if (request.getAttribute(alreadyFilteredAttributeName) != null) {
        // Proceed without invoking this filter...
        filterChain.doFilter(request, response);
    }
    else {
        // Do invoke this filter...
        request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
        try {
            doFilterInternal(httpRequest, httpResponse, filterChain);               
        }
        finally {
            // Remove the "already filtered" request attribute for this request.
            request.removeAttribute(alreadyFilteredAttributeName);
        }
    }
}

    protected void doFilterInternal(
        HttpServletRequest request, HttpServletResponse response, 
                    FilterChain filterChain) {
        throws ServletException, IOException
                            /*
                             *
                             *  
                             *  Put your processing logic here
                             *
                             *
                             */
    }

}

据我说,您应该尝试在web.xml中使用<filter>来使一些请求绕过servlet。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM