SSH(struts2,spring4,hibernate5)详解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SSH(struts2,spring4,hibernate5)详解相关的知识,希望对你有一定的参考价值。

使用ssh框架的目的:

  将典型的J2EE结构,分为表现层、中间层(业务逻辑层)和数据服务层。三层体系将业务规则、数据访问及合法性校验等工作放在中间层处理。客户端不直接与数据库交互,而是通过组件与中间层建立连接,再由中间层与数据库交互。

 

 struts2的核心与工作原理

    在学习struts2之前,首先我们要明白使用struts2的目的是什么?它能给我们带来什么样的好处?

 

设计目标

 

    Struts设计的第一目标就是使MVC模式应用于web程序设计。

 

mvc的好处:

 利于批量生产、规模生产、相互协作、推广普及。

mvc的坏处:

 不利个案创作、独立创作、难艺术化、难个性化。

技术优势

    Struts2有两方面的技术优势,一是所有的Struts2应用程序都是基于client/server HTTP交换协议,The JavaServlet API揭示了Java Servlet只是Java API的一个很小子集,这样我们可以在业务逻辑部分使用功能强大的Java语言进行程序设计。

    二是提供了对MVC的一个清晰的实现,这一实现包含了很多参与对所以请求进行处理的关键组件,如:拦截器、OGNL表达式语言、堆栈。

 

 因为struts2有这样目标,并且有这样的优势,所以,这是我们学习struts2的理由,下面,我们在深入剖析一下struts的工作原理。

工作原理

