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**
** List datas、offset、size、total**
** 3.写SystemContext类**
** 7.写UserException异常类**
数据持久层dao层,主要是操作Hibernate,还要写beans.xml
** 4.写IUserDao接口**
** 增、更新、删除、根据ID查用户load、查所用用户List list、查分页Pager find、根据username查用户loadByUsername**
** 5.实现IUserDao接口**
** 分页find()中取得SystemContext类**
业务逻辑层service层,主要是写验证
** 6.写IUserService接口**
** 增、更新、删除、根据ID查用户load、查所用用户List list、查分页Pager 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
1 2 mysql> create database spring_user;
并把字符编码改成UTF-8,可以参考 Ubuntu下的MySQL安装
1 2 create database spring_user default character set utf8 collate utf8_general_ci;
添加t_user表
1 2 CREATE TABLE IF NOT EXISTS `t_user` (`username` varchar(64) NOT NULL,`password` varchar(11) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;
** 插入用户和密码**
1 2 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <%@ 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
1 2 3 4 5 6 7 8 9 10 11 12 13 <%@ 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**
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 <%@ 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> |用户名:|<sf:input path="username"/><sf:errors path="username"/> </tr> <tr> |用户密码:|<sf:password path="password"/><sf:errors path="password"/> </tr> <tr> |用户昵称:|<sf:input path="nickname"/> </tr> <tr> |用户邮箱:|<sf:input path="email"/><sf:errors path="email"/> </tr> <tr> <td colspan="2"> <input type="submit" value="用户添加"/> </td> </tr> </table> </sf:form> </body> </html>
list.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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 <%@ 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> |用户标识:${pagers.total }|用户名|用户昵称|用户密码|用户邮箱 |操作 </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> |${u.id }|${u.username } |[${u.nickname }](${u.id }) |${u.password }|${u.email } |[更新](${u.id }/update) [删除](${u.id }/delete) </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
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 <%@ 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> |用户标识:|${user.id } </tr> <tr> |用户名:|${user.username } </tr> <tr> |用户密码:|${user.password } </tr> <tr> |用户昵称:|${user.nickname } </tr> <tr> |用户邮箱:|${user.email } </tr> </table> </body> </html>
update.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 28 29 30 31 32 33 34 <%@ 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> |用户名:|${user.username }<sf:hidden path="username"/> </tr> <tr> |用户密码:|<sf:password path="password"/><sf:errors path="password"/> </tr> <tr> |用户昵称:|<sf:input path="nickname"/> </tr> <tr> |用户邮箱:|<sf:input path="email"/><sf:errors path="email"/> </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方法
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 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文件里面将该实体类加进去即可:
1 2 3 4 5 <!-- 基于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实体方法
1 2 3 4 5 6 7 8 <property name="annotatedClasses"> <list> <value>com.sise.domain.Admin</value> <value>com.sise.domain.Remind</value> <value>com.sise.domain.User</value> </list> </property>
可以使用下面的来替代
1 2 3 4 5 <!-- 设置Spring取那个包中查找相应的实体类,指定hibernate实体类映射文件 --> <property name="packagesToScan"> <value>org.common.model</value> </property>
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 <!-- 导入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**
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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
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 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
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 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 的目的。
因此我定义如下的类:
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 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(); } }