此次项目基于SSH2框架(物业报修系统),为了避免忘记框架使用的步骤,我稍微记录一下注册模块的编写过程。
框架分层 核心是Spring框架,它有IOC容器,可以方便地管理Struts2和Hibernate;Struts2因其MVC的架构,因而负责显示;Hibernate则是持久层,实现DAO。
步骤 下面是详细的步骤,根据时间先后一步一步来。
Tomcat容器的配置(WebRoot/WEB-INF/web.xml) 该文件告诉Tomcat,主页是哪个、Action交给谁处理、网站的编码格式、过滤拦截哪些URL、托管给Spring等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 <?xml version="1.0" encoding="UTF-8" ?> <web-app version ="2.5" xmlns ="http://java.sun.com/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" > <display-name > 邱永臣配置</display-name > <filter > <filter-name > filterDispatcher</filter-name > <filter-class > org.apache.struts2.dispatcher.FilterDispatcher</filter-class > </filter > <filter-mapping > <filter-name > filterDispatcher</filter-name > <url-pattern > /*</url-pattern > </filter-mapping > <filter > <filter-name > struts-clean</filter-name > <filter-class > org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class > </filter > <filter-mapping > <filter-name > struts-clean</filter-name > <url-pattern > /*</url-pattern > </filter-mapping > <welcome-file-list > <welcome-file > lookRemindRepairOrder.jsp</welcome-file > </welcome-file-list > <context-param > <param-name > contextConfigLocation</param-name > <param-value > WEB-INF/applicationContext.xml</param-value > </context-param > <listener > <listener-class > org.springframework.web.context.ContextLoaderListener</listener-class > </listener > </web-app >
编写用户实体(model层) 所谓用户实体,其实是java bean,它内部有用户数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 /** * */ package com.ilovecl.myproperty.model; /** * 学生实体 * * @author 邱永臣 * * 对应的数据库建表命令为 create table `Student` ( `userId` int not null primary * key auto_increment, `userName` varchar(20) not null, `password` * varchar(20) not null, `phoneNumber` long, `email` varchar(100), * `sexual` varchar(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8; */ public class Student { private int userId; private String userName; private String password; private long phoneNumber; private String email; private String sexual; public Student() { super(); // TODO Auto-generated constructor stub } public Student(String userName2, String password2, long phoneNumber2, String email2, String sexual2) { this.userName = userName2; this.password = password2; this.phoneNumber = phoneNumber2; this.email = email2; this.sexual = sexual2; } /** * @return the userId */ public int getUserId() { return userId; } /** * @param userId * the userId to set */ public void setUserId(int userId) { this.userId = userId; } /** * @return the userName */ public String getUserName() { return userName; } /** * @param userName * the userName to set */ public void setUserName(String userName) { this.userName = userName; } /** * @return the password */ public String getPassword() { return password; } /** * @param password * the password to set */ public void setPassword(String password) { this.password = password; } /** * @return the phoneNumber */ public long getPhoneNumber() { return phoneNumber; } /** * @param phoneNumber * the phoneNumber to set */ public void setPhoneNumber(long phoneNumber) { this.phoneNumber = phoneNumber; } /** * @return the email */ public String getEmail() { return email; } /** * @param email * the email to set */ public void setEmail(String email) { this.email = email; } /** * @return the sexual */ public String getSexual() { return sexual; } /** * @param sexual * the sexual to set */ public void setSexual(String sexual) { this.sexual = sexual; } }
编写Hibernate的映射文件(Student.hbm.xml) Hibernate正是凭借它,才能将对象映射到数据库中去:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" ><hibernate-mapping > <class name ="com.ilovecl.myproperty.model.Student" table ="Student" > <id name ="userId" type ="java.lang.Integer" > <column name ="userId" /> <generator class ="increment" /> </id > <property name ="userName" type ="java.lang.String" > <column name ="userName" length ="20" /> </property > <property name ="password" type ="java.lang.String" > <column name ="password" length ="20" /> </property > <property name ="phoneNumber" type ="java.lang.Long" > <column name ="phoneNumber" /> </property > <property name ="email" type ="java.lang.String" > <column name ="email" length ="100" /> </property > <property name ="sexual" type ="java.lang.String" > <column name ="sexual" length ="10" /> </property > </class > </hibernate-mapping >
将Hibernate托管给Spring 在WebRoot/WEB-INF/applicationContext.xml中增加下面的代码代码,告诉Hibernate数据库的信息,映射文件的位置,将Hibernate的sessionFactory托管给Spring:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 <bean id ="dataSource" class ="org.apache.commons.dbcp.BasicDataSource" > <property name ="driverClassName" > <value > com.mysql.jdbc.Driver</value > </property > <property name ="url" > <value > jdbc:mysql://139.129.118.90:3306/myproperty?useUnicode=true& characterEncoding=UTF-8</value > </property > <property name ="username" > <value > root</value > </property > <property name ="password" > <value > test</value > </property > </bean > <bean id ="sessionFactory" class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" > <property name ="dataSource" > <ref bean ="dataSource" /> </property > <property name ="hibernateProperties" > <props > <prop key ="hibernate.dialect" > org.hibernate.dialect.MySQLDialect </prop > </props > </property > <property name ="mappingResources" > <list > <value > com/ilovecl/myproperty/model/Student.hbm.xml</value > </list > </property > </bean > <bean id ="baseTransactionProxy" class ="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract ="true" > <property name ="transactionManager" > <ref bean ="transactionManager" /> </property > <property name ="transactionAttributes" > <props > <prop key ="save*" > PROPAGATION_REQUIRED</prop > <prop key ="update*" > PROPAGATION_REQUIRED</prop > <prop key ="delete*" > PROPAGATION_REQUIRED</prop > </props > </property > </bean >
编写DAO层代码(接口和实现) DAO层专门操作实体,比如增删改查一个学生等。 接口代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 /** * */ package com.ilovecl.myproperty.DAO; import java.util.List; import com.ilovecl.myproperty.model.Student; /** * DAO层:学生DAO的接口 * * @author 邱永臣 * */ public interface IStudentDAO { public abstract void save(Student transientInstance); public abstract void delete(Student persistentInstance); public abstract Student findById(java.lang.Integer id); public abstract List<Student> findByUserName(java.lang.String userName); boolean isStudentExits(String userName); }
实现的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 /** * */ package com.ilovecl.myproperty.DAO.impl; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import com.ilovecl.myproperty.DAO.IStudentDAO; import com.ilovecl.myproperty.model.Student; /** * @author 邱永臣 * */ public class StudentDAO extends HibernateDaoSupport implements IStudentDAO { private static final Log log = LogFactory.getLog(StudentDAO.class); /* * (non-Javadoc) * * @see * com.ilovecl.myproperty.DAO.IStudentDAO#save(com.ilovecl.myproperty.model * .Student) */ @Override public void save(Student transientInstance) { log.debug("save(Student transientInstance) in StudentDAO"); try { this.getHibernateTemplate().saveOrUpdate(transientInstance); log.debug("save(Student transientInstance) in StudentDAO successful"); } catch (RuntimeException re) { log.error("save(Student transientInstance) in StudentDAO failed", re); throw re; } } /* * (non-Javadoc) * * @see * com.ilovecl.myproperty.DAO.IStudentDAO#delete(com.ilovecl.myproperty. * model.Student) */ @Override public void delete(Student persistentInstance) { log.debug("delete(Student persistentInstance)"); try { getHibernateTemplate().delete(persistentInstance); log.debug("delete(Student persistentInstance) successful"); } catch (RuntimeException re) { log.error("delete(Student persistentInstance) failed", re); throw re; } } /* * (non-Javadoc) * * @see com.ilovecl.myproperty.DAO.IStudentDAO#findById(java.lang.Integer) */ @Override public Student findById(Integer id) { log.debug("findById(Integer id) : " + id); try { Student instance = (Student) getHibernateTemplate().get( "com.ilovecl.myproperty.model.Student", id); return instance; } catch (RuntimeException re) { log.error("findById(Integer id) failed", re); throw re; } } /* * (non-Javadoc) * * @see * com.ilovecl.myproperty.DAO.IStudentDAO#findByUsername(java.lang.Object) */ @SuppressWarnings("unchecked") @Override public List<Student> findByUserName(String userName) { List<Student> students; try { String queryString = "from Student as model where model." + "userName" + "= ?"; students = getHibernateTemplate().find(queryString, userName); } catch (RuntimeException re) { log.error("findByUserName failed", re); throw re; } return students; } @Override public boolean isStudentExits(String userName) { return findByUserName(userName).size() == 1; } }
将DAO托管给Spring 在WebRoot/WEB-INF/applicationContext.xml中增加下面的代码代码:
1 2 3 4 5 6 7 <bean id ="studentDAO" class ="com.ilovecl.myproperty.DAO.impl.StudentDAO" > <property name ="sessionFactory" > <ref bean ="sessionFactory" /> </property > </bean >
编写逻辑层代码(接口与实现) 逻辑层原先放在Struts2控制层的Action中,但随着Action的日渐庞大,许多负责的逻辑代码需要分离出来单独作为逻辑层。
接口的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 /** * */ package com.ilovecl.myproperty.service; import com.ilovecl.myproperty.DAO.IStudentDAO; import com.ilovecl.myproperty.model.Student; /** * @author 邱永臣 * */ public interface IRegisterService { public IStudentDAO getStudentDAO(); public void setStudentDAO(IStudentDAO studentDAO); public boolean register(Student student); boolean isStudentExits(String userName); }
实现的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 /** * */ package com.ilovecl.myproperty.service.impl; import com.ilovecl.myproperty.DAO.IStudentDAO; import com.ilovecl.myproperty.model.Student; import com.ilovecl.myproperty.service.IRegisterService; /** * @author 邱永臣 * */ public class RegisterService implements IRegisterService { private IStudentDAO studentDAO; /** * @return the studentDAO */ public IStudentDAO getStudentDAO() { return studentDAO; } /** * @param studentDAO * the studentDAO to set */ public void setStudentDAO(IStudentDAO studentDAO) { this.studentDAO = studentDAO; } /* * (non-Javadoc) * * @see * com.ilovecl.myproperty.service.IRegisterService#isStudentExits(java.lang * .String) */ @Override public boolean isStudentExits(String userName) { return studentDAO.findByUserName(userName).size() == 1; } /* * (non-Javadoc) * * @see * com.ilovecl.myproperty.service.IRegisterService#register(java.lang.String * , java.lang.String) */ @Override public boolean register(Student student) { if (isStudentExits(student.getUserName())) { return false; } studentDAO.save(student); return true; } }
将逻辑层托管给Spring 在WebRoot/WEB-INF/applicationContext.xml中增加下面的代码代码:
1 2 3 4 5 6 7 8 <bean id ="registerService" parent ="baseTransactionProxy" > <property name ="target" > <bean class ="com.ilovecl.myproperty.service.impl.RegisterService" > <property name ="studentDAO" ref ="studentDAO" /> </bean > </property > </bean >
编写Struts2的Action 到这里,我们就进入了Struts2的MVC世界。
控制层:Action属于MVC中的C;
模型层:Struts1中用java bean作为模型层,也就是MVC中的M,但该方案在Struts2中被废除,模型层的内容直接放入Action;
视图层:jsp的内容即是视图层;
Action最主要的方法是execute,在用户点击注册按钮时,会执行该方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 /** * */ package com.ilovecl.myproperty.struts.action; import com.ilovecl.myproperty.model.Student; import com.ilovecl.myproperty.service.IRegisterService; import com.opensymphony.xwork2.ActionSupport; /** * 用户注册功能的Action类 * * @author 邱永臣 * */ @SuppressWarnings("serial") public class StudentRegisterAction extends ActionSupport { private int userId; private String userName; private String password; private String passwordConfirm; private long phoneNumber; private String email; private String sexual; String message; private IRegisterService iRegisterService; /** * */ public StudentRegisterAction() { phoneNumber = 0; email = ""; sexual = ""; } /* * (non-Javadoc) * * @see com.opensymphony.xwork2.ActionSupport#execute() */ @Override public String execute() throws Exception { this.message = ""; if (this.userName.equals("")) { this.message += "用户名为空!\n"; return INPUT; } else if (this.password.equals("") || this.passwordConfirm.equals("")) { this.message += "密码为空!\n"; return INPUT; } else if (!this.password.equals(this.passwordConfirm)) { this.message += "两次密码不相同!\n"; return INPUT; } if (iRegisterService.isStudentExits(userName)) { this.message += "账户已存在!"; return INPUT; } if (iRegisterService.register(new Student(userName, password, phoneNumber, email, sexual))) { this.message = "注册成功"; return SUCCESS; } else { this.message = "注册失败"; return INPUT; } } /** * @return the userId */ public int getUserId() { return userId; } /** * @param userId * the userId to set */ public void setUserId(int userId) { this.userId = userId; } /** * @return the userName */ public String getUserName() { return userName; } /** * @param userName * the userName to set */ public void setUserName(String userName) { this.userName = userName; } /** * @return the password */ public String getPassword() { return password; } /** * @param password * the password to set */ public void setPassword(String password) { this.password = password; } /** * @return the passwordConfirm */ public String getPasswordConfirm() { return passwordConfirm; } /** * @param passwordConfirm * the passwordConfirm to set */ public void setPasswordConfirm(String passwordConfirm) { this.passwordConfirm = passwordConfirm; } /** * @return the phoneNumber */ public long getPhoneNumber() { return phoneNumber; } /** * @param phoneNumber * the phoneNumber to set */ public void setPhoneNumber(long phoneNumber) { this.phoneNumber = phoneNumber; } /** * @return the email */ public String getEmail() { return email; } /** * @param email * the email to set */ public void setEmail(String email) { this.email = email; } /** * @return the sexual */ public String getSexual() { return sexual; } /** * @param sexual * the sexual to set */ public void setSexual(String sexual) { this.sexual = sexual; } /** * @return the iRegisterService */ public IRegisterService getiRegisterService() { return iRegisterService; } /** * @param iRegisterService * the iRegisterService to set */ public void setiRegisterService(IRegisterService iRegisterService) { this.iRegisterService = iRegisterService; } /** * @return the message */ public String getMessage() { return message; } /** * @param message * the message to set */ public void setMessage(String message) { this.message = message; } }
将Action托管给Spring 在WebRoot/WEB-INF/applicationContext.xml中增加下面的代码代码:
1 2 3 4 5 <bean id ="studentRegisterAction" class ="com.ilovecl.myproperty.struts.action.StudentRegisterAction" > <property name ="iRegisterService" ref ="registerService" /> </bean >
让Struts2找到从Spring那里找到Action 由于Spring管理着Action,Struts2需要Action的时候,只能找Spring要。
在struts.xml中增加下面的代码代码:
1 2 3 4 <action name ="register" class ="studentRegisterAction" > <result name ="success" > /register.jsp</result > <result name ="input" > /register.jsp</result > </action >
编写视图层页面(jsp) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <%@ page contentType="text/html;charset=utf-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" > <html > <head > <title > 用户注册</title > </head > <body > <br > <br > <br > <br > <div align ="center" > ${requestScope.message} <s:form action ="register" method ="POST" > <s:textfield name ="userName" label ="user name" /> <s:password name ="password" size ="21" label ="password" /> <s:password name ="passwordConfirm" size ="21" label ="passwordConfirm" /> <s:textfield name ="phoneNumber" label ="phoneNumber" /> <s:textfield name ="email" label ="email" /> <s:textfield name ="sexual" label ="sexual" /> <s:submit value ="OK" /> </s:form > </div > </body > </html >
其它 上面是就是一个完整的SSH2实现的注册模块,在运行之前必须先建立数据库,数据库的信息和建表命令都在上面。