前言:第一次搭建SSH(Spring+SpringMVC+Hibernate)框架,所以写点笔记记录一下,方便以后查看。本次操作环境是 Fedora 27 + Intellij IDEA 2017.3.5 (Ultimate Edition) + JDK 1.8.0_161 + Tomcat 8.5.31 + Apache Maven 3.5.4 。
本次的 SSH 框架搭建,是直接使用 Maven 来构建项目,这样就不用自己手动添加包了,而且更换包版本时也方便的多。搭建 SSH 框架,首先先创建一个 Maven Web 项目,这里不详细讲,下面给出链接:
Eclipse: http://www.cnblogs.com/leiOOlei/p/3361633.html
IDEA: https://blog.csdn.net/zht666/article/details/8673609
创建完成之后,就开始导入项目开发所需要的 jar 包,Maven 导入包很方便,直接在 .xml 中添加 jar 的信息,它会自动下载和导入项目中。在 pom.xml 中添加内容,最终文件内容如下:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.wjdgroupId>
<artifactId>sspvhartifactId>
<version>1.0-SNAPSHOTversion>
<properties>
<springVersion>4.3.18.RELEASEspringVersion>
<hibernateVersion>5.1.14.FinalhibernateVersion>
<jstlVersion>1.2jstlVersion>
<taglibVersion>1.1.2taglibVersion>
<servletVersion>3.0-alpha-1servletVersion>
<jsonVersion>1.9.13jsonVersion>
<jacksonVersion>2.5.0jacksonVersion>
<mysqlVersion>8.0.11mysqlVersion>
<c3p0Version>0.9.1.2c3p0Version>
<log4jVersion>1.2.17log4jVersion>
<fileuploadVersion>1.3.1fileuploadVersion>
properties>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>${springVersion}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-coreartifactId>
<version>${springVersion}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>${springVersion}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-ormartifactId>
<version>${springVersion}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>${springVersion}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>${springVersion}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>${springVersion}version>
dependency>
<dependency>
<groupId>org.hibernategroupId>
<artifactId>hibernate-coreartifactId>
<version>${hibernateVersion}version>
dependency>
<dependency>
<groupId>org.hibernategroupId>
<artifactId>hibernate-entitymanagerartifactId>
<version>${hibernateVersion}version>
dependency>
<dependency>
<groupId>jstlgroupId>
<artifactId>jstlartifactId>
<version>${jstlVersion}version>
dependency>
<dependency>
<groupId>taglibsgroupId>
<artifactId>standardartifactId>
<version>${taglibVersion}version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>${servletVersion}version>
<scope>providedscope>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysqlVersion}version>
dependency>
<dependency>
<groupId>c3p0groupId>
<artifactId>c3p0artifactId>
<version>${c3p0Version}version>
dependency>
<dependency>
<groupId>org.codehaus.jacksongroupId>
<artifactId>jackson-mapper-aslartifactId>
<version>${jsonVersion}version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-coreartifactId>
<version>${jacksonVersion}version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-annotationsartifactId>
<version>${jacksonVersion}version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>${jacksonVersion}version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>${log4jVersion}version>
dependency>
dependencies>
project>
基本上项目需要的 jar 已经导入了,如果还有其他的需求,可以自行添加。如果完全不知道该添加什么包,可以等程序运行出错时查看日志信息,从日志提示中得到未添加包的信息。
Spring MVC 是 Spring 提供的一个强大而灵活的 Web 框架。Spring MVC主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。他的两个核心是两个核心:
首先配置 Spring MVC 架构,先给出配置后的项目结构:
第一步先新建一个 web/WEB-INF/spingMVC.xml 文件,同时创建其他资源文件目录(如 resources 等),然后在文件中添加 Spring MVC 的配置:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.wjd" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
bean>
<mvc:resources mapping="/js/**" location="/resources/js/" />
<mvc:resources mapping="/css/**" location="/resources/css/" />
<mvc:resources mapping="/img/**" location="/resources/img/" />
beans>
配置好之后,将此配置文件信息添加到 web.xml 中,如下:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>dispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>/WEB-INF/springMVC.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>dispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
接下来就来测试一下 Spring MVC 是否配置成功了。新建 web/WEB-INF/views/testSpv.jsp 文件,添加文件内容如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>MVC Testtitle>
head>
<body>
This is a spring mvc test page!
body>
html>
然后在 controller 层创建一个 Controler 类,用于访问 testSpv.jsp 页面,内容如下:
package com.wjd.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class TestSpv {
@RequestMapping(value = "test", method = RequestMethod.GET)
public String test(){
return "testSpv";
}
}
前面在 springMVC.xml 文件中配置了视图解析器,因此这里返回的字符串 “testSpv” 会被解析器组装成 /WEB-INF/views/testSpv.jsp,以达到界面访问的目的。
最后是访问界面,首先将项目部署到 Tomcat 中,然后启动 Tomcat,在浏览器中访问地址 http://localhost:8080/sspvh/test(注意: sspvh 是我配置的根路径,应该根据不同情况修改),出现以下界面内容,说明 Spring MVC 已经配置成功:
其实也算不上什么整合,因为 Spring MVC 本身就属于 Spring 的一部分。这里的整合指的是将 Spring MVC 模块单独出来管理 Web 部分,其他部分由父容器 Spring 管理。至于为什么要分开管理,有很多理由,下面简单介绍一下:
既然要分开配置,就应该配置两个不同的 Spring 配置文件。新建文件 /WEB-INF/springContext.xml,添加以下内容:
<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:tx="http://www.springframework.org/schema/tx"
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.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.wjd">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
context:component-scan>
beans>
同时修改 springMVC.xml 文件如下:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
...
<context:component-scan base-package="com.wjd" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
context:component-scan>
...
beans>
注意:springContext.xml 和 springMVC.xml 这两个配置文件扫描注册的包是互相分开的,springMVC 仅扫描 @Controller 注解类,而其他的注解类由 springContext 来进行扫描注册,注意这两个扫描不要重叠了。
最后将 springContext.xml 文件配置信息添加到 web.xml 中,结果如下:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>/WEB-INF/springContext.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<servlet>
<servlet-name>dispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>/WEB-INF/springMVC.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>dispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
web-app>
到这里已经整合完成了,接下来对整合结果进行测试。由于 springMVC.xml 仅扫描注册了 @Controller 注解类,因此我们写个由 springContext.ml 扫描注册的 @Service 注解类来测试一下。
在 service 层写一个接口 TestService 接口,仅有 test() 方法,再写一个实现类 TestServiceImpl (记得添加 @Service 注解),代码如下:
package com.wjd.service;
import org.springframework.stereotype.Service;
@Service
public class TestServiceImpl implements TestService{
public String test() {
return "testSpv";
}
}
同时修改 controller 层的 TestController 类,内容如下:
package com.wjd.controller;
import com.wjd.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class TestSpv {
@Autowired
private TestService testService;
@RequestMapping(value = "test", method = RequestMethod.GET)
public String test(){
return "testSpv";
}
@RequestMapping(value = "serviceTest", method = RequestMethod.GET)
public String serviceTest(){
return testService.test();
}
}
最后重新部署项目,访问地址 http://localhost:8080/sspvh/serviceTest(注意: sspvh 是我配置的根路径,应该根据不同情况修改),界面显示如下则说明 Spring 和 Spring MVC 的配置正常:
Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,它将 POJO 与数据库表建立映射关系,是一个全自动的 orm 框架, hibernate 可以自动生成 SQL 语句,自动执行。
将 Hibernate 的配置信息写在 springContext.xml 中,最终文件内容如下:
<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:tx="http://www.springframework.org/schema/tx"
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.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.wjd">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
context:component-scan>
<bean id="propertyConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.propertiesvalue>
list>
property>
bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxPoolSize" value="40" />
<property name="minPoolSize" value="1" />
<property name="initialPoolSize" value="10" />
<property name="maxIdleTime" value="20" />
bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>com.wjdvalue>
list>
property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}prop>
props>
property>
bean>
<bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
bean>
<tx:annotation-driven transaction-manager="hibernateTransactionManager" />
beans>
注意一下 sessionFactory 中配置的 packagesToScan,Spring 会根据这个配置去扫描指定的包列表下的 @Entity 类,将其识别为实体类,然后 Hibernate 才能找到对应的实体对应关系,因此注意配置好 packagesToScan,否则 Hibernate 会提示找不到 Entity 类。
上述配置中用到的和数据库连接以及 Hibernate 相关的配置文件 jdbc.properties 内容如下:
# jdbc config
# jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssh?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
jdbc.username=root
jdbc.password=123456
# hibernate config
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.hbm2ddl.auto=update
该配置文件中需要注意的一点是数据库驱动 jdbc.driverClass,数据库版本不同时需要的驱动是不一样的。因为我用的数据库是 MYSQL 8.0.11,所以驱动类是 com.mysql.cj.jdbc.Driver,而 8 版本以前的(例如 MYSQL 5.5)应使用驱动类 com.mysql.jdbc.Driver。
到这里已经将 Hibernate 配置完成了,下面对这些配置进行一些测试,首先给出项目的结构:
实体类 Book:
package com.wjd.entity;
import javax.persistence.*;
@Entity
@Table(name = "book")
public class Book {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long bId;
private String name;
private Double price;
public Long getbId() {
return bId;
}
public void setbId(Long bId) {
this.bId = bId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}
Dao 层:
package com.wjd.dao;
import com.wjd.entity.Book;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public class BookDaoImpl implements BookDao {
@Autowired
private SessionFactory sessionFactory;
public boolean save(Book book) {
sessionFactory.getCurrentSession().save(book);
return true;
}
public List getBooks(){
List bookList = null;
String sql = "from Book";
Query query = sessionFactory.getCurrentSession().createQuery(sql);
bookList = query.list();
return bookList;
}
}
Service 层:
package com.wjd.service;
import com.wjd.dao.BookDao;
import com.wjd.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
@Transactional
public boolean save(Book book) {
return bookDao.save(book);
}
@Transactional
public List getBooks(){
return bookDao.getBooks();
}
}
Controller 层:
package com.wjd.controller;
import com.wjd.entity.Book;
import com.wjd.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@Controller
public class BookController {
@Autowired
private BookService bookService;
@RequestMapping(value = "save", method = RequestMethod.POST)
public String save(HttpServletRequest req, HttpServletResponse resp){
String name = req.getParameter("name");
Double price = Double.parseDouble(req.getParameter("price"));
Book book = new Book();
book.setName(name);
book.setPrice(price);
bookService.save(book);
return list(req, resp);
}
@RequestMapping(value = "list", method = RequestMethod.GET)
public String list(HttpServletRequest req, HttpServletResponse resp){
List bookList = bookService.getBooks();
req.setAttribute("listBooks", bookList);
return "book";
}
}
然后写个用于测试的界面 /WEB-INF/views/book.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<form action="save" method="post">
<fieldset style="width: 300px">
<legend>添加书籍legend>
<table>
<tr>
<td align="right" style="font-weight: bold">书名td>
<td><input type="text" name="name" value="" style="width: 200px">td>
tr>
<tr>
<td align="right" style="font-weight: bold">价格td>
<td><input type="text" name="price" value="" style="width: 200px">td>
tr>
<tr>
<td align="right" style="font-weight: bold">td>
<td><input type="submit" name="add" value="添加" style="width: 200px">td>
tr>
table>
fieldset>
form>
<c:if test="${!empty listBooks}">
<table border="1px solid #000000">
<tr>
<th width="80">Book IDth>
<th width="120">Book Nameth>
<th width="120">Book Priceth>
tr>
<c:forEach items="${listBooks}" var="book">
<tr>
<td>${book.bId}td>
<td>${book.name}td>
<td>${book.price}td>
tr>
c:forEach>
table>
c:if>
body>
html>
最后将项目部署到 Tomcat 中运行,在浏览器中访问地址 http://localhost:8080/sspvh/list(注意: sspvh 是我配置的根路径,应该根据不同情况修改),将出现以下内容(图中数据是我数据库中已经有的):
可以在此界面添加新的书籍,例如添加一本 C#,添加提交之后结果如下:
到此,已经将 Spring,Spring MVC 和 Hibernate 整合完成。
这次整合我遇到了几个问题:
整合参考:
https://www.cnblogs.com/xrog/p/6359706.html
https://www.journaldev.com/3531/spring-mvc-hibernate-mysql-integration-crud-example-tutorial
https://www.cnblogs.com/xuezhajun/p/7687230.htmlcomponent-scan 相关:
http://www.cnblogs.com/hafiz/p/5875770.html
http://www.cnblogs.com/hafiz/p/5875740.html
http://www.imooc.com/article/16155
http://www.imooc.com/article/6331
https://blog.csdn.net/chunqiuwei/article/details/16115135
https://blog.csdn.net/baidu_21780935/article/details/60959510
https://www.cnblogs.com/fightingcoding/p/component-scan.html
https://blog.csdn.net/pucao_cug/article/details/50359896packagesToScan 相关
https://blog.csdn.net/acmman/article/details/44652165
https://blog.csdn.net/mjl960108/article/details/53435050