Simplified Design Using Servlet APIs
Http://www.ibm.com/developerworks/cn/java/j-pureserv/
Introduction:For Web Pages with dynamic content, you can use the assumerver Pages (JSP) technology
The work of the designer is separated. Unfortunately, JSP is too complex for many designers, so Java developers have to handle JSP by themselves
Code, which often produces unsatisfactory results. This article demonstrates an unorthodox alternative: by using a simple helper object, the Web
Interface.
The purpose of designing JSP is to separate the tasks of Web developers from those of non-developers who design the dynamic page UI. Unfortunately, JSP
It is too complicated for many designers, and the software layer added to solve various dynamic content problems makes them very tricky. (For example, the international domain requires that text be stored elsewhere and referenced by keys .) So
For most projects, Java developers have to process their own JSP code, which often includes the work of the designers, so that their energy is consumed by the tag Library and other things, and they cannot concentrate on
Java code.
Unlike the orthodox method, you can use a simple helper object to build a simple and beautiful Web Interface Based on the conventional servlet. This article explains how to use standard
Write the view output of dynamic Web pages in Java format. I will explain the benefits of this approach and use a scoring application to demonstrate this approach, which manages an NCAA February March avid bonus pool.
HTML is dynamic
ThisServlet onlyThe method is very simple. It involves a servlet base class and a custom writer object, servlet
Subclass uses this object to generate output. The code is concise, because most HTML is encapsulated in the helper Object method and can be rewritten as needed. Code reuse is always pleasant, and most
Websites share many HTML pages, so reuse should be an important consideration. HTML output methods generate intuitive and compact servlet
Code, so the maintainability is very high, which makes the maintenance cost of the Code almost directly proportional to the code size. By Rewriting the JSP interface into a pure servlet, you can reduce the code by 2/3.
For example, to output a link based on user permissions, the following lengthy construction code is required:
<c:if test="${user.permission[ sessionScope.ConstantMap[ EDIT_WIDGET ] ] != 0}"> <c:url var="editUrl" value="/EditWidget.jsp"/> <div class="navigation"><a href="<c:out value="${editUrl}"/>">Edit this widget</a></div> </c:if> |
By using the Java syntax, the code is much simpler:
if (user.getPermission(Constants.EDIT_WIDGET) != 0) out.printNavlinkDIV("/EditWidget.jsp", "Edit this widget"); |
In addition, getting and outputting Business Objects in the same place, rather than passing them through request objects, this saves a lot of code. Conciseness is beautiful.
Using JSP and other view technologies may be the biggest headache in Web development. JSP pages are not HTML, XML, or Java
Code, assumerver Pages Standard Tag
Library (JSTL) code or Expression Language (EL), but a hodgedge of these things. JSP
The code is not just a strange combination, and every abstraction layer brings new obstacles to development. For example
Page debugging is just as difficult as exploration. You know that something is wrong, but you cannot find the location where the problem occurs. Although the mysterious error message points out the line number, this line number is often not the problem.
.
JSP technology cannot expand the base class, so code reuse can only be achieved through bean,include
File and custom tag library. The tag library is too cumbersome and is not suitable for effective reuse. It is very troublesome to maintain an XML file for each API modification you have made, and "tag design is a language design" (see Noel Bergman's article in references ). The result is that another layer is added to the interface that has been divided into many layers.
We face the brand new World Wide Web. Whether Ajax can lead Web development
The site will continue to develop in a more intelligent direction. In addition, although HTML itself is always declarative, the code that generates it is not necessarily so. JSP
Technology and other templated systems must be too complex because they try to express essentially dynamic output in declarative form. This is precisely why developers cannot tolerate adding
Cause of scriptlet: what we are trying to expressLogicThere are various forms.
By encapsulating HTML into Java code, the output logic can be expressed concisely.if
Statement andfor
The cycle can be in the form that everyone is familiar. Page elements can be re-constructed to make it easy to understand and maintain them. (For larger JSP
Page maintenance is very troublesome and prone to errors, especially in the absence of good comments .) By using pure
Servlet, you can add code reuse as much as possible, because you do not need to write new classes for the construction of each page.
HTML/XHTML compliance
Encapsulating HTML into a Java method can maintain consistency during reuse, helping reduce the number of input errors. This helps generate HTML or XHTML compliant with the standard.
Output.
I implemented the March Madness site according to XHTML 1.0 Strict. After all the functions are completed, you may only need to make five or six adjustments.
W3C Validation Service.
Avid Design
To demonstrate the concept of servlet-only, I built a scoring interface for an NCAA March Madness championship bonus pool. (See February March for fanatics and downloads ). You can select the top 20 teams from the 64 teams participating in the championship and assign each team a weighted score. After the competition starts, their selection becomes read-only. When the competition ends, the Administrator enters the name of the winning team. Based on the selected team, the accumulated score of the user is automatically calculated and the ranking of the score is displayed.
This project took me about three weeks of spare time and most of the time spent on style and images (after all, I am not a painter ). In addition to an HTML file and other static resources, the UI Layer consists of 21 Java classes. According to JavaNCSS measurement standards, there are a total of 1,334 Java statements (see references ).
February March
Every year in March, basketball fans in the United States will fall into fanaticism, because of the National Collegiate Athletic Association (NCAA) before
64
The Men's Basketball Team will carry out a knockout championship with all the winners. Many fans like to record their predictions and results as the competition goes on. There are also many fans who like to join in and establish informal bonus pools and bonuses.
It will be sent to the persons with the most accurate predictions.
Escape from MVC
The servlet-only design demonstrated here establishes a view layer between the client and the business logic. Model-View-Controller (MVC, or
Model 2) is actually not omnipotent, and the Web framework supporting it is often difficult to handle. Spring MVC and JavaServer
Faces (JSF) is too complex. I can assert that Struts is no less troublesome than this. Every time you adjust the control logic, you must adjust the bloated and complicated configuration file. N. Alex
Rupp (see references) even calls MVC an anti-pattern, a Web technology that looks smart and stupid.
For example, developers often misunderstand StrutsAction
The purpose of the module. Business logic is often put here (if not all are put in JSP ). Implementing a view and controller as a servlet can enable the business logic to be placed in the proper position, because the servlet explicitly focuses on the interface with the browser.
For this project, I used several classes from my own elseforif-servlet Library (see references ). ThisYesThe key to the design is that it provides a convenient interface for generating HTML. However, the focus of this article is not to prove the advantages of my methods.
Figure 1 shows a classification chart, in which the elseforif-servlet element is green:
Figure 1. Partial classification chart
At the top of the tree structure is an interface that contains HTML string constants, which provides convenience for HTML writer objects and servlets that use them. (You will see their functions later .) NextHTMLWriter
AndHTMLFlexiWriter
They implement some basic low-level HTML methods, which are useful for any Web site. The difference between the two is,HTMLWriter
Write directly to the output, whileHTMLFlexiWriter
You can also return the output in string format. It is often convenient to pass the result of an output method as a parameter to another method, for example:
out.printA(URL_ELSEFORIF, out.IMG("/img/elseforif.gif", 88, 31)); |
ThenMadnessWriter
Class, which adds the advanced output features required by the Web site: common elements such as the header, footer, and menu, that is, all unique content of the site. This is a lightweight, non-thread-safe object that abstracts the servlet base class.MadnessServlet
Instantiate this object for each request using a factory method.
This base class is responsible for processing the core servlet control logic so that specific sub-classes can focus on their specific tasks. After setting some standard HTTP headers and performing some page-level security checksMadnessWriter
The instance is passed to the protecteddoBoth()
Method:
protected void doBoth(HttpServletRequest request, HttpServletResponse response, HttpSession session, MadnessWriter out) throws ServletException, IOException
|
MadnessServlet
You have also implementedMadnessConstants
Which makes it easy for sub-classes to accessHTMLConstants
Static value defined in. ThereforeMadnessWriter
Objects and these constants, servlet implements very compact Java-style code.
Parameters and tests
Parameters can be effectively processed without the help of heavyweight systems. The elseforif-servlet library contains some helper classes, which can be directly used by the servlet in the decorator Modeinit()
Define parameters in the method.init()
A signature is formed, which makes the servlet have a good form, so that you can see the required parameters at a glance. A customizedMap
It encapsulates the independent variables and test results, which can be passed in the session as needed and shared among servlets. According to MVC, servlet (the Basic UI unit here) forms the view layer and control layer. For HTTP
This stateless interface makes sense. There is no clear difference between view requests and data update requests in the same basic form. To maintain modularity
Implement the form page in the servlet class and implement its processor in the other servlet class. However, no matter how the functions are separated, the HTML output logic, servlet
The processing of parameters and the page flow logic are self-closed objects of the same level. Although MVC abstracts them out of good intentions, it can cause functional disorder. The implementation of the business layer should be unrelated to the view layer. The key is to have a simple and clear business interface. In this way, the UI code can only handle the UI problem. (For the business layer of the sample application, I constructed a fairly rough CRUD interface on Apache Derby .)
Run the applicationThis Web application is almost completely self-contained, but you may need to modify some environment attributes in the web. xml descriptor before deploying it to webapps.
Directory. Specify at least the location for creating an embedded Derby instance and storing its data files. The default setting is the UNIX path --/var/derby /--
Therefore, if you are running Linux, you only need to create this directory (and allow servlet containers to write this directory ). UsernameAdminAnd PasswordPasswordLog on to this site. You can find more information in the README file of the downloaded package.Form and Its ProcessorNow let's look at the code. Before the start of the first round of the championship, the user enters the Picks page (see figure 2) and selects the team they like. After that, they can view the selection of themselves and other players in the form of read-only output.
Figure 2. Picks page
When this page is generated,Picks
The first thing servlet does is get its user objects from the business layer (in this systemPlayer
) And perform a security check:
PlayerManager playerMan = PlayerManager.GetInstance(); Player player = playerMan.select(session.getAttribute(P_PLAYER_ID), true); boolean readOnly = GetCutoffDateIsPassed() && !player.getAdmin(); String playerID = request.getParameter(P_PLAYER_ID); if (playerID != null) if (readOnly || player.getAdmin()) player = playerMan.select(playerID, true); else throw new ServletException("You may not view other players' picks" " until the cutoff date has passed: " + CutoffDate + "."); |
This ensures that normal users can view or edit selected teams according to business rules. It also creates some local variables that determine the page performance, especiallyreadOnly
. Next, createTeam
Object array. Each object represents a participating team. Then, call a method to generate an alphabetic map from the array. The drop-down control needs this map:
TeamManager teamMan = TeamManager.GetInstance(); Team[] teams = teamMan.selectAll(); Map selectTeams = getDropDownMap(teams); |
Now, start to output:
out.printPreContent(null, out.SCRIPTFile("/js/picks.js")); |
This method outputs the first part of the page, including the completeHEAD
Mark,BODY
Start tag and the logo at the top of the page. Note that the URL pointing to a JavaScript file is added inHEAD
. You may think that this method will expire when deploying the WAR file because it will add the context prefix/madness at the beginning of the URL. In fact, the context prefix is dynamically transmittedMadnessWriter
The constructor automatically adds the constructor to the beginning of any URL with a slash. If your context is uncertain, this feature is very useful. Next, call the output main menu:
out.printMenu(URL_PICKS); |
By passing the URL of the page to be displayedMadnessWriter
The instance skips the link on this page (you can also disable it ). Call a method to start output.TABLE
Element.Box
:
This starts several tags until the specific content in the box. (These tags will be ended later through a similar call. Note:printMenu()
The same method is called .) This encapsulation method can greatly simplify debugging. For example, I once encountered a bug with some boundary in the box.TD
The width of the browser window is 1%. I changed it to 0%, which corrected the effect on the entire site by modifying it in one place. This can be done with a custom tag library, but it is not that easy. The following rows output one or twoDIV
Element. The first one is successfully submitted to the user after the form is submitted:
if ("true".equals(request.getAttribute(P_SUCCESS))) out.printDIV("smallHeading", "Team picks were saved successfully."); out.printDIV("reminder", "(Reminder: \"Pick 20\" represents the team you" + " think likeliest to win. \"Pick 1\" is the least likely.)"); |
"smallHeading"
And"reminder"
The independent variable must be appliedDIV
The name of the cascade style table (CSS) class to start marking. The second independent variable is inDIV
Mark the output text. If reminderDIV
And I will callout.printBeginDIV("reminder")
, This method only outputsDIV
Start tag.HTMLWriter
AndHTMLFlexiWriter
The same naming mode is also used. However,HTMLConstants
For example, the defaultDIV
Use start and end tags respectivelyDIV
AndEND_DIV
. After reminder, a form is output, which provides a drop-down control for the user to select 20 teams. If you can only view the selected options, only the team name is output. According to the Java syntax, this logic is naturally expressed:
if (!readOnly) out.printSELECT(P_PICK + i, selectTeams, teamID); else { String teamName = (String)(selectTeams.get(teamID)); out.print((teamName != null) ? teamName : "(no pick)"); } |
printSELECT()
Method To createOPTION
In advance, it selects the key andteamID
Matched object. To complete the form, you need to output the team list displayed on the right of the page. The teams are sorted by NCAA region and ranking. Each region has a title, and the entire list is displayed as two columns. This requires some mathematical computation, so place it in a separate method, as shown in Listing 1:
Listing 1. Put the output code in a method
private void doRegionList(Team[] teams, MadnessWriter out) throws IOException { out.print(TABLE + TR); out.printBeginTD(null, "regionList"); for (int i = 0; i < teams.length; i++) { if ((i & 15) == 0) { if (i == 32) { out.print(END_TD + NL); out.printBeginTD(null, "regionList"); } out.print(NL + DIV); out.print(REGION_NAMES[i >> 4]); out.print(":" + END_DIV + OL); } out.print(NL + LI); out.printHTMLEscape(teams[i].getFullName()); out.print(" ("); out.print((teams[i].getRank() & 15) + 1); out.print(")"); out.print(END_LI); if ((i % 16) == 15) out.print(END_OL); } out.print(END_TABLE_3); }
|
END_TABLE_3
Constant is onlyTD
,TR
AndTABLE
End tag combination. This method seems a bit odd, but after mastering it, you can use concise code to build a good HTML design, which means that it is only used for the page structure, put as many styles as possible in the style sheet.
Now complete this page:
out.printEndBox(); out.printPostContent(); |
The box starting from the end of the first line,printPostContent()
The rest of the output page, including the footer. The Picks form page is complete.
Processor servlet (PicksAction
) Responds to the submitted Picks page, which collects the selected team IDs from the request object and passes them to the business layer to update the appropriatePlayer
Returns to the Picks form page. A security check is also executed here to ensure that users cannot update their selection after the competition starts. Form and its processor are both
Servlet, you do not need to write them to a separate interface. They all use the same business object to respond to parameterized browser requests. Together, they form a UI component. If you use MVC
Framework, then it will complicate the original simple things.
Back to Top
Other aspects
Although Web frameworks often make things complex, they can solve many small problems. Servlet-based design provides high flexibility and can solve these problems appropriately without relying on any solution.
Security
In enterprise applications, page-level security is usually implemented in XML
The descriptor file is handled in declarative mode. Similarly, based on my experience, I often need a more dynamic code-level interface to manage special behaviors on pages-for example, Picks servlet
Date-related logic. This can be handled using the Servlet API's built-in security methods, such asisUserInRole()
You can also write it as a separate interface. Using Servlet APIS is helpful for both methods.
HotSwap and development cycle
Compared with modifying JSP, modifying and re-compiling common classes is troublesome because JSP will automatically compile into a runable application. JavaHotSwap
The debugging interface (introduced in Java 1.4) can solve this problem. It allows you to reload the modified class at runtime without restarting the Web application, the session status will not be lost. Good IDE supports this feature. The servlet container I selected is Caucho Resin 3.0 (see references), which can even automatically detect modifications in the WEB-INF/classes and heat them.
Internationalization
Although many frameworks can internationalize text values in the form of attribute files, the same results can be achieved with a small amount of code in the HTML writer. You can add a method, suchprintText()
It uses a key as the independent variable and outputs the translated text value (text()
Will directly return text ). The servlet output code is still very concise and executes the same functions as the equivalent JSP (if not more ). This can also better control how to handle Missing translation words-whether to throw an exception or use the default language.
Smart skin
The March Madness design implements some interesting things. Log on to the homepage and you will see a welcome message. If you click the comma after "Welcome", you will find that the appearance and feeling have changed. The replaced skin is just another CSS file. I expandedMadnessWriter
When you choose to replace the skin, the servlet base class instantiates This subclass and passes the instance to the protected service method. Therefore,MadnessWriter
Subclass can not only overwrite the default style table, but also overwrite the structured HTML output code, such as displaying different logos and displaying more complex borders around the box. No special code is required in servlet.
Description of indentation
Note that the generated HTML is not indented, and the format is not readable. (However, creating indentation in the template code through a mix of HTML and scriptlet often leads to confusion. Even if you do not use scriptlet, cutting and pasting over time will also split the code .)
You only need to add some new line characters to the output to make the HTML generated by the March Madness site
It has better readability. However, whether the HTML format is beautiful is not important for this method, because you can easily find most la s by checking Java code.
Bug. You do not need to view the generated HTML source code. Putting elements and structures in the method greatly improves the simplicity and maintainability.
Back to Top
Conclusion
This article encourages readers to break away from the thinking patterns of common Web frameworks and consider using Java Servlet APIs to build Web interfaces directly. Java Web
There are a lot of frameworks and template systems available for developers, which makes people mistakenly think that these are essential, but they are often very complicated and difficult to use. Although some frameworks are very suitable for some types of Web
Applications, but you can also consider using built-in language features (such as extensions and encapsulation. As Bruce Tate said (see references), "it is always better to solve problems in a simple and smart way ".
Web frameworks are suitable for their scenarios. When a project has a dedicated HTML designer to generate and maintain
JSP/template is very suitable. However, for some projects
The simplicity is very meaningful. This method provides control capabilities and flexibility, and does not require that all dynamic content be placed in the request object. Simple servlet
Perform unit tests. It is also easy to reuse HTML output. You only need to add or override a method.
So try this method. You may be surprised by the results.