@记录自己的学习之旅(SSH框架篇)
SSH框架
SSH是一个集成框架,主要有三个基础框架整合而成,也就是我们常说的Spring+Struts+Hibernate。
通过SSH框架,我们可以将系统分为表示层,业务层和数据持久层。其中Struts作为SSH的一个基础框架,起到MVC分层架构的作用,Hibernate则是我们与数据进行交互的一条通道,为持久层提供支持,Spring则是担任一个管理者的角色。
如何搭建一个SSH框架
SSH整合 | 整合步骤 |
利用Spring整合Hibernate | 导包 |
配置applicationContext.xml | |
创建实体类和映射关系文件 | |
创建DAO接口及实现类 | |
声明DAO组件,注入SessionFactory | |
利用Spring整合Struts2 | 导包 |
配置web.xml | |
配置applicationContext.xml | |
创建并声明Action | |
配置Action,创建JSP |
一、Spring整合Hibernate
1、导包
创建一个WEB项目SSH_Day01,并导入数据库驱动包,Hibernate开发包以及Spring开发包。我这边直接从官网下的Hibernate和Spring的开发包,导入了里面的jar包,同时导入对应数据的驱动包和测试需要使用的jar包。
2、配置applicationContext.xml
在Java Resorces目录下我们建立一个resouce目录存放对应的配置文件。
2.1 配置数据源
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:dbconfig.properties" />
<!-- 配置数据源 -->
<bean id="ds" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<!-- 配置连接参数 -->
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- 配置连接池 -->
<property name="initialPoolSize" value="3"/>
<property name="maxPoolSize" value="10"/>
<property name="minPoolSize" value="1"/>
<!-- acquireIncrement:当连接池中的连接用完时,C3P0一次性创建新连接的数目 -->
<property name="acquireIncrement" value="3"/>
<!-- maxIdleTime:最大空闲时间,超过空闲时间的连接将被丢弃。为0或负数则永不丢弃。默认为0; -->
<property name="maxIdleTime" value="60"/>
</bean>
我这里用的是Oracle的数据库,对应的连接配置文件如下:
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:orcl
jdbc.username=zyq
jdbc.password=1234
2.2 配置SessionFactory
<!-- 配置SessionFactory -->
<bean id = "SessionFactory" class = "org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- 依赖数据源 -->
<property name="dataSource" ref= "ds"/>
<!-- Hibernate框架相关配置 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.OracleDialect
</prop>
<!-- 在控制台输出sql -->
<prop key="hibernate.show_sql">true</prop>
<!-- 将sql格式化,然后再输出 -->
<prop key="hibernate.formate_sql">true</prop>
</props>
</property>
</bean>
这边dialect就是“方言”,因为hibernate是要把Java对象转换成关系数据库来描述的,而关系数据库虽然有一些统一的标准,但是各个数据库之间还是有不同的地方,我们用这种方式将它里面将不同数据类型、SQL语法转换成hibernate能理解的统一的格式。
2.3 配置注解扫描和事务管理
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.*"/>
<!-- 声明式事务管理,采用AOP形式切入 -->
<bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory"/>
</bean>
<!-- 通知 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- 传播行为 -->
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
<tx:method name="select*" propagation="SUPPORTS" read-only="true" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 切面 -->
<aop:config>
<aop:advisor advice-ref="txAdvice"
pointcut="within(com.*.*)" />
</aop:config>
3 创建实体类和映射关系文件
3.1 创建实体类
在src目录下,新建一个entity包用于存放我们的实体类,这里我创建了一个User类,这个大家可以随便建立。
对应的User类代码如下
package com.entity;
public class User {
private Integer id;
private String card;
private String username;
private String password;
private String company;
private Integer age;
private Integer sex;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCard() {
return card;
}
public void setCard(String card) {
this.card = card;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username == null ? null : username.trim();
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password == null ? null : password.trim();
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company == null ? null : company.trim();
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
}
3.2 创建映射关系文件
一般每个实体类都有自己的映射文件,并使用XXX.hbm.xml的形式来命名,“XXX”既是持久化类名,并且持久化类与其映射文件放在同一目录下。这里我建立了User.hbm.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.entity.User" table="user_test">
<id name="id" type="integer" column="id">
<!-- 用来指明主键的生成方式 -->
<generator class="sequence">
<param name="sequence">seq_user_test</param>
</generator>
</id>
<property name="card" type="string" column ="usr_id"/>
<property name="username" type="string" column ="usr_nam"/>
<property name="password" type="string" column ="pwd"/>
<property name="company" type="string" column ="company"/>
<property name="age" type="integer" column ="age"/>
<property name="sex" type="integer" column ="sex"/>
</class>
</hibernate-mapping>
这里hibernate-mapping是XXX.hbm.xml配置文件的根节点;
class中属性含义
name :实体类名,默认要写类全名,若配置了hibernate-mapping节点的package属性则可以只写类名。
table :此实体类对应的数据库表名。
id中属性含义
name :实体类属性名,用做数据库表主键的成员变量。
type :数据库字段类型。
column :数据库主键字段。
generator中属性含义
class :用于指定主键的生成方式
sequence:适用于代理主键,Hibernate根据底层数据库的序列来生成标识符。这里用的序列是在对应数据库里建立的。
property中属性含义
name :实体类属性名。
type :数据库字段类型。
column :数据库对应字段。
3.3 在配置文件中注册映射关系文件
<!-- 配置SessionFactory -->
<bean id = "SessionFactory" class = "org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- 依赖数据源 -->
<property name="dataSource" ref= "ds"/>
<!-- Hibernate框架相关配置 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.OracleDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.formate_sql">true</prop>
</props>
</property>
<!-- 注册映射文件 -->
<property name="mappingResources">
<list>
<value>com/entity/User.hbm.xml</value>
</list>
</property>
</bean>
4、创建DAO接口及实现类
创建包com.dao,在包里新建一个UserDao接口,声明增删改查的方法。
package com.dao;
import java.util.List;
import com.entity.User;
/**
*
* @author Mr.ZOU
* 实现对User表的增删改查的接口
*/
public interface UserDao {
//查找所有数据
List<User> findAll();
//根据id查询单条记录
User findById(Integer id);
//保存
void save(User user);
//更新
void update(User user);
//删除
void delete(Integer id);
}
接着新建一个实现类UserDaoImpl来继承HibernateDaoSupport,实现接口UserDao。
package com.dao;
import java.util.List;
import javax.annotation.Resource;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;
import com.entity.User;
@Repository
public class UserDaoImpl extends HibernateDaoSupport implements UserDao{
@Resource
public void setSf(SessionFactory sf) {
super.setSessionFactory(sf);
}
@Override
public List<User> findAll() {
String hql = "from User";
return (List<User>) getHibernateTemplate().find(hql);
}
@Override
public User findById(Integer id) {
return getHibernateTemplate().get(User.class, id);
}
@Override
public void save(User user) {
getHibernateTemplate().save(user);
}
@Override
public void update(User user) {
getHibernateTemplate().update(user);
}
@Override
public void delete(Integer id) {
User user = new User();
user.setId(id);
getHibernateTemplate().delete(user);
}
}
5、测试
在com.dao目录下新建TestDao测试类。具体代码如下:
package com.dao;
import java.util.List;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.annotation.Transactional;
import com.entity.User;
public class TestDao {
private String conf="applicationContext.xml";
@Test
/**
* 测试查询功能
*/
public void test1() {
ApplicationContext ctx = new ClassPathXmlApplicationContext(conf);
UserDao dao = (UserDao) ctx.getBean("userDaoImpl");
List<User> list= dao.findAll();
for(User user : list) {
System.out.println(user.getCard()+" "+user.getUsername());
}
}
@Test
/**
* 测试查询功能
*/
public void test2() {
ApplicationContext ctx = new ClassPathXmlApplicationContext(conf);
UserDao dao = (UserDao) ctx.getBean("userDaoImpl");
User user= dao.findById(3);
System.out.println(user.getCard()+" "+user.getUsername());
}
@Test
/**
* 测试保存功能
*/
@Transactional
public void test3() {
ApplicationContext ctx = new ClassPathXmlApplicationContext(conf);
UserDao dao = (UserDao) ctx.getBean("userDaoImpl");
User user= new User();
user.setCard("174258");
user.setUsername("王五");
user.setPassword("174258");
user.setCompany("JIALIDUN UNIVERSITY");
user.setAge(23);
user.setSex(2);
dao.save(user);
test1();
}
@Test
/**
* 测试更新功能
*/
@Transactional
public void test4() {
ApplicationContext ctx = new ClassPathXmlApplicationContext(conf);
UserDao dao = (UserDao) ctx.getBean("userDaoImpl");
User user= dao.findById(3);
user.setSex(2);
dao.update(user);
}
@Test
/**
* 测试删除功能
*/
@Transactional
public void test5() {
ApplicationContext ctx = new ClassPathXmlApplicationContext(conf);
UserDao dao = (UserDao) ctx.getBean("userDaoImpl");
dao.delete(10);
}
}
二、Spring整合Struts
1、导包
导入Struts2开发包,Spring开发包以及Spring整合Struts2开发包。不同版本之间可能会有冲突,我在开始也遇到了jar包问题,后来用的Spring版本是4.3.20,Struts2用的是2.5.20。
2、配置web.xml
主要是进行容器启动时加载Spring和Struts2前端控制器,具体代码如下:
<?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_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>SSH_Day01</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 配置listener,在容器启动时自动加载Spring -->
<listener>
<!-- ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext.xml的配置信息。
因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,
启动容器时,就会默认执行它实现的方法。
ContextLoaderListener通过一个ContextLoader对象来初始化Spring容器-->
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--配置Struts2前端控制器 -->
<filter>
<filter-name>struts</filter-name>
<filter-class>
org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
3、创建Action
建立包com.action,在包下建立FindUserAction类,在这个Action的业务方法中,调用UserDao查询方法查出结果显示在页面上。需要使用Spring注解声明这个Action组件,另外也需要通过注解将DAO注入。
代码如下所示:
package com.action;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import com.dao.UserDao;
import com.entity.User;
@Controller
@Scope("prototype")
public class FindUserAction {
@Resource
private UserDao userDao;
private List<User> users;
public String load() {
setUsers(userDao.findAll());
return "success";
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
4、配置struts.xml
在src根目录下建立struts.xml,代码如下所示。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!-- package提供了将多个Action组织为一个模块的方式
package的名字必须是唯一的
name:package名称
extends:继承的父package名称
namespace:定义package命名空间 该命名空间影响到url的地址,例如此命名空间为/user
地址为http://localhost:8080/SSH_Day01/user/findUser
result里配置了跳转到的页面
-->
<package name="user" namespace="/user" extends="struts-default">
<action name="findUser" class="findUserAction" method = "load">
<result name="success">
/WEB-INF/jsp/user.jsp
</result>
</action>
</package>
</struts>
4、配置对应的jsp文件
在WebContent目录下建一个index.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">
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>查询用户</title>
</head>
<body>
<a href="<%=path%>/user/findUser"> 查询所有用户 </a>
</body>
</html>
在WEB-INF目录下新建一个包jsp存放我们的jsp文,建立user.jsp,具体代码如下:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@page import="com.entity.*"%>
<%@page import="java.util.List"%>
<!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>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<base href="<%=basePath%>"></base>
<style type="text/css">
.td td{
width: 100px;
}
.table{
text-align: center;
margin: 0 auto;
}
</style>
</head>
<body>
<%
List list = ((List<User>)request.getAttribute("users"));
%>
<table class="table">
<tr class="td">
<td>ID</td>
<td>用户名</td>
<td>密码</td>
<td style="width: 200px">公司</td>
<td>年龄</td>
<td>性别</td>
</tr>
<%for ( int i=0 ; i<list.size(); i++ ){%>
<% User user = (User)list.get(i);%>
<% if( user !=null){%>
<tr class="td">
<td><%=user.getId()%></td>
<td><%=user.getUsername()%></td>
<td><%=user.getPassword()%></td>
<td><%=user.getCompany()%></td>
<td><%=user.getAge()%></td>
<td><%=user.getSex()==1?"男":"女"%></td>
</tr>
<%}else{ %>
<tr class="td">
<td style="color: red;">暂无相关数据</td>
</tr>
<%} }%>
</table>
</body>
</head>
</html>
三、启动项目测试
配置完毕后,我们可以利用Tomcat进行测试。
四、感想
在做的途中也遇到很多问题,但感觉主要的还是jar包之间的问题,通过百度也都解决了,祝愿各位小伙伴在学习途中也都能解决各自的问题。
项目地址:https://gitee.com/ggpig/SSH_Day01