Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 27 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
27
Dung lượng
570,46 KB
Nội dung
AdvancedStruts Introduction This is the second tutorial on Struts. The first tutorial covered setting up a struts environment, i18n, forwards, forms, actions, and finally error handling. We will be building upon those basic Struts topics in this tutorial. If you do not feel comfortable with any on the previously mentioned topics please go back and review Beginning Struts before tackling this tutorial. My goal with this tutorial is to continue building a generic, fully functioning web site that uses struts as its backbone. The next goal is to teach you how to do the very same thing. By the end of this tutorial you should have a generic web site that with a little work can be modified to serve as the base of your site. Let me stress that you will still have a lot of work to do to get your site up and running, but this should give you a running start. What topics will we be covering in this tutorial? We will start off by extending the error handling of our first web site. Then we will move on to DynaActionForms, logic tags, and tiles. I have also added in chapters on handling login state, and adding struts-menu to the mix. We have a lot of ground to cover so lets get started! Chapter 1 – Extended Error Handling Step 1 – Setting up the base project. If you walked through the first tutorial you should know by now that you will be building and modifying an existing web site. You can find a working war file under the solutions directory if you downloaded the advancedStruts.zip. In the solutions directory navigate to Chapter 1/Step 1 base/advancedStruts.war. Extract this file and use as the base of your site. You shouldn’t have to get any of the other solution war files, but if you get stuck on any particular step you can always extract the solution war. Note: The advancedStruts.war differs from the ending beginningStruts.war in the following ways: • Changed all occurrences of advanced to beginning • Updates jar and tld files to 1.1b2 • Modified web.xml to use struts-tiles.tld instead of tiles.tld (beta 2 uses struts-tiles.xml and beta 1 uses tiles.tld) Step 2 – {0} Struts allows for more generic messages then what we have been using. Currently the ApplicationResources.properties file contains the following lines: error.required.userId=<br>User Id is required! error.required.password=<br>Password is required! This is not bad currently, but anyone that has developed a large web site can see where the duplication will quickly set in. Lets say you have fifty plus messages that all end in “is required!,” at some point there is going to be a typo or the wrong message is going to be references. In order to nip this in the bud now change those lines to the following: errors.required={0} is required! Now the question is how do you print “User Id” or “Password” in place of {0}? The answer to this question lies in the LoginForm.jsp. Find the following section of code: if (userId == null || userId.length() == 0) errors.add("userId", new ActionError("error.required.userId")); if (password == null || password.length() == 0) errors.add("password", new ActionError("error.required.password")); Now you just got rid of error.required.userId and error.required.password, so change both of those keys to errors.required. if (userId == null || userId.length() == 0) errors.add("userId", new ActionError("errors.required")); if (password == null || password.length() == 0) errors.add("password", new ActionError("errors.required")); Start Tomcat and create one of the preceding errors. You should see the following screen if all of the code has been updated correctly: We still have the {0} in the error message. So we now have to tell struts what to print in place of the {0} in our message. The answer can be found in the struts documentation: http://jakarta.apache.org/struts/api/index.html Click on ActionError and look at the 2 nd constructor listed. From this you should have noticed we forgot to include the value0 option with our constructor for our ActionError. Replace the following code in the LoginForm.java: if (userId == null || userId.length() == 0) errors.add("userId", new ActionError("errors.required")); if (password == null || password.length() == 0) errors.add("password", new ActionError("errors.required")); With: if (userId == null || userId.length() == 0) errors.add("userId", new ActionError("errors.required", “User Id”)); if (password == null || password.length() == 0) errors.add("password", new ActionError("errors.required", “Password”)); Restart Tomcat and have a look at the site. You should see something similar to this: Whoa, what happened here? It all worked in English, but in Spanish I still get User Id or Password? That doesn’t look good at all. Don’t fret; we will correct this in Step 2. Step 2 – i18n and Errors. Our goal in Step 2 is to show the following screen in Spanish: To do this we need to verify we have the following ApplicationResources.properties file: welcome=Hola Amigos, usted es un buscador. history=Esto es su historia de la compañía. reserved=Estos son los artículos que usted reservó. requested=Usted ha solicitado estos artículos. link.footer.home=El HOGAR link.footer.reserved=RESERVADO link.footer.requested=SOLICITANDO link.sidebar.history=Historia link.sidebar.login=Login link.sidebar.requested=Los Artículos solicitados link.sidebar.reserved=Los Artículos reservados footer.tagline=Pavoneos de Greenbrier Y Russel Tutoriales. footer.by=Desarrollado por <a href="mailto:jborn@gr.com" class="by_a">Jeff Born</a> y <a href="mailto:rjackson@gr.com" class="by_a">Robert Jackson</a> header.title=G&R se Pavonea la Tienda E Tutorial header.alt.home=el hogar header.alt.requested=solicitando header.alt.reserved=reservado header.alt.login=login countrycode=/es userId=La identificación del usuario password=la seña login.userId=La identificación del usuario: login.password=la seña: errors.required={0} se reqriere. error.authentication=<span class=error>ERROR: <UL>Login inválido proporcionó por favor prueba otra vez.</UL></span><hr> errors.header= errors.footer= The bolded lines are the important ones for our example. Everything else happens in the LoginForm.java. Take a moment and look at the struts documentation again. This time look at MessageResources. The important methods are getMessageResources and getMessage. By using these we should be able to i18n are code again. First we need to bring in the messages so add the following line of code: ActionErrors errors = new ActionErrors(); // Add this line MessageResources messages = MessageResources.getMessageResources("ApplicationResources"); // Add this line if (userId == null || userId.length() == 0) Note: Make sure you use ApplicationResources. If you misspell it you will get nothing. All the messages you try and retrieve will be null. This is one of the pitfalls of Struts. It sometimes makes debugging more difficult than it has to be. However once everything is set up correctly it makes maintenance much easier than a traditional site. Now we need to pass either userId or the password message in rather than our hardcoded values. Modify the code to use the following: errors.add("userId", new ActionError("errors.required", messages.getMessage(request.getLocale(), "userId"))); // or password If you leave off request.getLocale() the message will be pulled from the servers default locale ApplicationResources.properties file. Once you restart Tomcat and refresh your screen you should see the i18n error messages being displayed. Step 3 Now the question becomes why have the server validate that you have actually typed something into the web browser screen before pressing submit. The only good reason I can come up with is that browser doesn’t support JavaScript. Since almost every browser does support JavaScript, the next question becomes how can I add this to my application? In order to do this we need to add quite a few files to the project: Create a validation.xml in the WEB-INF folder, and copy in the following code: <?xml version="1.0" encoding="ISO-8859-1" ?> <! Validation Rules for the AdvancedStrutsTutorial Web Application > <form-validation> <! ========== Default Language Form Definitions ===================== > <formset> <form name="loginForm"> <field property="userId" depends="minlength,maxlength"> <arg0 key="userId"/> <arg1 key="${var:minlength}" name="minlength" resource="false"/> <arg1 key="${var:maxlength}" name="maxlength" resource="false"/> <var> <var-name>maxlength</var-name> <var-value>16</var-value> </var> <var> <var-name>minlength</var-name> <var-value>3</var-value> </var> </field> <field property="password" depends="minlength,maxlength"> <arg0 key="password"/> <arg1 key="${var:minlength}" name="minlength" resource="false"/> <arg1 key="${var:maxlength}" name="maxlength" resource="false"/> <var> <var-name>maxlength</var-name> <var-value>16</var-value> </var> <var> <var-name>minlength</var-name> <var-value>3</var-value> </var> </field> </form> </formset> </form-validation> Note: The arg0 fields here need to be in the ApplicationResources file. The field property=”blah” has to match the field on the login.jsp. validator-rules.xml: Extract this file from the C:\jakarta-struts-1.1-b2\webapps\struts-example.war file. It is found in the web-inf relative path. Once that is done find the following code: <validator name="minlength" classname="org.apache.struts.util.StrutsValidator" method="validateMinLength" methodParams="java.lang.Object, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.Field, org.apache.struts.action.ActionErrors, javax.servlet.http.HttpServletRequest" depends="required" msg="errors.minlength"> <javascript><![CDATA[ function validateMinLength(form) { var bValid = true; var focusField = null; var i = 0; var fields = new Array(); oMinLength = new minlength(); for (x in oMinLength) { if (form[oMinLength[x][0]].type == 'text' || form[oMinLength[x][0]].type == 'textarea') { Replace the last three lines: for (x in oMinLength) { if (form[oMinLength[x][0]].type == 'text' || form[oMinLength[x][0]].type == 'textarea') { With the following four lines: for (x in oMinLength) { if (form[oMinLength[x][0]].type == 'text' || form[oMinLength[x][0]].type == 'password' || form[oMinLength[x][0]].type == 'textarea') { You will also need to do this under the next ‘code’ paragraph for maxlength. Note: The struts example decided that hackers were to big of a threat to tell someone what lengths a password could be. I don’t agree with the reasons for taking this out, so we are adding it back in. If you don’t want the validate the password on the front end just modify the validator.xml and remove the password field from the list of fields you want to have validated. Also in the struts-example.war file you will find a file called staticJavascript.jsp. Copy that file into your application. Now we need to tell Struts to load the validator plugin. This is done by adding the following to the struts-config.xml: <! ========== Plug Ins Configuration ================================== > <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml, /WEB-INF/validation.xml"/> </plug-in> Note: I added this after the Message Resources Definitions section. If you open the validator-rules.xml you will find some directions to added front end validation to your application. The plugin we just took care of, but we also need to add the messages it refers to to the ApplicationResources.properties file. The lines we need to add are: # Standard error messages for validator framework checks errors.required={0} is required. errors.minlength={0} can not be less than {1} characters. errors.maxlength={0} can not be greater than {1} characters. errors.invalid={0} is invalid. errors.byte={0} must be an byte. errors.short={0} must be an short. errors.integer={0} must be an integer. errors.long={0} must be an long. errors.float={0} must be an float. errors.double={0} must be an double. errors.date={0} is not a date. errors.range={0} is not in the range {1} through {2}. errors.creditcard={0} is not a valid credit card number. errors.email={0} is an invalid e-mail address. Note: We previously created a message key called errors.required. Make sure you end up with this key listed only once. The last file is where we actually want to use these new resources; The login.jsp. First we need to tell the login.jsp to load some JavaScript functions. Add the following code to the bottom of the login.jsp after the </html:form> tag: <html:javascript formName="loginForm" dynamicJavascript="true" staticJavascript="false"/> <script language="Javascript1.1" src="staticJavascript.jsp"></script> Next we need to update the following line: <html:form action="login" focus="userId"> With: <html:form action="login" focus="userId" onsubmit="return validateLoginForm(this);"> After you have all of those steps completed Restart Tomcat and browse to the Login page of your application. If everything goes according to plans you should see the following after pressing the submit button. Chapter 2 – Dynamics At Work. Introduction to Dynamic Forms. Most people will agree with me that creating the LoginForm.java seems a tad bit redundant. All we have in it are getter, setters, and a validation routine. The getters and setters should be easily created on the fly, and the non-business logic validation shouldn’t be to hard to move, or have generated for us. The only question most of you would have is not really why to do it, but how. The following Chapter will show you how to modify your application to use a DynaActionForm and a DynaValidatorForm. Step 1 – Delete LoginForm.java That’s right go ahead and delete it. You won’t be needing it anymore. In case you forgot where its located at, you should find it under WEB-INF/src/com/gr/struts. Now comes the hard part; Getting rid of those pesky error messages caused by deleting a .java file that is still referenced by other .java file. If you open the config-struts.xml file you should see a form-beans section. In there you will find one form-bean defined for the LoginForm. In order for this form to be created dynamically (along with the getters and the setters,) we need to tell struts which class will take the place of com.gr.struts.LoginForm. That class is org.apache.struts.action.DynaActionForm, so go ahead and replace the following code: <form-beans> <form-bean name="LoginForm" type="org.apache.struts.action"/> </form-beans> With: <form-beans> <form-bean name="LoginForm" type="org.apache.struts.action.DynaActionForm"> </form-bean> </form-beans> Observant students will already have noticed that we now have an ending tag for the <form-bean> tag. This is because inbetween <form-bean> and </form-bean> we will be listing out all of the fields used on are form. Like this: <form-beans> <form-bean name="loginForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="userId" type="java.lang.String" /> <form-property name="password" type="java.lang.String" /> </form-bean> </form-beans> The name field must be the same as the property name for the html:text or password tag, and the type is the class that this field represents. Now we need to change the LoginBean.java. It made a direct reference to the LoginForm class in the following code: public void setParameters(ActionForm form) { userId = ((LoginForm) form).getUserId(); password = ((LoginForm) form).getPassword(); } LoginForm no longer exist so we can’t cast to it anymore, but we should be able to cast to a DynaActionForm like so: public void setParameters(ActionForm form) { userId = ((DynaActionForm) form).getUserId(); password = ((DynaActionForm) form).getPassword(); } Now once we do that the method getUserId and getPassword no longer exist. We need something more generic. How about just get(String) which will “return the value of a simple property with the specified name” (Taken from the JavaDocs on DynaActionForm.) Now your code should look like this: public void setParameters(ActionForm form) { userId = ((DynaActionForm) form). get("userId"); password = ((DynaActionForm) form). get("password"); } The final step is to tell the compiler you expect both of these keys to return Strings. That is done with a cast like so: public void setParameters(ActionForm form) { userId = (String) ((DynaActionForm) form).get("userId"); password = (String) ((DynaActionForm) form).get("password"); } For forms without a lot of fields coding up all the cast as we just did works fine, but I prefer the following notation, because even the simplest form seems to grow out of control: public void setParameters(ActionForm baseForm) { DynaActionForm form = (DynaActionForm)baseForm; userId = (String) form.get("userId"); password = (String) form.get("password"); } Doing it this way you only have to specify the DynaActionForm cast once. That’s it. You should be able to restart Tomcat and continue working with your application without a problem. If you do have a problem you can always go back to the solution folder and check your files against the solution files. [...]... add struts- menu.tld to the WEB-INF folder Note: You can get the struts- menu.tld, struts- menu.jar, scripts directory and scripts, and menuconfig.xml files from the advancedStruts.jar in the solutions directory You can also get these files from StrutsMenu-1.1.zip file although the ones found in the solutions directory have had some minor tweaking already done (Color, menu options, etc…) Modify the struts- config.xml... Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org /struts/ dtds /struts- config_1_1.dtd"> Struts configuration file for the example application, using the proposed new syntax If used with Struts1 .1, you need to declare a Tiles plug-in If used with Struts1 .0.x, nothing special is required > struts. css into this directory Then go and find the advancedStruts.war in the solutions/Chapter 3/Step 1 path, and extract the following files: classicLayout.jsp menu.jsp menuNoStruts.jsp vboxLayout.jsp Note: I’ve taken quite a bit of the files out of the tiles-blank -struts1 -1.war file When I first started using tiles I just modified and added to the working tiles-blank -struts1 -1 solution... the struts environment we have a modification to the strutsconfig.xml file Using tiles is no exception Since there are a lot of changes to the struts- config.xml file and we don’t want to miss one I’m just going to have you copy the following to replace your current struts- config.xml: .struts. tiles.TilesRequestProcessor" /> -> Struts version > struts1 .0.x > struts1 .0.x > struts modules, even if the plugin is declared several times Paths found in Tiles definitions are relative to the main context > struts1 .0.x > struts1 .0.x > < /struts- config> Now that you have this completed what does it all mean? . Advanced Struts Introduction This is the second tutorial on Struts. The first tutorial covered setting up a struts environment, i18n, forwards, forms,. those basic Struts topics in this tutorial. If you do not feel comfortable with any on the previously mentioned topics please go back and review Beginning Struts before tackling this tutorial. . extract the solution war. Note: The advancedStruts.war differs from the ending beginningStruts.war in the following ways: • Changed all occurrences of advanced to beginning • Updates jar and