工程地址:https://github.com/tonglin0325/article-manager.git
1.搭建環境的第一步是導包,把下面這些包都導入工程中
/media/common/工作/Ubuntu軟件/SpringMVC_jar包整理/aop
/media/common/工作/Ubuntu軟件/SpringMVC_jar包整理/apache-commons-logging
/media/common/工作/Ubuntu軟件/SpringMVC_jar包整理/apache-log4j
/media/common/工作/Ubuntu軟件/SpringMVC_jar包整理/bean-validator
/media/common/工作/Ubuntu軟件/SpringMVC_jar包整理/dbcp
/media/common/工作/Ubuntu軟件/SpringMVC_jar包整理/hibernate-3.6.8.
/media/common/工作/Ubuntu軟件/SpringMVC_jar包整理/JSTL
/media/common/工作/Ubuntu軟件/SpringMVC_jar包整理/mysql
/media/common/工作/Ubuntu軟件/SpringMVC_jar包整理/pager
/media/common/工作/Ubuntu軟件/SpringMVC_jar包整理/sitemesh
/media/common/工作/Ubuntu軟件/SpringMVC_jar包整理/spring
手動導包也可以,不過不是很方便,推薦學習使用maven的pom.xml文件來導入jar包
整個系統的結構

表示層(JSP頁面),一般包名是view
▼
控制層,一般包名是action或者web,控制層也會操作實體層
▼
業務邏輯層,一般包名是service
▼
數據持久層,一般包名是dao
▼
實體層(JavaBean),一般包名是model或者entity
寫成的過程和上面的方向相反,從下往上寫
實體Entity層
1.先寫User類
Id,username,nickname,password,email
其中還包括注入
2.再寫Page類
public class Pager<T>
List<T> datas、offset、size、total
3.寫SystemContext類
7.寫UserException異常類
數據持久層dao層,主要是操作Hibernate,還要寫beans.xml
4.寫IUserDao接口
增、更新、刪除、根據ID查用戶load、查所用用戶List<User> list、查分頁Pager<User> find、根據username查用戶loadByUsername
5.實現IUserDao接口
分頁find()中取得SystemContext類
業務邏輯層service層,主要是寫驗證
6.寫IUserService接口
增、更新、刪除、根據ID查用戶load、查所用用戶List<User> list、查分頁Pager<User> find、根據username查用戶loadByUsername
8.實現IUserService接口
密碼登錄驗證login、添加用戶、修改用戶、刪除用戶、查詢用戶、列出所有用戶、分頁find()
控制層action層
9.LoginFilter.java登錄權限,實現Filter接口,doFilter()方法
在請求是/user/*的時候攔截驗證權限,沒有權限重定向/login,有權限放行
10.SystemContext.java分頁過濾,實現Filter接口,doFilter()方法
在請求是/*中,如果參數為Pager.offset的時候,攔截取得offset,設置SystemContext中的offset和size
11.IndexController.java,Session共享數據
在請求是/login的時候,將ModelMap中的屬性放入Session中,實現多窗口共享數據
12.UserController.java,總的請求為/user,這也就是MVC模型中的RequestMapping
在請求是/user和/的時候,向model模型中添加——userService.find()
在請求是/add的時候(分GET和POST),向model模型中添加——new User()
在請求是/{id}的時候,向model模型中添加——userService.load(id)
在請求是/{id}/update的時候(分GET和POST)...
在請求是/{id}/delete的時候...
最后再傳給DispatchServlet,使用model從Controller給視圖傳值
在jsp中通過 ${ } 取得屬性
記得加上@Controller,通過Annotation來配置控制器
注意:在持久層、業務層、控制層中,分別采用@Repository、@Service、@Controller對分層中的類進行注釋
2.在工程的src/目錄下加入beans.xml、jdbc.properties和log4j.properties這三個文件
3.新建一個數據庫文件
新建一個數據庫spring_user
mysql> create database spring_user;

並把字符編碼改成UTF-8,可以參考 Ubuntu下的MySQL安裝

create database spring_user default character set utf8 collate utf8_general_ci;
添加t_user表
CREATE TABLE IF NOT EXISTS `t_user` (`username` varchar(64) NOT NULL,`password` varchar(11) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;
插入用戶和密碼
INSERT INTO t_user (username,password) VALUES('admin','admin');
4.接下來在頁面就可以用admin來登錄

而且中文也正常顯示

整個項目的結構
1.JSP頁面:登錄、添加、列表、詳情、更新、錯誤

2.實體層(Bean或者model):分頁類、分頁查詢結果類、用戶類、Exception類

3.控制層(Action):頁面控制器、登錄過濾器、分頁查詢結果過濾器、用戶控制器

4.業務邏輯層(Service):一個接口和一個實現類(包括注入userDAO、登入驗證、添刪該查用戶等等)

5.數據持久層(DAO):一個接口和一個實現類(和HibernateDaoSupport相關,用戶增刪改查等等)

1.JSP頁面
login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用戶登錄</title>
</head>
<body>
<form method="post">
用戶名:<input type="text" name="username"/><br/>
用戶密碼:<input type="password" name="password"/><br/>
<input type="submit" value="用戶登錄"/>
</form>
</body>
</html>
error.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>發現異常</title>
</head>
<body>
<h1>${exception.message }</h1>
</body>
</html>
add.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用戶添加</title>
</head>
<body>
<sf:form method="post" modelAttribute="user">
<table width="700" align="center" border="1">
<tr>
<td>用戶名:</td><td><sf:input path="username"/><sf:errors path="username"/></td>
</tr>
<tr>
<td>用戶密碼:</td><td><sf:password path="password"/><sf:errors path="password"/></td>
</tr>
<tr>
<td>用戶昵稱:</td><td><sf:input path="nickname"/></td>
</tr>
<tr>
<td>用戶郵箱:</td><td><sf:input path="email"/><sf:errors path="email"/></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="用戶添加"/>
</td>
</tr>
</table>
</sf:form>
</body>
</html>
list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用戶列表</title>
</head>
<body>
<table width="700" align="center" border="1">
<tr>
<td>用戶標識:${pagers.total }</td><td>用戶名</td><td>用戶昵稱</td><td>用戶密碼</td><td>用戶郵箱</td>
<td>操作</td>
</tr>
<c:if test="${pagers.total le 0 }">
<tr>
<td colspan="6">目前還沒有用戶數據</td>
</tr>
</c:if>
<c:if test="${pagers.total gt 0}">
<c:forEach items="${pagers.datas }" var="u">
<tr>
<td>${u.id }</td><td>${u.username }</td>
<td><a href="${u.id }">${u.nickname }</a></td>
<td>${u.password }</td><td>${u.email }</td>
<td><a href="${u.id }/update">更新</a> <a href="${u.id }/delete">刪除</a></td>
</tr>
</c:forEach>
<tr>
<td colspan="6">
<jsp:include page="/inc/pager.jsp">
<jsp:param value="users" name="url"/>
<jsp:param value="${pagers.total}" name="items"/>
</jsp:include>
</td>
</tr>
</c:if>
</table>
</body>
</html>
show.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用戶[${user.nickname }]詳細信息</title>
</head>
<body>
<table width="700" align="center" border="1">
<tr>
<td>用戶標識:</td><td>${user.id }</td>
</tr>
<tr>
<td>用戶名:</td><td>${user.username }</td>
</tr>
<tr>
<td>用戶密碼:</td><td>${user.password }</td>
</tr>
<tr>
<td>用戶昵稱:</td><td>${user.nickname }</td>
</tr>
<tr>
<td>用戶郵箱:</td><td>${user.email }</td>
</tr>
</table>
</body>
</html>
update.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用戶更新</title>
</head>
<body>
<sf:form method="post" modelAttribute="user">
<table width="700" align="center" border="1">
<tr>
<td>用戶名:</td><td>${user.username }<sf:hidden path="username"/></td>
</tr>
<tr>
<td>用戶密碼:</td><td><sf:password path="password"/><sf:errors path="password"/></td>
</tr>
<tr>
<td>用戶昵稱:</td><td><sf:input path="nickname"/></td>
</tr>
<tr>
<td>用戶郵箱:</td><td><sf:input path="email"/><sf:errors path="email"/></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="用戶更新"/>
</td>
</tr>
</table>
</sf:form>
</body>
</html>
分頁結構

5.在src/目錄下建立包org.common.model
model包中一般放的是實體類,這些類定義了一些基本的屬性以及簡單的get/set方法,這些類和數據庫中的表存在對應關系
一般都是javabean對象,例如與數據庫的某個表相關聯。

先寫User類,文件名字為User.java,其中就是簡單的get方法和set方法
package org.common.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity //如果我們當前這個bean要設置成實體對象,就需要加上Entity這個注解
@Table(name="t_user") //設置數據庫的表名
public class User {
private int id;
private String username;
private String nickname;
private String password;
private String email;
//(建議不要在屬性上引入注解,因為屬性是private的,如果引入注解會破壞其封裝特性,所以建議在getter方法上加入注解)
@Id //定義為數據庫的主鍵ID
@GeneratedValue //ID的生成策略為自動生成
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
接下來只需要在hibernate.cfg.xml文件里面將該實體類加進去即可:
<!-- 基於annotation的配置 -->
<mapping class="com.xiaoluo.bean.User"/>
<!-- 基於hbm.xml配置文件 -->
<mapping resource="com/xiaoluo/bean/User.hbm.xml"/>
但是,我們采取的方法是使用Spring配置數據源,即在Spring容器中定義數據源,指定映射文件、設置hibernate控制屬性等信息,完成集成組裝的工作,完全拋開hibernate.cfg.xml配置文件,具體的方法就是在beans.xml文件中加入



其中的Spring注解hibernate實體方法
<property name="annotatedClasses">
<list>
<value>com.sise.domain.Admin</value>
<value>com.sise.domain.Remind</value>
<value>com.sise.domain.User</value>
</list>
</property>
可以使用下面的來替代
<!-- 設置Spring取那個包中查找相應的實體類,指定hibernate實體類映射文件 --> <property name="packagesToScan"> <value>org.common.model</value> </property>
<!-- 導入Src目錄下的jdbc.properties文件 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!-- 配置連接池的初始值 -->
<property name="initialSize" value="1" />
<!-- 連接池的最大值 -->
<!-- <property name="maxActive" value="500"/> -->
<!-- 最大空閑時,當經過一個高峰之后,連接池可以將一些用不到的連接釋放,一直減少到maxIdle為止 -->
<!-- <property name="maxIdle" value="2"/> -->
<!-- 當最小空閑時,當連接少於minIdle時會自動去申請一些連接 -->
<property name="minIdle" value="1" />
<property name="maxActive" value="100" />
<property name="maxIdle" value="20" />
<property name="maxWait" value="1000" />
</bean>
<!--創建Spring的SessionFactory工廠 -->
<!-- 如果使用的是Annotation的方式,不能使用LocalSessionFactoryBean,而應該使用 org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<!-- 注入數據源 -->
<property name="dataSource" ref="dataSource" />
<!-- 設置Spring取那個包中查找相應的實體類,指定hibernate實體類映射文件 -->
<property name="packagesToScan">
<value>org.common.model</value>
</property>
<!-- 指定hibernate配置屬性-->
<property name="hibernateProperties">
<!-- <value> hibernate.dialect=org.hibernate.dialect.HSQLDialect </value> -->
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.format_sql">false</prop>
</props>
</property>
</bean>
6.在src/目錄下建立包org.common.dao
在dao中,寫與數據庫的操作,增刪改查等方法

首先寫IUserDao接口,文件名為IUserDao.java
package org.common.dao;
import java.util.List;
import org.common.model.Pager;
import org.common.model.User;
public interface IUserDao { //IUserDao接口
public void add(User user);
public void update(User user);
public void delete(int id);
public User load(int id);
public List<User> list();
public Pager<User> find();
public User loadByUsername(String username);
}
同時,還要在包org.common.model下加上分頁的類,文件名是Page.java
package org.common.model;
import java.util.List;
public class Pager<T> { //分頁
private List<T> datas;
private int offset;
private int size;
private long total;
public List<T> getDatas() {
return datas;
}
public void setDatas(List<T> datas) {
this.datas = datas;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
}
在寫完分頁的類之后,接下來寫DAO返回給service的東西,文件名是SystemContext.java
package org.common.model;
public class SystemContext { //傳分頁需要把當前頁和每頁顯示多少條
private static ThreadLocal<Integer> offset = new ThreadLocal<Integer>();
private static ThreadLocal<Integer> size = new ThreadLocal<Integer>();
public static Integer getOffset() {
return offset.get();
}
public static void setOffset(Integer _offset) {
offset.set(_offset);
}
public static void removeOffset() {
offset.remove();
}
public static Integer getSize() {
return size.get();
}
public static void setSize(Integer _size) {
size.set(_size);
}
public static void removeSize() {
size.remove();
}
}
接下來實現IUserDao接口,寫UserDao類,文件名是UserDao.java
在實現的同時,還要繼承HibernateDaoSupport,extends HibernateDaoSupport
但是在spring 的HibernateDaoSupport中,setSessionFactory是使用final 修飾的,無法重寫,沒有辦法使用注解的方式注入sessionFactroy
所以可以自己定義一個方法,這個方法去調用hibernateDaoSupport 中的setSessionFacotry方法,達到注入sessionFactory 的目的。
因此我定義如下的類:
package org.common.dao;
import java.util.List;
import javax.annotation.Resource;
import org.common.model.Pager;
import org.common.model.SystemContext;
import org.common.model.User;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;
@Repository("userDao") //申明一個DAO
public class UserDao extends HibernateDaoSupport implements IUserDao {
//但是在spring 的HibernateDaoSupport中,setSessionFactory是使用final 修飾的,無法重寫,沒有辦法使用注解的方式注入sessionFactroy
//所以可以自己定義一個方法,這個方法去調用hibernateDaoSupport 中的setSessionFacotry方法,達到注入sessionFactory 的目的。
@Resource
public void setSuperSessionFactory(SessionFactory sessionFactory) {
this.setSessionFactory(sessionFactory);
}
@Override
public void add(User user) {
this.getHibernateTemplate().save(user);
}
@Override
public void update(User user) {
this.getHibernateTemplate().update(user);
}
@Override
public void delete(int id) {
User user = this.load(id);
this.getHibernateTemplate().delete(user);
}
@Override
public User load(int id) {
return this.getHibernateTemplate().load(User.class, id);
}
@SuppressWarnings("unchecked")
@Override
public List<User> list() {
return this.getSession().createQuery("from User").list();
}
@SuppressWarnings("unchecked")
@Override
public Pager<User> find() {
int size = SystemContext.getSize();
int offset = SystemContext.getOffset();
Query query = this.getSession().createQuery("from User");
query.setFirstResult(offset).setMaxResults(size);
List<User> datas = query.list();
Pager<User> us = new Pager<User>();
us.setDatas(datas);
us.setOffset(offset);
us.setSize(size);
long total = (Long)this.getSession()
.createQuery("select count(*) from User")
.uniqueResult();
us.setTotal(total);
return us;
}
@Override
public User loadByUsername(String username) {
return (User)this.getSession().createQuery("from User where username=?")
.setParameter(0, username).uniqueResult();
}
}
