此文是在这篇博文的基础上进行的,原文在这里http://blog.csdn.net/bjyfb/article/details/8998267
1. 说明
搭建SpringMVC+Spring+Hibernate的框架,项目结构如图1所示
引用的jar包为Spring3.2.6和Hibernate4,如图2所示
2. 配置文件
2.1 spring-mvc.xml
注意看其中的注释内容,写的比较详细
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"
default-autowire="byName">
<!-- 开启注解,java文件里的@ -->
<mvc:annotation-driven />
<!-- 注解扫描包,注意换成自己的路径 -->
<context:component-scan base-package="com.lq.controller">
<!-- 只扫描@Controller的部分 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--完成请求和注解POJO的映射 -->
<bean
class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<!-- 静态资源(js/image)的访问 ,可添加多个-->
<mvc:resources location="/js/" mapping="/js/**" />
<!-- 定义视图解析器 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
2.2 spring-common.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 注意下面配置中的spring-*.xsd的版本号要与使用的jar包匹配 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 只解析除controller之外的注解(即解析service、dao), 避免重复加载导致事务失效 -->
<context:component-scan base-package="com.lq">
<!-- annotation为spting-mvc中解析的内容 -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<!-- 换成自己的数据库路径 -->
<property name="url" value="jdbc:mysql://localhost/mvctest"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- 配置SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- packagesToScan 扫描包所在路径(name中的内容其实是个关键字,可以扫描一整个包) -->
<property name="packagesToScan">
<list>
<!-- 此处可添加多个entity -->
<value>com.lq.entity</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<!-- 第一次生成数据库的时候用create,之后换成update,否则内容会清空 -->
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext
</prop>
</props>
</property>
</bean>
<!-- 配置一个事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 拦截的是下段配置aop里设置的路径,即txPointcut中配置的路径 -->
<!-- 具体的propagation含义请自查 -->
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="merge*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="put*" propagation="REQUIRED" />
<tx:method name="use*" propagation="REQUIRED" />
<!--hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到 -->
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="count*" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" propagation="REQUIRED" read-only="true" />
<tx:method name="list*" propagation="REQUIRED" read-only="true" />
<tx:method name="*" read-only="true" />
</tx:attributes>
</tx:advice>
<aop:config expose-proxy="true">
<!-- 只对业务逻辑层(service层)实施事务 -->
<aop:pointcut id="txPointcut"
expression="execution(* com.lq.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
</aop:config>
</beans>
2.3 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>Spring-MVC-model</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 加载所有的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:config/spring/spring-*.xml</param-value>
</context-param>
<!-- 配置Spring监听 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置SpringMVC -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:config/spring/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置字符集 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置Session -->
<filter>
<filter-name>openSession</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openSession</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
3. POJO类
3.1 User
package com.lq.entity;
import javax.persistence.*;
import org.hibernate.annotations.GenericGenerator;
@Entity
//创建的数据库表名称
@Table(name = "T_USER")
public class User {
@Id
//关键字生成模式
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(length = 32)
private String id;
@Column(length = 32)
private String userName;
@Column(length = 32)
private String age;
//省略了get和set方法
}
3.2 Customer
package com.lq.entity;
import javax.persistence.*;
import org.hibernate.annotations.GenericGenerator;
@Entity
@Table(name = "t_customer")
public class Customer {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(length = 32)
private String id;
@Column(length = 32)
private String name;
@Column(length = 32)
private String age;
//省略了get和set方法
}
4. Dao层
4.1 UserDao
package com.lq.dao;
import java.util.List;
import com.lq.entity.User;
public interface UserDao {
public User getUser(String id);
public List<User> getAllUser();
public void addUser(User user);
public boolean delUser(String id);
public boolean updateUser(User user);
}
4.2 UserDaoImpl
实现了UserDao中的接口
package com.lq.dao;
import java.util.List;
import javax.annotation.Resource;
import com.lq.entity.User;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Repository;
//注入
@Repository
public class UserDaoImpl implements UserDao {
//注入已在spring-common.xml中配制好的sessionFactory
@Resource(name = "sessionFactory")
private SessionFactory sessionFactory;
@Override
public User getUser(String id) {
String hql = "from User u where u.id=?";
Query query = sessionFactory.getCurrentSession().createQuery(hql);
query.setString(0, id);
return (User) query.uniqueResult();
}
@Override
public List<User> getAllUser() {
String hql = "from User";
Query query = sessionFactory.getCurrentSession().createQuery(hql);
return query.list();
}
@Override
public void addUser(User user) {
sessionFactory.getCurrentSession().save(user);
}
@Override
public boolean delUser(String id) {
String hql = "delete User u where u.id = ?";
Query query = sessionFactory.getCurrentSession().createQuery(hql);
query.setString(0, id);
return (query.executeUpdate() > 0);
}
@Override
public boolean updateUser(User user) {
String hql = "update User u set u.userName = ?,u.age=? where u.id = ?";
Query query = sessionFactory.getCurrentSession().createQuery(hql);
query.setString(0, user.getUserName());
query.setString(1, user.getAge());
query.setString(2, user.getId());
return (query.executeUpdate() > 0);
}
}
4.3 CustomerDao
因为CustomerDao主要是用来测试hibernate的事务机制是否起作用的,所以就写了一个方法
package com.lq.dao;
import com.lq.entity.Customer;
public interface CustomerDao {
public void addCustomer(Customer customer);
}
4.4 CustomerDaoImpl
package com.lq.dao;
import javax.annotation.Resource;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Repository;
import com.lq.entity.Customer;
@Repository
public class CustomerDaoImpl implements CustomerDao {
@Resource(name = "sessionFactory")
private SessionFactory sessionFactory;
@Override
public void addCustomer(Customer customer) {
sessionFactory.getCurrentSession().save(customer);
}
}
5. Service层
5.1 UserService
package com.lq.service;
import java.util.List;
import com.lq.entity.User;
public interface UserService {
public User getUser(String id);
public List<User> getAllUser();
public void addUser(User user);
public boolean delUser(String id);
public boolean updateUser(User user);
}
5.2 UserServiceImpl
package com.lq.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.lq.dao.CustomerDao;
import com.lq.dao.UserDao;
import com.lq.entity.Customer;
import com.lq.entity.User;
//注入Service
@Service
public class UserServiceImpl implements UserService {
//注入Dao
@Autowired
private UserDao userDao;
@Autowired
private CustomerDao customerDao;
@Override
public User getUser(String id) {
return userDao.getUser(id);
}
@Override
public List<User> getAllUser() {
return userDao.getAllUser();
}
@Override
public void addUser(User user) {
userDao.addUser(user);
}
@Override
public boolean delUser(String id) {
return userDao.delUser(id);
}
@Override
public boolean updateUser(User user) {
return userDao.updateUser(user);
}
}
5.3 CustomerService
package com.lq.service;
import com.lq.entity.Customer;
public interface CustomerService {
public void addCustomer(Customer customer);
}
5.4 CustomerServiceImpl
package com.lq.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.lq.dao.CustomerDao;
import com.lq.entity.Customer;
@Service
public class CustomerServiceImpl implements CustomerService {
@Autowired
private CustomerDao customerDao;
@Override
public void addCustomer(Customer customer) {
customerDao.addCustomer(customer);
}
}
6. Controller层 - UserController
package com.lq.controller;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.lq.entity.User;
import com.lq.service.CustomerService;
import com.lq.service.UserService;
//注入controller
@Controller
@RequestMapping("/user")
public class UserController {
//注入service
@Autowired
private UserService userService;
@Autowired
private CustomerService customerService;
@RequestMapping("/getAllUser")
public String getAllUser(HttpServletRequest request) {
request.setAttribute("userList", userService.getAllUser());
return "/index";
}
@RequestMapping("/getUser")
public String getUser(String id, HttpServletRequest request) {
request.setAttribute("user", userService.getUser(id));
return "/editUser";
}
@RequestMapping("/toAddUser")
public String toAddUser() {
return "/addUser";
}
@RequestMapping("/addUser")
public String addUser(User user, HttpServletRequest request) {
try {
userService.addUser(user);
return "redirect:/user/getAllUser";
} catch (Exception e) {
return "/error";
}
}
@RequestMapping("/delUser")
public void delUser(String id, HttpServletResponse response) {
String result = "{\"result\":\"error\"}";
if (userService.delUser(id)) {
result = "{\"result\":\"success\"}";
}
response.setContentType("application/json");
try {
PrintWriter out = response.getWriter();
out.write(result);
} catch (IOException e) {
e.printStackTrace();
}
}
@RequestMapping("/updateUser")
public String updateUser(User user, HttpServletRequest request) {
if (userService.updateUser(user)) {
user = userService.getUser(user.getId());
request.setAttribute("user", user);
return "redirect:/user/getAllUser";
} else {
return "/error";
}
}
}
7. 前台界面
7.1 index.jsp
在搭建时注意更换自己的路径,别忘了引入jQuery包
<%@ 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>
<script type="text/javascript" src="../js/jquery-1.10.2.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
function del(id){
$.get("/Spring-MVC-model/user/delUser?id=" + id,function(data){
if("success" == data.result){
alert("删除成功");
window.location.reload();
}else{
alert("删除失败");
}
});
}
</script>
</head>
<body>
<h6><a href="/Spring-MVC-model/user/toAddUser">添加用户</a></h6>
<table border="1">
<tbody>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>操作</th>
</tr>
<c:if test="${!empty userList }">
<c:forEach items="${userList }" var="user">
<tr>
<td>${user.userName }</td>
<td>${user.age }</td>
<td>
<a href="/Spring-MVC-model/user/getUser?id=${user.id }">编辑</a>
<a href="javascript:del('${user.id }')">删除</a>
</td>
</tr>
</c:forEach>
</c:if>
</tbody>
</table>
</body>
</html>
7.2 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>Insert title here</title>
</head>
<body>
<h5><a href="/Spring-MVC-model/user/getAllUser">进入用户管理页</a></h5>
</body>
</html>
7.3 addUser.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>Insert title here</title>
<script type="text/javascript">
function addUser(){
var form = document.forms[0];
form.action = "/Spring-MVC-model/user/addUser";
form.method="post";
form.submit();
}
</script>
</head>
<body>
<h1>添加用户</h1>
<form action="" name="userForm">
姓名:<input type="text" name="userName">
年龄:<input type="text" name="age">
<input type="button" value="添加" onclick="addUser()">
</form>
</body>
</html>
7.4 editUser.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>
<script type="text/javascript" src="../js/jquery-1.10.2.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>编辑用户</h1>
<form action="/Spring-MVC-model/user/updateUser" name="userForm" method="post">
<input type="hidden" name="id" value="${user.id }">
姓名:<input type="text" name="userName" value="${user.userName }">
年龄:<input type="text" name="age" value="${user.age }">
<input type="submit" value="编辑" >
</form>
</body>
</html>
7.5 error.jsp和success.jsp只有一行文字
8. 执行
现在,就可以用tomcat启动工程了,显示效果如下
8.1 载入页面
从此地址进入:http://localhost:8080/Spring-MVC-model/login.jsp
8.2 显示存在用户
8.3 添加用户
8.4 删除用户
9. 检测Hibernate事务机制
首先,在UserServiceImpl中,修改addUser方法
@Override
public void addUser(User user) {
/* 用于测试hibernate的事务机制是否起作用
* 在数据库中把user表的age字段设置为Not NULL,即输入null值会报错
* 正确保存customer数据后,user数据会因为null值报错
* 此时,若事务机制启动,则customer和user的数据都不会保存*/
Customer customer = new Customer();
customer.setAge("15");
customer.setName("43");
customerDao.addCustomer(customer);
userDao.addUser(user);
}
然后执行,发现两个表的数据添加成功。
接着,再在该addUser方法下,添加语句,使user的age为null
@Override
public void addUser(User user) {
...
user.setAge(null);
userDao.addUser(user);
}
并数据库中User表的age字段设置为Not null
最后执行,会显示error界面。此时查看数据库,customer和user的数据都没有写入,证明hibernate事务起作用了。
10. 遇到的错误
10.1 jar包引用错误
报错信息如下
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Cannot locate BeanDefinitionParser for element [resources]
当时没把错误记下来,但是解决方法是一样的。错误原因是由于spring的配置文件中开头的注释与使用的jar包不匹配。
出处:http://stackoverflow.com/questions/13080485/spring-mvc-3-issue-with-the-resources-tag
10.2 Error creating bean with name ‘UserServiceImpl’: Injection of resource dependencies failed;
这类错误多半是配置文件的问题,请仔细查看spring-*.xml中配置的项目路径,以及接口实现(Impl)的文件中是否使用注入(@)
10.3 引用<%@ taglib prefix=”c” uri=”http://java.sun.com/jsp/jstl/core” %>出错
需要导入jstl.jar和standard.jar两个jar包。
11. 结束语
至此,SpringMVC和Hibernate都可以跑起来了,如遇到问题,请静心仔细看注释部分。其他的内容就要不断地摸索了。再次感谢原作者的分享以及帮助我的朋友们。
附上项目下载地址:http://download.csdn.net/detail/shaunqing/8672283
以上(2015.5.7)