Suruts2的工作原理可以用下面这张图来描述:

  技术分享

 一个请求在Struts2框架中的处理大概分为以下几个步骤 :

  1、客户端初始化一个指向Servlet容器(例如Tomcat)的请求

  2、这个请求经过一系列的过滤器(Filter)

 这个Filter 启动须要在在wed.xml配置文件里配置,配置详情如下:(注:前提要导入struts2的相关jar包

 <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>

 配置了Filter后,就会读struts.xml配置文件 ,根据struts.xml配置文件找到对应的Action 并实例化该Action 调用其方法execute(); 

 struts.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">
 <struts>
    <package name="mypac" extends="struts-default">
        <action name="index" class= "action.IndexAction" method="execute">
            <result name="success">/index.jsp</result>
            <result name="error">/error.jsp</result>
        </action>
   
     </package>
 </struts>
<result name="success">/index.jsp</result>
<result name="error">/error.jsp</result>

 调用其方法execute()后,就会返回一个字符串,根据对应的字符串找到对应的页面,返回给客户端(注:上面红色字体就是要和execute()返回的字符串相同才会找到对应页面

Struts2的总结:

  struts2给我的带来的好处如下:

1.获取表单内容,并组织生成参数对象
2.根据请求的参数转发请求给适当的控制器
3.在控制器中调用业务接口
4.将业务接口返回的结果包装起来发送给指定的视图,并由视图完成处理结果的展现
5.做一些简单的校验或是国际化工作

 二 spring4 的工作原理

  spring原理:

  内部最核心的就是IOC了,动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射,反射其实就是在运行时动态的去创建、调用对象,Spring就是在运行时,跟     xml Spring的配置文件来动态的创建对象,和调用对象里的方法的

   Spring还有一个核心就是AOP这个就是面向切面编程,可以为某一类对象 进行监督和控制(也就是 在调用这类对象的具体方法的前后去调用你指定的 模块)从而达到对一个模块扩充的功能。这些都是通过  配置类达到的。  
      Spring目的:就是让对象与对象(模块与模块)之间的关系没有通过代码来关联,都是通过配置类说明管理的(Spring根据这些配置 内部通过反射去动态的组装对象)  
      要记住:Spring是一个容器,凡是在容器里的对象才会有Spring所提供的这些服务和功能。  
Spring里用的最经典的一个设计模式就是:模板方法模式。(这里我都不介绍了,是一个很常用的设计模式), Spring里的配置是很多的,很难都记住,但是Spring里的精华也无非就是以上的两点,把以上两点跟理解了 也就基本上掌握了Spring.

在wed.xml配置(目的:启动spring 监听整个wed项目)

 

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

 

 

 

配置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" />

    <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>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.connection.autocommit">false</prop>
                <!-- 开机自动生成表 -->
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
        <property name="mappingResources">
            <list>
                <value>news/entity/News.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}" />
        <!-- 每300秒检查所有连接池中的空闲连接 -->
        <property name="idleConnectionTestPeriod" value="300"></property>
        <!-- 最大空闲时间,900秒内未使用则连接被丢弃。若为0则永不丢弃 -->
        <property name="maxIdleTime" value="900"></property>
        <!-- 最大连接数 -->
        <property name="maxPoolSize" value="2"></property>

    </bean>
    
    <bean id="myNewsAction" class="news.action.NewsAction" scope="prototype">
        <property name="ns" ref="myNewsService"></property>
    </bean>
    
    <bean id="myNewsService" class="news.service.NewsServiceImpl" scope="prototype">
        <property name="nd" ref="myNewsDao"></property>
    </bean>
    
    <bean id="myNewsDao" class="news.dao.NewsDaoImpl" scope="prototype">
        <property name="sf" ref="mySessionFactory"></property>
    </bean>    
</beans>
            

 

引入的外部属性文件(jdbc.properties)目的:为了就算不懂java代码的人也可以配置数据库
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/news
jdbc.user=root
jdbc.password=123456


#oracle
jdbc_oracle.driver=oracle.jdbc.driver.OracleDriver
jdbc_oracle.url=jdbc:oracle:[email protected]127.0.0.1:1521:orcl
jdbc_oracle.user=news
jdbc_oracle.password=123456
sprinng的配置文件的简化(目的:少写一些配置文件)

实现方法通过spring的注解:

我们可以发现下面这段代码是不是感觉比较复杂或者说不好看 ,我们可以通过注解代替它

 <bean id="myNewsAction" class="news.action.NewsAction" scope="prototype">
        <property name="ns" ref="myNewsService"></property>
    </bean>
    
    <bean id="myNewsService" class="news.service.NewsServiceImpl" scope="prototype">
        <property name="nd" ref="myNewsDao"></property>
    </bean>
    
    <bean id="myNewsDao" class="news.dao.NewsDaoImpl" scope="prototype">
        <property name="sf" ref="mySessionFactory"></property>
    </bean>    

我们可以直接删除上面这些配置文件,再添加一个注解的解释器:很简单只需配置一句:<context:component-scan base-package="news"></context:component-scan>(注:news 是须要注解类所在的包名,或者包名的前置)

技术分享

上面只列举了在dao中的注解,我们还需要在action、service里也使用同样的方法添加注解。这里就不一一举例了。   

    [email protected]注解--定义控制器(类级别上的注解)action)

      [email protected]注解--定义业务处理类(service)

      [email protected]注解--定义底层数据库处理接口(dao)

      [email protected]注解--实现注入(jdk)

      [email protected]("prototype")--//非单例

 

三 hibernate 的核心与原理

Hibernate是开源的一个ORM(对象关系映射)框架


      ORM,即Object-Relational Mapping,它的作用就是在关系型数据库和对象之间做了一个映射。从对象(Object)映射到关系(Relation),再从关系映射到对象。这样,我们在操作数据库的时候,不需要再去和复杂SQL打交道,只要像操作对象一样操作它就可以了(把关系数据库的字段在内存中映射成对象的属性)。


 Hibernate的核心:

 

技术分享

Hibernate的优/缺点:

 优点:

1、更加对象化

      以对象化的思维操作数据库,我们只需要操作对象就可以了,开发更加对象化。

