上一篇已经搭建好了开发环境,现在用一个简单的注册登录来体验一下S2SH。
1、建立一个实体类:user.java,在cn.dy.bean包新建class
1 package cn.dy.bean;
2
3 public class User {
4 private Integer userId;
5 private String userName;
6 private String userPassword;
7 private String trueName;
8 private String peopleId;
9 get()...set()...
10 }
2、建立hibernate配置文件,在cn.dy.bean包新建文件,命名为:User.hbm.xml,内容如下
1 <?xml version="1.0" encoding="utf-8"?>
2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
4 <hibernate-mapping>
5 <class name="cn.dy.bean.User" table="tb_user" catalog="learn">
6 <id name="userId" type="integer">
7 <column name="userId" />
8 <generator class="identity" />
9 </id>
10 <property name="userName" type="string">
11 <column name="userName" length="16" not-null="true">
12 <comment>帐号</comment>
13 </column>
14 </property>
15 <property name="userPassword" type="string">
16 <column name="userPassword" length="50" not-null="true">
17 <comment>密码</comment>
18 </column>
19 </property>
20 <property name="trueName" type="string">
21 <column name="trueName" length="20" not-null="true">
22 <comment>真实姓名</comment>
23 </column>
24 </property>
25 <property name="peopleId" type="string">
26 <column name="peopleId" length="20" not-null="true">
27 <comment>身份证号码</comment>
28 </column>
29 </property>
30 </class>
31 </hibernate-mapping>
注意第五行,class是映射的类,table是数据库对应的表名,如果不填的话,默认是和类名一致,catalog为数据库名称,下面的几行都比较简单,看看就明白,这里就不解释了。
注:使用hibernate注解可以省略这个User.hbm.xml文件,具体见另一篇文章:【待填】
3、检查一下配置是否成功,新建一个单元测试类,new>other>java>JUnit>JUnit Test Case,选择New JUnit 4 test把它放到刚才我们建立的cn.dy.test包里。命名为UserTest,然后选择setUpBeforeClass(),finish,然后加入相关的jar包(选择最后一项)。这里需要说的是为什么选择setUpBeforeClass(),因为我们想要测试,所以在测试类构建完成后,就想获取一个上下文,方便使用。至此,测试类代码如下,运行不报错,说明已经配置成功,然后打开数据库找到learns,发现里面已经建立了tb_user表。
1 package cn.dy.test;
2
3 import org.junit.BeforeClass;
4 import org.junit.Test;
5 import org.springframework.context.ApplicationContext;
6 import org.springframework.context.support.ClassPathXmlApplicationContext;
7
8 public class UserTest {
9
10 @BeforeClass
11 public static void setUpBeforeClass() throws Exception {
12 }
13
14 @Test
15 public void test() {
16 ApplicationContext act = new ClassPathXmlApplicationContext(
17 "file:WebRoot/WEB-INF/spring.xml");
18 }
19 }
注:spring文件的路径一定要注意,有人问了,为什么以前见的路径和这个不一样呢,这里我强调一下,如果你的spring配置文件放在WEB-INF文件夹下,就是用我的这个表现方式,如果你的spring配置文件在src下,直接使用spring.xml就好了。我建议还是放在WEB-INF文件夹下比较好,毕竟里面有数据库的配置代码,安全至上。
4、测试成功继续进行我们的小项目,首先把功能整理清楚,要实现的功能有:用户的注册、修改、删除、查找。也就是基本的操作。好,修改index.jsp文件,代码如下
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%@ taglib uri="/struts-tags" prefix="s"%>
3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5 <head>
6 <title>简单的注册页面</title>
7 </head>
8 <body>
9 <s:form action="" namespace="" method="post">
10 <table>
11 <tr>
12 <td><label for="name">*帐号:</label></td>
13 <td><s:textfield id="name" name="user.userName" value="" /></td>
14 </tr>
15 <tr>
16 <td><label for="password">*密码:</label></td>
17 <td><s:password id="password" name="user.userPassword" value="" /></td>
18 </tr>
19 <tr>
20 <td><label for="repassword">*确认密码:</label></td>
21 <td><s:password id="repassword" value="" name="repassword" /></td>
22 </tr>
23 <tr>
24 <td><label for="true">*真实姓名:</label></td>
25 <td><s:textfield id="true" name="user.trueName" value="" /></td>
26 </tr>
27 <tr>
28 <td><label for="peopleId">*身份证号:</label></td>
29 <td><s:textfield id="peopleId" name="user.peopleId" value="" /></td>
30 </tr>
31 <tr>
32 <td> </td>
33 <td><s:submit value="添加" /><s:reset value="重置" /></td>
34 </tr>
35 </table>
36 </s:form>
37 </body>
38 </html>
注意:<s:textfield />标签里面的name属性值的格式,这样才能被action辨认,方便反射。index.jsp页面里面去掉了对于编码来说不必要的部分,比如说head不分的meta块,实际的web前端开发中,这一部分是及其重要的,涉及到SEO知识,大家了解这个关联就好,这里不做阐述。具体请见【待填】
5、在cn.dy.dao新建UserDao.java接口
1 package cn.dy.dao;
2
3 import java.util.List;
4 import cn.dy.bean.User;
5
6 public interface UserDao {
7
8 public void insert(User user);
9
10 public User search(Integer userId);
11
12 public void delete(Integer userIds);
13
14 public List<User> list();
15 }
cn.dy.dao.impl新建UserDaoBean.java类,@Transactional声明这是事务方法,这就是基于注解方式配置事务;@Repository("userDao")注意这样写以后,后面调用的userDao,就是UserDaoBean.java,而不是UserDao.java。@Transactional(propagation = Propagation.NOT_SUPPORTED)很明显,查找是不需要事务处理的。只有需要提交的方法才需要事务处理,比如说:添加,删除,修改。
1 package cn.dy.dao.impl;
2
3 import java.util.List;
4 import cn.dy.bean.User;
5 import cn.dy.dao.UserDao;
6 import javax.annotation.Resource;
7
8 import org.hibernate.SessionFactory;
9 import org.springframework.stereotype.Repository;
10 import org.springframework.transaction.annotation.Propagation;
11 import org.springframework.transaction.annotation.Transactional;
12
13 @Repository("userDao")
14 @Transactional
15 public class UserDaoBean implements UserDao {
16
17 @Resource
18 SessionFactory factory;
19
20 @Override
21 public void delete(Integer userIds) {
22 // 不要使用get方法查找.效率很低,这里使用load方法
23 for (Integer userId : userIds) {
24 factory.getCurrentSession().delete(
25 factory.getCurrentSession().load(User.class, userId));
26 }
27 }
28
29 @Override
30 @Transactional(propagation = Propagation.NOT_SUPPORTED)
31 public User search(Integer userId) {
32 return (User) factory.getCurrentSession().get(User.class, userId);
33 }
34
35 @SuppressWarnings("unchecked")
36 @Override
37 @Transactional(propagation = Propagation.NOT_SUPPORTED)
38 public List<User> list() {
39 return factory.getCurrentSession().createQuery("from User").list();
40 }
41
42 @Override
43 public void insert(User user) {
44 // persist相当于save.而merge相当于saveOrUpdate
45 factory.getCurrentSession().persist(user);
46 }
47 }
48
cn.dy.service新建UserService.java接口,这里大家都注意到了,和UserDao.java几乎完全相同,那为什么还需要多此一举呢?事实上,这是很有必要的,具体见:【待填】
1 package cn.dy.service;
2
3 import java.util.List;
4 import cn.dy.bean.User;
5
6 public interface UserService {
7
8 public void insert(User user);
9
10 public User search(Integer userId);
11
12 public void delete(Integer userIds);
13
14 public List<User> list();
15 }
cn.dy.service.impl新建UserServiceBean.java类,注意这里的@Service("userService"),在测试类中反射时候,userService就是代表UserServiceBean.java类。
1 package cn.dy.service.impl;
2
3 import java.util.List;
4 import javax.annotation.Resource;
5 import org.springframework.stereotype.Service;
6 import cn.dy.bean.User;
7 import cn.dy.dao.UserDao;
8 import cn.dy.service.UserService;
9
10 @Service("userService")
11 public class UserServiceBean implements UserService {
12
13 @Resource
14 private UserDao userDao;
15
16 public void setUserDao(UserDao userDao) {
17 this.userDao = userDao;
18 }
19
20 @Override
21 public void delete(Integer userIds) {
22 userDao.delete(userIds);
23 }
24
25 @Override
26 public User search(Integer userId) {
27 return userDao.search(userId);
28 }
29
30 @Override
31 public List<User> list() {
32 return userDao.list();
33 }
34
35 @Override
36 public void insert(User user) {
37 userDao.insert(user);
38 }
39 }
40
6、数据层和业务层都已经建好了,最后建立action,在cn.dy.action新建UserAction.java类,@Controller注解这是个控制类,@Scope("prototype")设置这个类为非单例模式,什么时候设为非单例呢,当action中存放针对某个用户的信息时,如用户注册,就要用@Scope("prototype")避免默认的单例模式。如果想知道不设置这个会有什么后果,也很简单,去掉这一行代码,然后连续注册两个用户,你的答案就会出现。这里纠正一下网上某些文章的解决办法,有些文章说可以修改UserDaoBean.java类中的insert方法,修改persist(user)为merge(user);确实解决了不能连续注册的问题,但是..merge不等于persist,这样会有什么样的后果,留给大家自己先思考下。(我提示下,会有非常严重的资料同步问题,怎么发生的,自己思考吧),千万不要把persist换成merge!切记。
1 package cn.dy.action;
2
3 import javax.annotation.Resource;
4
5 import org.springframework.context.annotation.Scope;
6 import org.springframework.stereotype.Controller;
7 import com.opensymphony.xwork2.ActionSupport;
8 import cn.dy.bean.User;
9 import cn.dy.service.UserService;
10
11 @Controller
12 @Scope("prototype")
13 public class UserAction extends ActionSupport {
14 @Resource
15 UserService userService;
16 private User user;
17
18 public User getUser() {
19 return user;
20 }
21
22 public void setUser(User user) {
23 this.user = user;
24 }
25
26 public String insert() {
27 return null;
28 }
29 }
30
7、在struts配置文件里面配置action,好让表单提交的时候能找到相对应的路径。
1 <package name="user" namespace="/user" extends="struts-default">
2 <action name="op_*" class="userAction" method="{1}">
3 <result>/success.jsp</result>
4 </action>
5 </package>
op_*说明以op_开头的跳转都会到userAction,而那个星号所代表的单词就是userAction里面的方法名称,由method={1}映射,另外一个注意点就是result的跳转类型,这里因为是简单的项目,不会太详细解释,详情请移步【待填】
8、好了,现在开始扫尾,在和index.jsp同一级目录新建success.jsp文件,里面就写一句代码:注册成功,欢迎某某(如何获取action传过来的值?请移步【待填】)
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2
3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
4 <html>
5 <head>
6 <title>结果页面</title>
7 </head>
8 <body>
9 注册成功,欢迎${requestScope.user.userName}
10 </body>
11 </html>
12
index.jsp页面里面改变<s:form>的提交代码<s:form action="op_insert" namespace="/user" method="post">
UserAction里面的insert方法代码(SUCCESS是默认值,action必须继承com.opensymphony.xwork2.ActionSupport才能使用,其他默认值详见【待填】)
1 public String insert() {
2 userService.insert(user);
3 return SUCCESS;
4 }
9、测试,把项目部署到tomcat中,然后地址栏输入http://localhost:8080/DyEngima/,返回正确页面。
下面将要讨论的是注册页面的ajax验证,我这里是通过jQuery实现的。