SSH框架的搭建
ssh框架的组成:
一、Java Resources -----src目录下
1、 java四个包:
ssh.action : IndexAction (mvc/控制层。)
ssh.dao : IndexDao;IndexDaoImpl (数据库访问包,接口)
ssh.entity: BookCard,BookCard.hbm.xml (实体类,映射实体类)
ssh.service: IndexService, IndexServiceImpl (业务逻辑处理层,接口)
(ssh.untity:数据库连接包,已经被applicationContext 配置信息代替)
二、 xml 文件:src目录的xml文件5个:
2.1 applicationContext.xml:
引入外部属性(插入jdbc.properties,方便数据库信息变动的时候做出修改。),
不需要new对象,防止紧密耦合,直接由spring管理类, 注入数据库连接池,检查连接信息。
2.2 jdbc.properties:
数据库连接信息的文本内容,包含驱动(哪种数据库,url地址,数据库名,用户名和密码)
2.3 s001,s002,s003.xml:多人开发的时候,配置信息说明。
2.4 Struts.xml:管理s001,s002,s003.xml文件
三、WEB-INF 目录下:
3.1 jsp文件夹:index.jsp 显示数据库表信息,
error.jsp 和 s_tag.jsp :有错误信息的时候跳转 “温馨提示” :页面出错了,也许是xx原因。
要有错误信息的页面跳转,不然服务器停止了,客服打不开网页,出现一堆乱码,一些粗口的问候就来了。
/*
这里做补充:为什么jsp页面不放到WebContent的根目录,那样岂不是更好?
1、更好的分层,大型项目可不是只有2,3个网页啊!
2、加密,隐藏主页,在s001.xml配置信息文件中,/WEB-INF/jsp/index.jsp
index主页是隐藏起来的。你无法直接运行(报404错),只有运行default.jsp 重定向跳转 主页,才能打开。
细心的网友可以看看,百度,淘宝一些大型网页是没有后缀(.html, .jsp这些的都是被隐藏了起来。)
*/
3.2 lib文件夹:ssh框架和数据库驱动包存放(struts,spring,hibernate 的所有驱动包,这里挑选用的上的。)
3.3 web.xml : 配置struts 和spring 信息文件
3.4 WEB-INF:目录外,default.jsp: 用于加密,重定向跳转index.jsp 主页面。
四、struts ,spring,hibernate 驱动包的挑选:
1、系统分4层:表示层,业务逻辑层,数据持久层,域模块层。
2、struts:作为系统的整体基础架构,负责MVC的分离,控制业务跳转。
自动获取参数,自动进行类型转换,不需要写重定向跳转代码(sendRedirect)
2、spring:管理struts,hibernate;分析需求,实现DAO接口。
3、Hibernate:实现java类和数据库之间的转换和访问,
百度云盘地址:链接:http://pan.baidu.com/s/1cuY2MM 密码:3sub
版本:
4.1 struts-2.3.30 (77.7M):只需要解压
ssh包\struts-2.3.30-all.zip\struts-2.3.30\apps\ 下的 struts2-blank即可。
往eclipse导入 struts的lib包(struts2-blank项目中的lib包)
4.2 spring -framework-4.2.2 (63.8M)
libs目录下:
spring-aop-4.2.2RELLASE
一直到 spring-web-4.2.2.RELEASE-sources
后面webmvc暂时不要,中间排除:javadoc,sources后缀的jar包
不排除:RELLASE都要
SSH框架\struts2.3.30-showcase\WEB-INF\lib
这个目录找2个jar包:commons-logging-1.1.3 :这样就有4个commons包了
struts2-spring-plugin-2.3.30 :这个是struts连接spring的包。
4.3 hibernate -release -5.2.2 (71.6M)
打包:lib\required 所有包(15个)
这里还有一个xml文件可以抓取出来用:
project\hibernate-core\src\test\resources下的 连接配置信息包:
1、连接的配置信息 hibernate.cfg.xml (cfg-->>config)
2、映射信息:(实体类) XXXX.hbm.xml
3、
E:\SSH框架\hibernate-release-5.2.2.Final\project\hibernate-ehcache\src\test\resources\hibernate-config
这个文件:hibernate.cfg.xml,在原来的基础上修改一下。后面具体讲。
三个版本都有最新版,但是不稳定,现在小编我只用稳定的旧版(每个版本的使用方法都不太一样。)
其他包:dbcp2个包(数据库连接池):这个用myeclipse应该自带,ssh框架没有,不过我网盘也上传了。
commons-pool,commons-dbcp
五、代码显示:以下写一个《图书馆信息管理系统》
5.1 数据库代码
数据库:Mysql ;数据库名:Library ;表名:Stack;
(温馨提示:mysql中,数据库名和表名这些都默认小写,例如:create Library; 但是创建的还是小写:library)
mysql 一些数据类型和写法 与sql 不同,初学者要先分清楚。
--创建数据库
create database library;
--创建表
use library;
create table Stack(
cid int auto_increment,
title varchar(50), --书名
writer varchar(30),--作者
bookdate datetime,--出版日期
price decimal(10,2),--价格
primary key(cid) --设置主键和 cid的自动增长,从1001开始
)AUTO_INCREMENT=1001;
--多行插入数据
insert into Stack(cid,title,writer,bookdate,price) values
('1001','《临界爵迹》','郭敬明','2011-1-1',19),
('1002','《斗罗大陆3》','唐家三少','2016-1-18',18),
('1003','《小说绘》','湖北知音传媒','2009-9-1',10);
5.2
-------- ssh.action : IndexAction (mvc控制层)
public class IndexAction extends ActionSupport {
//声明service,但不给它创建具体的实现类的实例,
private IndexService is = null;
public void setIs(IndexService is) {
this.is = is;
}
public String execute1() {
List<BookCard> myBookCardList = is.getAllBookCard();
System.out.println("结果集:"+myBookCardList.size());
ActionContext ac = ActionContext.getContext();
ac.put("myBookCardList", myBookCardList);
return "success";
}
public String formatDouble(double s){
DecimalFormat fmat=new DecimalFormat("\u00A4##.0"); // 是个给导出的《图书表》价格这列,前面增加 $符号
return fmat.format(s);
}
}
5.3
---------dao包:访问数据库 IndexDao
import java.util.List;
import ssh.entity.BookCard;
public interface IndexDao {
public List<BookCard> getAllBookCard();
}
------------IndexDaoImple 接口
public class IndexDaoImpl implements IndexDao {
//在SSH的设计理念:要使用某个实例,那么就定义声明一个对象,然后
//给它添加set方法(用于spring注入进来),实现不要关注这个实例
//来自于那里,以及怎么创建,或者它是谁
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf) {
this.sessionFactory = sf;
}
@Override
public List<BookCard> getAllBookCard() {
//sessionFactory这个实例可以自己按常规的hibernate传统写法创建
//也可以交给spring去托管
//sessionFactory = new Configuration().configurebuildSessionFactory();
Session session = sessionFactory.openSession();
System.out.println("sessionFactory:"+sessionFactory);
System.out.println("session:"+session);
//后面当使用JPA的时候,EntityManager 类似于 SessionQuery query = session.createQuery("from BookCard");
//System.out.println("query:"+query);
//这2行代码,会交给spring的AOP帮忙处理
List<BookCard> list = query.getResultList();
return list;
}
}
5.4
-----------------entity实体类:
public class BookCard {
private int cid ;
private String name;
private String sex ;
private Date cardDate;
private Double deposit;
------------------------------- BookCard.hbm.xml映射实体类数据
<!--name: 实体类的包名+类名 table:对应数据库表名 定义主键 mane:实体类的属性 column:数据库的列名 --->
<?xml version="1.0" encoding="UTF-8"?>
<hibernate-mapping xmlns="http://www.hibernate.org/xsd/hibernate-mapping">
<class name="ssh.entity.BookCard" table="BookCard">
<id name="cid" column="cid">
<generator class="native"></generator>
</id>
<property name="name" type="string" length="50" column="name" not-null="true"></property>
<property name="sex" type="string" length="2" column="sex"></property>
<property name="cardDate" type="date" column="cardDate"></property>
<property name="deposit" type="double" column="deposit"></property>
</class>
</hibernate-mapping>
IndexService;
public interface IndexService {
public List<BookCard> getAllBookCard();
public void setId(IndexDao id);
}
-----------IndexServiceImpl 业务逻辑处理层接口
public class IndexServiceImpl implements IndexService {
//dao实例使用注入方式
//??为什么要让Dao为空的?
//答:new 实现类的代码不见了,这样本类就不用关注具体的实现类是谁</span>
private IndexDao id;
//用于注入使用
public void setId(IndexDao id) {
System.out.println("有人给我注入了一个dao实例:"+id);
this.id = id;
}
@Override
public List<BookCard> getAllBookCard() {
<span style="color:#3366ff;">//本类应该编写业务逻辑的代码,
//但本例没有业务逻辑,就不用写。
//访问数据库的代码,不会出现在service这一层
//交给dao来操作数据库</span>
List<BookCard> myBookCardList = id.getAllBookCard();
//进行其它的业务逻辑操作,比如增加多一个选项,是否过期
//本例不需要
//....
return myBookCardList;
}
}
5.6
-------------------applicationContext.xml
引入外部属性(插入jdbc.properties,方便数据库信息变动的时候做出修改。),
不需要new对象,防止紧密耦合,直接由spring管理类, 注入数据库连接池,检查连接信息。
<?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">
<!-- 引入外部属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 类似于财务部门一样,类就是钱,所有需要类的实例都由spring去管理 -->
<bean id="myIndexAction" class="ssh.action.IndexAction" scope="prototype">
<!-- setIs(myIndexService) -->
<property name="is" ref="myIndexService"/>
</bean>
<!-- myIndexService = new ssh.service.IndexServiceImpl() -->
<bean id="myIndexService" class="ssh.service.IndexServiceImpl" scope="prototype">
<property name="id" ref="myIndexDao"/>
</bean>
<bean id="myIndexDao" class="ssh.dao.IndexDaoImpl" scope="prototype">
<span style="color:#3366ff;"><!-- 晚点再注入能用的seesionFactory --></span>
<property name="sessionFactory" ref="mySessionFactory"></property>
</bean>
<!--
错误的做法,new org.hibernate.internal.SessionFactoryImpl()
不可以,需要configuration来创建
bean id="mySessionFactory" class="org.hibernate.internal.SessionFactoryImpl"></bean
-->
<bean id="mySessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!-- 注入连接池,包含了数据库用户名,密码等等信息 -->
<property name="dataSource" ref="myDataSource"/>
<!-- 配置Hibernate的其他的属性 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> <span style="font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace; line-height: 21.6px; white-space: nowrap;"><span style="color:#3366ff;"><!-- 配置数据库驱动,这里使用mysql --></span></span>
<prop key="hibernate.show_sql">true</prop><span style="color:#3366ff;"> <!-- 显示数据库信息 --></span>
<prop key="hibernate.format_sql">true</prop> <span style="color:#3366ff;"><!-- 格式化数据库信息 --></span>
<prop key="hibernate.connection.autocommit">false</prop><span style="color:#3366ff;"> <!-- 自动提交数据库信息-off --></span>
<span style="color:#3366ff;"><!-- 开机自动生成表信息 --></span>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>ssh/entity/BookCard.hbm.xml</value>
</list>
</property>
</bean>
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
<span style="color:#3366ff;"><!-- 每300秒检查所有连接池中的空闲连接 --></span>
<property name="idleConnectionTestPeriod" value="300"></property>
<span style="color:#3366ff;"><!-- 最大空闲时间,900秒内未使用则连接被丢弃。若为0则永不丢弃 --></span>
<property name="maxIdleTime" value="900"></property>
<span style="color:#3366ff;"><!-- 最大连接数 --></span>
<property name="maxPoolSize" value="2"></property>
</bean>
</beans>
5.7
jdbc.properties
(数据库连接信息的文本,和applicationContext分开是方便数据库变动后的修改)
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/carddb
jdbc.user=root
jdbc.password=
5.8
s001.xml;
<?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">
<span style="color:#3366ff;"><!-- 上面的头,注意版本,从样例里复制过来 showcase.war\WEB-INF\src\java\struts.xml -->
</span>
<struts>
<!-- 第1步:先定义一个包 --></span>
<package name="mypck001" extends="struts-default">
<!-- 第2步:定义一个action,配置跳转信息 name 类似于Servlet @WebServlet("/IndexServlet")
设计思想:关心了具体的实现类 ,必须改为不要关注那个实现类
加入spring后,struts的action节点的class属性意义发生变化,
直接引用spring帮忙创建的实例 --></span>
<action name="Index" class="myIndexAction" method="execute1">
<!-- 跳转是forward/WEB-INF/是防止jsp不经过action就可以访问-->
<result name="success">/WEB-INF/jsp/index2.jsp</result>
<result name="error">/WEB-INF/jsp/s_tag.jsp</result>
</action>
</package>
</struts>
----------------s002.xml ; s003.xml
<?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">
<!-- 上面的头,注意版本,从样例里复制过来 showcase.war\WEB-INF\src\java\struts.xml -->
<struts>
<package name="mypck002" extends="struts-default">
<!—s003.xml在这里修改一个数字即可 -->
</package>
</struts>
------------struts.xml 管理s001,002,003.xml信息
<?xmlversion="1.0" encoding="UTF-8" ?>
<!DOCTYPEstruts PUBLIC "-//Apache Software Foundation//DTDStruts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<!-- 上面的头,注意版本,从样例里复制过来 showcase.war\WEB-INF\src\java\struts.xml -->
<!-- include文件用于分割,实现多人并发不冲突 -->
<!-- 告知Struts2运行时使用Spring来创建对象 -->
<constantname="struts.objectFactory" value="spring" />
<include file="s001.xml"/>
<include file="s002.xml"/>
<include file="s003.xml"/>
</constantname>
5.9
jSP: index.jsp 主页,建表显示数据库表信息
头文件:</span>
<%@ taglib uri="/struts-tags" prefix="s" %>
<table border="1">
<tr>
<td>全选</td>
<td>序号</td>
<td>卡号</td>
<td>姓名</td>
<td>性别</td>
<td>办卡日期</td>
<td>押金</td>
</tr>
<s:iterator value="#myBookCardList" status="bcs">
<tr>
<td></td>
<td><s:property value="#bcs.count" /></td> <span style="color:#3366ff;"> <!-- count:计算 -->
<td><s:property value="cid"></s:property></td>
<td><s:property value="name"></s:property></td>
<td><s:property value="sex"></s:property></td>
<td><s:date name="cardDate" format="yyyy年MM月dd日"> <!-- 注意日期格式不要写错了 -->
</s:date></td>
<td><s:property value="%{formatDouble(deposit)}"> <!-- 价格 -->
</s:property></td>
</tr>
</s:iterator>
<s:if test="myBookCardList.size()==0">
<tr>
<td colspan="7">没有查找到数据</td>
</tr>
</s:if>
</table>
-----------error.jsp 错误页面
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
我是错误页面
<c:out value="${id}"></c:out>
5.10
------------web.xml 这里默认default.jsp 为主页,其实default 不是主页,只是重定向跳转 主页。(重定向在一些杀毒软件中会有警告提示。)
<?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_001</display-name>
<welcome-file-list>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<!-- struts2过滤器的配置:struts就像一条看门犬,有客户访问就释放资源 -->
<filter>
<filter-name>struts2</filter-name> <!-- 下面这句代码略长,是struts的目录的包 -->
<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监视器的配置: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>
5.11
---------default.jsp (用于重定向跳转主页,隐藏主页。)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%><%
response.sendRedirect("Index.action"); <!-- sendRedirect:重定向跳转主页Index -->
%>