2、移植性
      因为Hibernate做了持久层的封装,你就不知道数据库,你写的所有的代码都具有可复用性。

3、Hibernate是一个没有侵入性的框架,没有侵入性的框架我们称为轻量级框架。

      对比Struts的Action和ActionForm,都需要继承,离不开Struts。Hibernate不需要继承任何类,不需要实现任何接口。这样的对象叫POJO对象。

4、Hibernate代码测试方便。

5、提高效率,提高生产力。

 

缺点:

1、使用数据库特性的语句,将很难调优

2、对大批量数据更新存在问题

3、系统中存在大量的攻击查询功能

 

四 Spring声明式事务

 

1.什么是声明式事务?

  声明式事务(declarative transaction management)是spring提供的对程序事务管理的方式之一。Spring的声明式事务就是采用声明的方式来处理事务,用在Spring配置文件中声明式的处理事务来代替代码式的处理事务。这样的好处是,事务管理不侵入开发的组件,具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要更改事务管理,也只需要在定义的配置文件中修改配置即可,在不需要事务管理的时候,只要在配置文件上修改一下,即可移去事务管理服务,无需改变代码重新编译,这样维护起来极其方便。

 

2.首先我们看看手动写事务如下图:

技术分享

由上图可以看出,首先我们需要建立一个新的session.openSession(),其次通过session的getTransaction().begin()方法和getTransaction().commit()方法进行事务创建和事务提交,并且需要关闭session.close(),这样一来我们每次调用这个方法都会重新创建一个新的session,都要反复的做一样的事情,这样就不符合我们的软件工程设计思想,接下来我们使用声明式事务管理方式进行对代码的简化和调整

 

使用springAOP声明式事务管理。

1.首先我们要到aop的jar包

技术分享

2.然后在application.xml配置文件中进行事务配置:

<!--配置事务  -->
    <!--配置Hibernate的局部事务管理器,使用HibernateTransactionManager类  -->
    <!--该类实现PlatformTransactionManager 接口,是针对Hibernate的特定实现  -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <!--配置HibernateTransactionManager时须要注入SessionFactory的引用  -->
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
    
    <!--配置事务的增强处理,指定事务管理器  -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="del*" propagation="REQUIRED" />
            <tx:method name="mod*" propagation="REQUIRED" />
            <tx:method name="*" propagation="REQUIRED" read-only="true" />
        </tx:attributes>
    </tx:advice>
    
    <aop:config>
        <aop:pointcut id="interceptorPointCuts"
            expression="execution(*   
        dao.*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="interceptorPointCuts" />
    </aop:config>

 

将上图dao的代码进行修改 将session.openSession()改成getCurrentSessionn(); 由Spring去帮我们去启动事务去管理。

技术分享

2、使用@Transactional注解方式。

首先在application.xml配置文件里配置@Transactional注解的解析器具体如下:

<!--配置事务  -->
    <!--配置Hibernate的局部事务管理器,使用HibernateTransactionManager类  -->
    <!--该类实现PlatformTransactionManager 接口,是针对Hibernate的特定实现  -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <!--配置HibernateTransactionManager时须要注入SessionFactory的引用  -->
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
    <!--解析事务注解  -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    

接下来就注意里 这里的注解不是写在dao层 而是写在service层,应为是service调用了dao 大家千万注意了 具体如下:

技术分享

技术分享

 

  



















以上是关于SSH(struts2,spring4,hibernate5)详解的主要内容,如果未能解决你的问题,请参考以下文章

SSH框架的简化(struts2spring4hibernate5)

SSH框架的简化(struts2spring4hibernate5)

基于struts2.5.2+hibernate5.2.2+spring4.3.2搭建SSH框架

SSH整合(struts2.3.24+hibernate3.6.10+spring4.3.2+mysql5.5+myeclipse8.5+tomcat6+jdk1.6)

原创整合Spring4+Hibernate4+Struts2时NullPointerException问题解决

SSH整合