SSH它不是一个框架而是由 struts+spring+hibernate组成的的一个集成框架,也是目前较流行的一种Web应用程序开源框架。
成SSH框架的系统主要分为四层:表示层、业务逻辑层、数据持久层和域模块层,以帮助开发人员在短期内搭建结构清晰、可复用性好、维护方便的Web应用程序。
在搭建SSH框架之前,我前几天发表的博客就已经对SSH(Struts2,Spring,Hibernate)的三大框架都进行了说明,在这里就不详细的介绍SSH一些概念性的东西了。
接下来,简单的介绍一下JPA吧!
JPA全称(Java Persistence API.JPA)通过注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。(本例是通过XML来描述对象-关系表的映射关系)
JPA的宗旨是为POJO提供持久化标准的一套规范。
1.1.JPA提供的技术
(1)ORM映射元数据 JPA支持XML和JDK 5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持 久化到数据库表中;
(2)JPA 的API用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解 脱出来。
(3)查询语言
通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
2.JPA的文件结构
如上图,我们需要建立一个POJO类,通过映射文件创建对应的表。把我们的配置信息存放在META-INF/persistence.xml文件中,注意目录META-INF跟persistence.xml名字都是固定的,都不能更改为别的名字。(persistence .xml必须放在classpath(也就是src目录下)路径下的META-INF文件夹中)。
导包什么的,在之前的文章都已经讲解过了(把之前文章的jar包综合一下就可以了),在这边就不发jar包的截图了。
本项目的搭建环境:
Windows 7-64位,Eclipse(开发工具),jdk1.8.0_91,Tomcat 8.0,struts-2.3.30-apps,spring-framework-4.2.2.RELEASE,hibernate-release-5.2.2.Final,sql sever2008.
现在开始搭建一个完整的SSH框架项目
在我们搭建项目前,需要在我们WebContent/WEB-INF/lib目录下导入我们三大框架(Struts2,Spring,Hibernate)的依赖包(jar包)
(1.导入Struts2的jar包(在这边我们下载的是Struts2-2.3.30版本的war包)导包步骤如下图:
a.需要在我们war包路径下找到我们的jar包
(2. 导入Spring的jar的包(spring-framework-4.2.2.RELEASE版本的war包)
a. 解压war包
b.在D:\SSH\spring-framework-4.2.2.RELEASE\libs路径下找到我们的jar包
(c.因为上图没有显示所有Spring要导进lib的包,下图补上:
(2. 导入Hibernate的jar包(hibernate-release-5.2.2.Final版本的war包)
注意:hibernate跟c3p0的jar包都是在D:\SSH\hibernate-release-5.2.2.Final\lib lib的路径下
(a.解压war包
(b.在D:\SSH\hibernate-release-5.2.2.Final\lib\required路径下找到我们的jar包
(c.连接数据库还需要在D:\SSH\hibernate-release-5.2.2.Final\lib\optional\c3p0目录下导入c3p0的jar包
第一招:导完包后就需要配置我们的web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>SSH</display-name>
<welcome-file-list>
<welcome-file>index.action</welcome-file>
</welcome-file-list>
<!-- Struts2过滤器的配置 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- spring监听器配置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
第二招:在src目录下创建四个包(package)进行分层。
第三招:根据数据库表的字段编写BookJava(实体类)和BookJava.hbm.xml(映射文件)放到java_entity包里。
分解一:实体类(BookJava)
package java_entity;
import java.math.BigDecimal;
import java.sql.Date;
public class BookJava {
private int cid;
private String name;
private Date BookDate;
private BigDecimal deposit;
public BookJava() {
super();
}
public BookJava(int cid, String name, Date bookDate, BigDecimal deposit) {
super();
this.cid = cid;
this.name = name;
BookDate = bookDate;
this.deposit = deposit;
}
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBookDate() {
return BookDate;
}
public void setBookDate(Date bookDate) {
BookDate = bookDate;
}
public BigDecimal getDeposit() {
return deposit;
}
public void setDeposit(BigDecimal deposit) {
this.deposit = deposit;
}
}
分解二:映射文件(BookJava.hbm.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2016-8-30 10:28:51 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<!-- 实体类class和数据库表table的映射 table写的是表名-->
<class name="java_entity.BookJava" table="bookJava">
<!-- id元素对应了表中的主键,持久化生成一个对象标识符来建立内存中的对象和数据表中的对应关系 -->
<id name="cid" type="int">
<column name="cid"></column>
<generator class="increment"></generator>
</id>
<!-- 普通属性的映射
name 表示类中的属性名称;type 表示表中数据的类型;column 表示表中的列名称-->
<property name="name" type="java.lang.String">
<column name="name"></column>
</property>
<property name="BookDate" type="java.sql.Date">
<column name="BookDate"></column>
</property>
<property name="deposit" type="java.math.BigDecimal">
<column name="deposit"></column>
</property>
</class>
</hibernate-mapping>
第四招:在java_service包里编写JavaService(接口类)和JavaServiceImpl(实现类)。
分解一:接口类(JavaService)
package java_service;
import java.util.List;
import java_entity.BookJava;
//创建JavaService(接口类)
public interface JavaService {
public List<BookJava> getAllJavaBook();
}
分解二:实现类(JavaServiceImpl)
package java_service;
import java.util.List;
import java_dao.JavaBookDao;
import java_entity.BookJava;
//业务逻辑层
public class JavaServiceImpl implements JavaService {
//注入(spring)dao包里实现类的实例
private JavaBookDao jd;
public void setJd(JavaBookDao jd) {
System.out.println("注入dao的实例"+jd);
this.jd = jd;
}
public List<BookJava> getAllJavaBook() {
List<BookJava> JavaBook=jd.getAllJavaBookDao();
return JavaBook;
}
}
第五招:在java_action包编写javaBookAction类。
package java_action;
import java.text.DecimalFormat;
import java.util.List;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import java_entity.BookJava;
import java_service.JavaService;
public class JavaBookAction extends ActionSupport {
//注入service实例
private JavaService jsi;
public void setJsi(JavaService jsi) {
this.jsi = jsi;
}
public String execute(){
List<BookJava> javaList=jsi.getAllJavaBook();
System.out.println("结果集:"+javaList.size());
ActionContext ac=ActionContext.getContext();
ac.put("javaList",javaList);
return SUCCESS;
}
//输出人民币符号
public String formatDouble(double s){
DecimalFormat df=new DecimalFormat("\u00A4##.0");
return df.format(s);
}
}
第五招:struts配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 将所有的实现类都交给spring托管 -->
<constant name="struts.objectFactory" value="spring"></constant>
<package name="javaPackage" extends="struts-default" namespace="/">
<action name="index" class="javaBookAction" method="execute">
<result name="success">/WEB-INF/jsp/javaIndex.jsp</result>
</action>
</package>
</struts>
第六招:applicationContext配置文件
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
<bean id="javaBookAction" class="java_action.JavaBookAction" scope="prototype">
<property name="jsi" ref="javaService"></property>
</bean>
<bean id="javaService" class="java_service.JavaServiceImpl" scope="prototype">
<property name="jd" ref="javaBookdaoImpl"></property>
</bean>
<bean id="javaBookdaoImpl" class="java_dao.JavaBookDaoImpl" scope="prototype">
<!-- JPA是Hibernate跟mybatis公用的接口,所以JPA就拥有独立的EntityManagerFactory实例-->
<!-- 给javaBookdaoImpl注入 EntityManagerFactory实例-->
<property name="emf" ref="EntityManagerFactory"></property>
</bean>
<bean id="EntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="myjpa"></property>
</bean>
</beans>
第七招:JPA的配置文件(persistence.xml)
注意:(1)目录META-INF跟persistence.xml名字都是固定的,都不能更改为别的名字。
(2)persistence .xml必须放在classpath(也就是src目录下)路径下的META-INF文件夹中。
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sum.com/xml/ns/presistence/persistence_2_0.xsd">
<!-- Name属性用于定义持久化单元的名字 (name必选,空值也合法);transaction-type 指定事务类型(可选) -->
<persistence-unit name="myjpa" transaction-type="RESOURCE_LOCAL">
<!-- hibernate驱动的实现类,入口类 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!-- 导入映射文件的路径-->
<mapping-file>java_entity/BookJava.hbm.xml</mapping-file>
<properties>
<!-- 数据库加载的驱动 -->
<property name="hibernate.connection.driver_class" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<!-- 数据库url地址 -->
<property name="hibernate.connection.url" value="jdbc:sqlserver://localhost:1433;DatabaseName=SSH"/>
<!-- 数据库登录名 -->
<property name="hibernate.connection.user" value="sa"/>
<!-- 数据库登录密码 -->
<property name="hibernate.connection.password" value="123"/>
<!-- 在控制台显示sql语句(值为true则为显示,为false则不显示) -->
<property name="hibernate.show_sql" value="true"></property>
<!-- 设置值为update会自动判断表是否存在,若表存在时则更新表,表不存在时则新建表 -->
<property name="hibernate.hbm2ddl.auto" value="update"></property>
</properties>
</persistence-unit>
</persistence>
第八招:创建一个javaiIndex.jsp页面将所有数据取出来显示到页面上。
注意:用Struts2标签必须在jsp页面添加如下定义:
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!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>
<table border="1px">
<tr>
<th>编号</th>
<th>书名</th>
<th>出版日期</th>
<th>课本价格</th>
</tr>
<s:iterator value="javaList">
<tr>
<td><s:property value="cid"/></td>
<td><s:property value="name"/></td>
<td><s:date name="BookDate" format="yyyy-MM-dd"></s:date></td>
<td><s:property value="%{formatDouble(deposit)}" /></td>
</tr>
</s:iterator>
<s:if test="javaList.size()==0">
<tr>
<td colspan="7">没有查找到数据</td>
</tr>
</s:if>
</table>
</body>
</html>
最后输出结果:
总结:ssh框架最主要的本质是:“高内聚、低耦合”。在ssh中使用Struts是作为系统的整体基础架构,主要负责MVC的分离,在Struts框架的模型部分,控制业务跳转,利用Hibernate框架对持久层提供支持,Spring做管理层,管理struts和hibernate。具体做法是:用面向对象的分析方法根据需求提出一些模型,将这些模型实现为基本的Java对象,然后编写基本的DAO(Data Access Objects)接口,并给出Hibernate的DAO实现,采用Hibernate架构实现的DAO类来实现Java类与数据库之间的转换和访问,最后由Spring做管理,管理struts和hibernate。
JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。