小弟最近开始了Java的学习之路,希望能够学习一下各种框架。
这两天在接触Struts,网上找了本书Struts in Action(中文版)(惭愧自己的E文水准╮(╯▽╰)╭)。书中的例子是基于Struts1.1的,于是我就用MyEclipse中比较接近的Struts1.3来调试书中的例子(小弟实在找不到Struts2.0的详细又好读的教程,只能先用这本书凑活了!)。
言归正传,像我这样的新手在调试书中的例子的时候可是遇到了相当多的困难啊,不过最后还算能够达到目的。因此在这里写下这篇文章以示纪念,也希望能给其他一些想学Struts的童鞋们一些参考。
小弟用的IDE是MyEclipse 8.6,实现一个登录功能的project。
1. 首先创建一个Web Project:
2. 添加Struts功能:
这里我选择的Struts版本是1.3,package名称改为app:
然后生成的目录树结构就是这样的了:
3. 添加jsp页面,在WebRoot下创建文件夹pages,添加logon.jsp(登陆页面)和welcome.jsp(欢迎页面),这两个jsp页面都是使用的Struts1.2/1.3的jsp模板。然后按照Struts in Action书上说了添加了一张图片资源struts-power.gif(这张图片你可以Google出来)。这3个文件添加完成之后,目录树结构就应该是这样子的了:
4. 添加Java文件,用于控制页面的流程。
Java文件都在app包里面(如下图所示),为了工程显示整齐,我把ApplicationResources.properties移到文件夹res里面了,res中的另一个文件user.properties用来存放登录的用户名和密码:
5. 到这里我们需要的所有文件都创建好了,接下来我们就要在这些文件中实现我们需要的功能了。小弟写不出来具体的先后顺序,就直接把每个文件的代码贴下来了:
(1)struts-config.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd"> <struts-config> <form-beans> <form-bean name="logonForm" type="app.LogonForm" /> </form-beans> <global-forwards> <forward name="logoff" path="/Logoff.do" /> <forward name="logon" path="/Logon.do" /> <forward name="welcome" path="/Welcome.do" /> </global-forwards> <action-mappings> <action path="/Welcome" type="org.apache.struts.actions.ForwardAction" parameter="/pages/welcome.jsp" /> <action path="/Logon" type="org.apache.struts.actions.ForwardAction" parameter="/pages/logon.jsp" /> <action path="/LogonSubmit" type="app.LogonAction" name="logonForm" scope="request" validate="true" input="/pages/logon.jsp"> <forward name="success" path="/pages/welcome.jsp" /> </action> <action path="/Logoff" type="app.LogoffAction"> <forward name="success" path="/pages/welcome.jsp" /> </action> </action-mappings> <message-resources parameter="res.ApplicationResources" /> </struts-config>
(2)ApplicationResources.properties,这个文件中定义的是一些消息,等号左边相当于key,右边相当于value:
# Resources for parameter 'res.ApplicationResources' # Project struts_logon errors.header=<H3><font color="red">Validation Error</font></H3>You must correct the following error(s) before proceeding:<UL> errors.footer=</UL><HR> error.username.required=<LI>Username is required</LI> error.password.required=<LI>Password is required</LI> error.logon.invalid=<LI>Username and password provided not found in user directory. Password must match exactly, including any lower or upper case characters.</LI>
(3)user.properties,这个设定用户名和密码,你可以随自己的喜好随便设置,我的文件中是这样的:
fl=123456 sa=123456
(4)配置文件基本都完成了,接下来我们就开始实现页面的功能了,首先是jsp页面的代码:
index.jsp,这个是默认的首页,设置为直接指向welcome.jsp页面:
<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %> <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %> <%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <logic:forward name="welcome"/>
logon.jsp:
<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%> <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%> <%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html:html> <head> <html:base /> <title>Sign in, Please!</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <html:errors /> <html:form action="/LogonSubmit" focus="username"> <table border="0" width="100%"> <tr> <th align="right"> Username: </th> <td align="left"> <html:text property="username" /> </td> </tr> <tr> <th align="right"> Password: </th> <td align="left"> <html:password property="password" /> </td> </tr> <tr> <td align="right"> <html:submit /> </td> <td align="left"> <html:reset /> </td> </tr> </table> </html:form> </body> </html:html>
welcome.jsp:
<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%> <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%> <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%> <%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html:html lang="true"> <head> <html:base /> <title>Welcome!</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <logic:present name="user"> <h3> Welcome <bean:write name="user" property="username" /> ! </h3> </logic:present> <logic:notPresent scope="session" name="user"> <h3> Welcome World! </h3> </logic:notPresent> <html:errors /> <ul> <li> <html:link forward="logon">Sign in</html:link> </li> <logic:present name="user"> <li> <html:link forward="logoff">Sign out</html:link> </li> </logic:present> </ul> <img src='struts-power.gif' alt='Powered by Struts'> </body> </html:html>
(5)下面是Java代码,
Constants.java 定义一些常量,这样设计便于维护:
package app; public final class Constants { public static final String Package = "app"; public static final String USER_KEY = "user"; public static final String SUCCESS = "success"; public static final String LOGON = "logon"; public static final String WELCOME = "welcome"; public static final int DEBUG = 1; public static final int NORMAL = 0; }
LogoffAction.java 登出控制器:
package app; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; public final class LogoffAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { HttpSession session = request.getSession(); session.removeAttribute(Constants.USER_KEY); return mapping.findForward(Constants.SUCCESS); } }
LogonAction.java 登入控制器:
package app; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts.action.Action; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ActionMessages; public final class LogonAction extends Action { public boolean isUserLogon(String username, String password) throws UserDirectoryException { return UserDirectory.getInstance().isValidPassword(username, password); } public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String username = ((LogonForm) form).getUsername(); String password = ((LogonForm) form).getPassword(); boolean validated = false; try { validated = isUserLogon(username, password); } catch (UserDirectoryException ude) { ActionErrors errors = new ActionErrors(); errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.logon.connect")); saveErrors(request, errors); return new ActionForward(mapping.getInput()); } if (!validated) { ActionErrors errors = new ActionErrors(); errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("error.logon.invalid")); saveErrors(request, errors); return new ActionForward(mapping.getInput()); } HttpSession session = request.getSession(); session.setAttribute(Constants.USER_KEY, form); return mapping.findForward(Constants.SUCCESS); } }
LogonForm.java 对应登录的表单:
package app; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; public final class LogonForm extends ActionForm { private String password = null; private String username = null; public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } public String getUsername() { return this.username; } public void setUsername(String username) { this.username = username; } public void reset(ActionMapping mapping, HttpServletRequest request) { setPassword(null); setUsername(null); } public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if (username == null || username.length() < 1) errors.add("username", new ActionMessage("error.username.required")); if (password == null || password.length() < 1) errors.add("password", new ActionMessage("error.password.required")); return errors; } }
UserDirectory.java 用于判断登入的用户是否有效,这是一个单实例的类:
package app; import java.io.IOException; import java.io.FileOutputStream; import java.io.InputStream; import java.util.Enumeration; import java.util.Properties; public class UserDirectory { private static final String UserDirectoryFile = "res/users.properties"; private static final String UserDirectoryHeader = "${user}=${password}"; private static UserDirectory userDirectory = null; private static Properties properties; private UserDirectory() throws UserDirectoryException { InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(UserDirectoryFile); properties = null; if (inputStream == null) { throw new UserDirectoryException(); } else { try { properties = new Properties(); properties.load(inputStream); inputStream.close(); } catch (IOException e) { properties = null; System.out.println(e.getMessage()); throw new UserDirectoryException(); } finally { inputStream = null; } } } public static UserDirectory getInstance() throws UserDirectoryException { if (userDirectory == null) { userDirectory = new UserDirectory(); } return userDirectory; } public String fixUsername(String username) { return username.toLowerCase(); } public boolean isValidPassword(String username, String password) { if (password == null) return false; String fixUsername = fixUsername(username); if (!isUserExist(fixUsername)) return false; return password.equals(getPassword(fixUsername)); } public boolean isUserExist(String username) { if (username == null) return false; return properties.getProperty(username) != null; } public String getPassword(String username) { return properties.getProperty(username); } public Enumeration getUserNames() { return properties.propertyNames(); } public void setUser(String username, String password) throws UserDirectoryException { if (username == null || password == null) { throw new UserDirectoryException(); } try { properties.put(fixUsername(username), password); properties.store(new FileOutputStream(UserDirectoryFile), UserDirectoryHeader); } catch (IOException e) { throw new UserDirectoryException(); } } }
UserDirectoryException.java 自定义异常类,直接继承Exception类就可以了:
package app; public class UserDirectoryException extends Exception { }
6. 所有文件都完成了,我们开始测试一下啦,直接用MyEclipse自带的Tomcat服务器来部署我们的应用:
7. 部署完成,启动Tomcat服务器,打开浏览器,输入地址 http://localhost:8080/struts_logon/
顺利打开welcome页面
点击 Sign In,什么都不输入,直接点击Submit,正如我们希望的给出了错误信息:
再输入正确的用户名密码试试吧!