简体   繁体   中英

Struts 2, multiple views and jQuery - How do I reuse common code?

I've read most of the online resources for building a simple "Hello World" app using Java and Struts 2. I understand the simple stuff. My problem is that I'm trying to expand that learning and build a large scale app, and I just don't see how to connect the dots.

Scenario: I've got three views to begin with: Home.jsp, MyAccount.jsp, Contact.jsp. Each has the following HTML:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>

<html>
    <head>
        <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <script type="text/javascript" src="js/common.js"></script>
        ...
    </head>
    <body>
        <!-- If logged in, says "hello <s:property name="username">"
             Else displays link to .show() #loginPane -->
        <div id="accountHeader">...</div>

        <!-- Displays <s:textfield> tags and <s:submit> tag to accept username and password -->
        <div id="loginPane" style="display: none">...</div>

        <header>...</header>

        <nav>...</nav>

        <!-- Displays view-specific content that includes Struts 2 tags -->
        <div id="content">...</div>

        <footer>...</footer>
    </body>
</html>

So, obviously there is a lot of code common to each view (anything not in #content div).

How do I architect these views for code reuse?

What I've tried:

  • Placing common code in common.js and using jQuery .html() calls to populate <div> s. [ Doesn't work because jQuery cannot generate code with <s:> tags. ]

  • Using only one .jsp view file and placing view-specific code in common.js to be generated with jQuery .html() calls. [ Doesn't work for the same reason -- jQuery cannot generate code with <s:> tags. ]

  • Placing all view components in .jspf files and loading each with jQuery .load() calls from common.js. [ Doesn't work -- I'm guessing the .jspf files need the Struts 2 <%taglib ...%> included in each, but jQuery .load() treats the <%taglib ...%> as text to be displayed in the <div> ... and also fails to properly generate the <s:> tags. ]

What is the proper way to do this? How do I architect my view(s) for code reuse?

My apologies if this isn't the proper forum to ask for architecture help, but I'm really struggling here... Perhaps point me to a more appropriate forum or an online tutorial that addresses this type of architecture?

Thanks in advance!

I've used several methods to accomplish this type of re-use of code including Tiles and tooling around with Sitemesh and other template frameworks. What I've found is that, much as Steven Benitez, in the end I preferred to use JSP taglibs, native Struts2 taglibs, and JSTL to essentially build out my own templating routines. The main reason I prefer this is that there tends to be less overhead and it's been a lot easier to maintain and extend in the long run.

Generally What I do is define my base template, index.jsp for example, and then in each independent Struts controller class I will define what page fragment is used. I try to split my controllers up in such a way that each page or function is handled by a single controller and I implement the Preparable interface. This way I can set a parameter for the page to reference. Sometimes I set it as a variable in the controller class, sometimes a sessions variable depending on what type of stating I need for the application.

Once I have a variable with the page to reference, I can just use a JSTL import or Struts include tag to load the page fragment.

The controller class would look something like this:

@Results({
    @Result(name = "success", location = "/WEB-INF/content/index.jsp")
})
public class IndexController extends RestActionSupport implements Preparable{
    private String page;
    private String pageTitle;

    @Override
    public void prepare() throws Exception {
        page = "home";
        pageTitle= "My Home Page";
    }
    ...
}

And then the JSP would look something like this:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="s" uri="/struts-tags"%> 
<html>
    <head>
        <title> ${pageTitle}</title>
    </head>

    <body>
        <c:import url="${page}.jsp" />
    </body>
</html>

EDIT: Fragment page example:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="s" uri="/struts-tags"%>

<div>
    <h1>Welcome Home!</h1>
</div>

<script type='text/javascript'>
    $(document).ready(function() {
        // page specific scripting if needed
    );
</script>

You can encapsulate common template code in JSP tag files, as explained in this answer or you can also use decorator frameworks such as Tiles or SiteMesh to do this.

Personally, I prefer JSP tag files. Do not attempt to write out HTML with jQuery or to put all of your code into a single JSP.

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