上一篇已經搭建好了開發環境,現在用一個簡單的注冊登錄來體驗一下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>&nbsp;</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實現的。


      此文部分內容來源網絡。如有侵犯您的版權問題,請來消息至電子郵件DyEngima&163.com(&換成@),經核實后會在文章內部標明來源。
轉載請注明來源http://www.aygfsteel.com/DyEnigma/
簽名:有能力、有擔當、有情義的人才能稱之為男人,而不是由性別決定。