SSH的初步使用
首先创建maven项目,我用的是IDEA—2018.
在pom.xml中导入依赖关系:<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <spring.version>5.0.8.RELEASE</spring.version> <struts.version>2.5.14</struts.version> <hibernate.version>5.3.6.Final</hibernate.version> </properties>
在上面的properties中配置struts,spring,hibernate的版本,下面的${struts.version}等取就可以,这样使得版本一致,就避免了版本不一致带来的问题(之前项目就出现,解决了好久)。
<dependencies>
<!-- javaee环境所需的炸包start -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_2.5_spec</artifactId>
<version>1.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<!-- 加上这个provided属性,代表不部署,只是开发用 -->
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
<!-- 排除添加依赖 -->
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jstl-impl</artifactId>
<version>1.2</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- javaee环境所需的炸包end -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>${struts.version}</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>${struts.version}</version>
</dependency>
<!-- 导入spring包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 使用druid连接池的数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
</dependencies>
步骤分析
1.容器运行时加载web.xml文件
> 这是struts2的核心过滤器配置
<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
</filter-class>
<!--<init-param>默认加载的是struts.xml文件,下面代码是自定义它的位置
<param-name>config</param-name>
<param-value>struts-default.xml,configs/struts/bigpig.xml</param-value>
</init-param>-->
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
> 这是Spring的配置文件,默认进入applicationContext.xml中,如下可以自定义
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext.xm
l的配置信息 。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,
启动容器时,就会默认执行它实现的方法。-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<welcome-file-list>
<welcome-file>/addClazz.jsp</welcome-file>
</welcome-file-list>
2.struts中的配置:
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<!-- 需要产生action时默认找 struts.objectFactory,
此处找名字叫“spring“的Factory-->
<constant name="struts.objectFactory" value="spring">
</constant>
<package namespace="/" name="sys" extends="struts-default">
<global-allowed-methods>regex:.*</global-allowed-methods>
<action name="clazz" class="com.seecen.myssh.action.ClazzAction">
<result>/Myindex.jsp</result>
</action>
</package>
3.spring的applicationContext.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 读取properties配置文件 -->
## 这里配置了jdbc的beans可以把jdbc的驱动等分离出去,就是下面的DataSource中property可以用jdbc(properties的文件名).url,和字段名;’
***<bean id="readProperty" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>***
<!-- 配置数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.pwd}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="initialSize" value="5"/>
<property name="minIdle" value="5"/>
<property name="maxActive" value="10"/>
<property name="maxWait" value="5000"/>
<property name="timeBetweenEvictionRunsMillis" value="30000"/>
<property name="minEvictableIdleTimeMillis" value="300000"/>
<property name="testWhileIdle" value="true"/>
<property name="validationQuery" value="SELECT '1' from dual "/>
<property name="testOnBorrow" value="false"/>
<property name="testOnReturn" value="false"/>
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="true"/>
<property name="maxPoolPreparedStatementPerConnectionSize" value="20"/>
<!-- 配置监控统计拦截的filters,去掉后监控界面sql无法统计
<property name="filters" value="stat" />
-->
</bean>
<!-- 创建hibernate的sessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>com.seecen.hbnt.mappers/Clazz.hbm.xml</value>
<value>com.seecen.hbnt.mappers/Teacher.hbm.xml</value>
<value>com.seecen.hbnt.mappers/trainee.hbm.xml</value>
</list>
</property>
</bean>
<!-- 创建Hibernate事务 -->
<bean id="myTransaction" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- Spring 的aop事务-->
<!-- 配置切面(哪些方法要切入事务),事务隔离级别和事务传播特性 -->
<tx:advice id="methodAdvice" transaction-manager="myTransaction">
<tx:attributes>
<tx:method name="find*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"/>
<tx:method name="paging*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"/>
<tx:method name="query*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"/>
<tx:method name="isExist*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"/>
<tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED"/>
<tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED"/>
<tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED"/>
<tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 创建类的切面 -->
<aop:config>
<aop:pointcut expression="execution(* com.seecen..services.impl.*.*(..))" id="serviceCut"/>
<aop:advisor advice-ref="methodAdvice" pointcut-ref="serviceCut"/>
</aop:config>
<!--自定义切面-->
<aop:config>
<aop:aspect ref="log">
<aop:after-returning method="luanlai" returning="data" pointcut-ref="serviceCut"></aop:after-returning>
<aop:before method="doBefore" pointcut-ref="serviceCut"></aop:before>
<aop:after method="doAfter" pointcut-ref="serviceCut"></aop:after>
<aop:around method="doRound" pointcut-ref="serviceCut"></aop:around>
</aop:aspect>
</aop:config>
<bean id="log" class="com.seecen.myssh.aspect.LogAspect">
<constructor-arg name="value" value="Wuyequan"></constructor-arg>
</bean>
<bean id="clazzDao" class="com.seecen.myssh.dao.impl.ClazzDaoImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="clazzService" class="com.seecen.myssh.services.impl.ClazzServiceImpl">
<property name="clazzDao" ref="clazzDao"></property>
</bean>
<!--spring默认为单利, 设置为多例-->
<bean scope="prototype" id="clazzAction" class="com.seecen.myssh.action.ClazzAction">
<property name="clazzService" ref="clazzService"></property>
</bean>
</beans>
4:jdbc中的配置
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:xe
jdbc.username=quan
jdbc.pwd=123456
//方言配置,spring可以支持不同的数据库,这里我使用的是oracle11g,
由于没什么更新,用10g可以兼容.
jdbc.dialect=org.hibernate.dialect.Oracle10gDialect
第三步中,创建hibernate的sessionFactory,prop配置了三个hibernate映射文件
<property name="mappingResources">
<list>
<value>com.seecen.hbnt.mappers/Clazz.hbm.xml</value>
<value>com.seecen.hbnt.mappers/Teacher.hbm.xml</value>
<value>com.seecen.hbnt.mappers/trainee.hbm.xml</value>
</list>
</property>
5 例:Clazz.hbm.xml文件配置
<hibernate-mapping package="com.seecen.myssh.pojo">
<class lazy="true" name="Clazz" table="t_clazz">
<id name="clazzId" column="CLAZZ_ID" type="java.lang.Integer">
<generator class="native">
<param name="sequence_name">SEQ_CLAZZ</param>
</generator>
</id>
<property name="clazzName" column="CLAZZ_NAME"/>
<set name="trainees" inverse="true">
<!-- 这个是学员表的外键 -->
<key column="CLAZZ_ID"></key>
<one-to-many class="Trainee"></one-to-many>
</set>
</class>
</hibernate-mapping>
6:java的实现
pojo:
package com.seecen.myssh.pojo;
import java.util.Set;
public class Clazz {
private Integer clazzId;
private String clazzName;
private Set<Trainee> trainees;
public Integer getClazzId() {
return clazzId;
}
public void setClazzId(Integer clazzId) {
this.clazzId = clazzId;
}
public String getClazzName() {
return clazzName;
}
public void setClazzName(String clazzName) {
this.clazzName = clazzName;
}
public Set<Trainee> getTrainees() {
return trainees;
}
public void setTrainees(Set<Trainee> trainees) {
this.trainees = trainees;
}
}
Dao层:面向接口
1:
public interface IClazzDao {
void save(Clazz claz);
}
2:创建sessionFactory
public class BaseDao {
public SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory=sessionFactory;
}
public Session getSession(){
Session session=sessionFactory.getCurrentSession();
if(session==null){
session=sessionFactory.openSession();
System.out.println("走了openSession方法");
}
//System.out.println("走了OpenSession");
return session;
}
}
3:
public class ClazzDaoImpl extends BaseDao implements IClazzDao {
@Override
public void save(Clazz clazz) {
//接口Session中的方法,Session.class
getSession().save(clazz);
}
}
service层
1:
public interface IClazzService {
void save(Clazz clazz);
}
2:
public class ClazzServiceImpl implements IClazzService {
private IClazzDao clazzDao;
@Override
public void save(Clazz clazz) {
clazzDao.save(clazz);
}
//为什么只用setClazzDao?
public void setClazzDao(IClazzDao clazzDao){
this.clazzDao=clazzDao;
}
}
Controller层,action层:
public class ClazzAction extends ActionSupport {
private Clazz clazz;
private IClazzService clazzService;
public Clazz getClazz() {
return clazz;
}
public void setClazz(Clazz clazz) {
this.clazz = clazz;
}
public void setClazzService(IClazzService clazzService) {
this.clazzService = clazzService;
}
public String execute() throws Exception{
clazzService.save(clazz);
return SUCCESS;
}
}
service和action中只用了set方法,get自动调用?
jsp页面
<form action="${pageContext.request.contextPath}/clazz.action" method="post">
<input name="clazz.clazzName">
<input type="submit">
</form>
#输入要添加的班级的名字,提交之后,根据路径的clazz.action进入struts.xml中的配置(structs2的执行步骤),匹配里面namespace,name,和action的name进入该类中的方法,默认execute方法。
##该项目中配置切面,哪些方法要切入事物,事物隔离级别和事物传播特性
<tx:advice id="methodAdvice" transaction-manager="myTransaction">
<tx:attributes>
<tx:method name="find*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"/>
<tx:method name="paging*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"/>
<tx:method name="query*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"/>
<tx:method name="isExist*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"/>
<tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED"/>
<tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED"/>
<tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED"/>
<tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
//定义切在哪里 .. 表示seecen和service中间
<aop:pointcut expression="execution(* com.seecen..service.impl.*.*(..))" id="serviceCut"/>
<aop:advisor advice-ref="methodAdvice" pointcut-ref="serviceCut"/>
//ref表示的是上一个配置的id
//比如 aop中advisor配advice-ref =tx中的id
<!-- 自定义切面 -->
<aop:aspect ref="log">
<aop:after-returning returning="data" method="aaa" pointcut-ref="serviceCut"> </aop:after-returning>
<aop:before method="doBefore" pointcut-ref="serviceCut"></aop:before>
<!--<aop:after method="doAfter" pointcut-ref="serviceCut"></aop:after>-->
<aop:around method="doRound" pointcut-ref="serviceCut"></aop:around>
</aop:aspect>
</aop:config>