SSH框架总结

SSH框架总结

一、搭建SSH框架

1.1导入相关Jar包 大约45个
1.2相关配置文件
1.2.1web.xml
1、配置ContextLoaderLinstener,用于加载spring 的applicationContext.xml配置文件
    默认加载位置为web-inf下的,需要指明 配置文件位置  contextConfigLocation
    如果配置文件找不到,就会报FileNotFound找不到异常
    <!--配置Spring加载 监听器 -->
      <listener>
        <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>
    clsspath是spring中特有的用于标识类路径下
1、1在配置Struts2可以配置OpenSessionInViewFilter  用于解决nosession问题,非必须,
    必须配置在struts2核心控制器之前
    <filter>
    <filter-name>openSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>openSessionInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
2、配置Struts核心控制器  StrutsPreparedAndExecuteFilter  
        两个作用:加载struts2配置文件在init方法中加载,配置文件只加载一次,对用户的action请求或空白请求进行拦截
     <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>

3、配置Spring编码过滤器   CharacterEncodingFilter   用于解决post请求乱码问题
        可以配置参数 encoidng   UTF-8
    非必须,因为如果使用struts2与spring整合时,struts2本身就解决了post请求乱码问题
        <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <!--配置参数,指定使用UTF-8编码  -->
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
1.2.2struts.xml文件配置
1、struts2的配置文件:
    default.properties    配置struts运行中的常量
    struts-default.xml    配置拦截器以及结果视图,以及bean的配置
    struts-xxx-plugin.xml   插件的配置文件,非必须
    struts.xml            程序员编写的配置文件,配置常量,action,自定义拦截器等
    struts.properties    配置常量,一般不需要配置,在struts.xml文件中配置
2、package配置
    name 包名,唯一   
    namespace名称空间 默认为 "/"   
    extends 继承的父包  默认为struts-default
3、action配置
    name 访问名称   Action_*  *表示访问方法
    class 类的全限定类名或者spring中对应的id名称    
    method 方法       ${1}表示第一个*代表的内容
    result 逻辑视图  
    interceptor-ref 明确指明当前使用的是哪个拦截器
        可以配置param  name
    namespace+name  路径为action的完整访问路径
4、interceptor配置
    interceptors 表示所有拦截器
        interceptor 配置自定义的拦截器  name  拦截器的名称 ,class拦截器的全限定类名
        interceptor-stack  配置拦截器栈  
            interceptor-ref 配置拦截器引用   name拦截器的名称   自定义拦截器放在默认拦截器栈后面
    default-interceptor-ref 默认拦截器配置   name=拦截器或着拦截器栈名称
5、拦截器
    拦截器是struts2的基石,很多功能都是基于拦截器实现的,在用户访问action方法之前执行,采用责任链的设计模式
    ,采用递归调用的方式执行。
6、拦截器的编写
    实现Interceptor接口
    继承AbstractInterceptor类
    继承MethodFilterInterceptor类
 我们一般使用继承AbstractInterceptor
    <struts>

        <constant name="struts.enable.DynamicMethodInvocation" value="false" />
        <constant name="struts.devMode" value="true" />
        <!--配置上传文件大小  -->
        <constant name="struts.multipart.maxSize" value="20000000"></constant> 
        <!-- 加载国际化配置文件 -->
        <constant name="struts.custom.i18n.resources" value="uploadError" />
        <!--全局包,用于配置全局信息  -->

        <package name="public" namespace="/" extends="struts-default">
            <interceptors>
                <interceptor name="loginInterceptor" class="loginInterceptor"></interceptor>
                <interceptor-stack name="myInterceptorStack">
                    <interceptor-ref name="defaultStack"></interceptor-ref>
                    <!-- 自定义拦截器放在默认拦截器后面 -->
                     <interceptor-ref name="loginInterceptor">
                     <!--  设置不需要拦截的方法-->
            <param name="excludeMethods">customerAction_list,linkmanAction_list,sysUserAction_login,sysUserAction_loginUI</param>
                     </interceptor-ref> 

                </interceptor-stack>
            </interceptors>
            <default-interceptor-ref name="myInterceptorStack"></default-interceptor-ref>
            <global-results>
                <result name="loginError">/login.jsp</result>
                <result name="success">/jsp/success.jsp</result>
                <result name="error">/jsp/error.jsp</result>
            </global-results>
        </package>

        <include file="struts/struts-sysUser.xml"></include>
        <include file="struts/struts-customer.xml"></include>
        <include file="struts/struts-linkman.xml"></include>
         <include file="struts/struts-saleVisit.xml"></include>
    </struts>   
1.2.3applicationContext.xml文件配置
1、配置数据源,用于连接数据库
    C3P0数据源   ComboPooledDataSource
        driverClass jdbcUrl user password
    DBCP数据源   BasicDataSource
    JDBC数据源   DriverManagerDataSource

2、配置sessionFactory 是sring与hibernate整合的关键点     类LocalSessionFactoryBean
    dataSource    configLocations(classpath:hibernate.cfg.xml)
3、配置Hibernate事务管理器
    transactionManager    

    需要注入sessionFactory
4、配置声明式事务通知
    transaction-manger 指明使用的事务管理器
    tx:method 表示哪些方法使用事务  name为方法名,propagation为事务行为
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    声明式事务的原理:AOP
    AOP的原理是什么?动态代理模式
    动态代理模式?JDK实现动态代理,cglib实现动态代理
    这两种方式的区别:JDK动态代理时目标对象一定实现接口,而cglib可以不实现
    JDK动态代理用的类?Proxy.newProxyInstance()
    Cglib代理如何实现?
        1.创建一个Enhancer eh = new Ehancer();
    2.Eh.setSuperClass();
    3.设置回调:eh.setCallback();
    4.生成代理对象:eh.create();

    1.  事务管理器的配置
    父接口:PlatformTransactionManager
    Hibernate事务管理器的子类:HibernateTransactionManager
    Jdbc事务管理器的子类:DataSourceTransactionManager

    PlatformTransactionManager它的内部是什么工作的?
    TransactionDefinition:事务定义信息
    TransactionStatus:事务状态
    它需要根据TransactionDefinition这个对象,得到事务的定 义信息,再根据事务的执行状态TransactionStatus,来决定事务是提交还是回滚。

    2.  事务通知的配置:<tx:advice>
    事务通知advice为什么可以作用到切入点表达式所指定的类中的方法?
    因为在配置声明式事务时,它的本质也是去生成代理子类对象,所以此时只要根据你指定的切入点表达式的要求,针对目标对象直接生成代理对象,而同时通过aop来实现横向代码的动态织入,从而实现了事务的控制。它对应的通知类型,可以认为环绕通知。

5、配置声明式事务与aop整合
    aop:pointcut 配置切入点表达式 expresssion(需要事务执行的方法)  
    <aop:config>
        <aop:pointcut expression="execution(* cn.lx.crm.service.impl.*.*(..))" id="myPointcut"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"/>
    </aop:config>
6、配置文件分离的思想
    公共配置+分层思想
    applicationContext.xml
    applicationContext-dao.xml
    applicationContext-service.xml
    applicationContext-action.xml
    公共配置+分模块思想
    applicationContext.xml
    applicationContext-customer.xml
7、bean配置的作用域
    request\session\global session\singleton\prototype
        signleton 单例
        prototype 多实例     配置action时,一定要配置多实例
8、bean生命周期  spring配置文件加载时创建
    init destory
9、bean对象的创建三种方式
    构造函数  实例工厂 静态工厂
10、bean对象注值的三种方式
    setter注值  构造函数注值  p名称空间注值
1.2.4 hibernate.cfg.xml文件配置
1、配置SQL方言
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
2、配置自动建表
<property name="hibernate.hbm2ddl.auto">update</property>
3、配置显示SQL
<property name="hibernate.show_sql">true</property>
4、配置格式化SQL
<property name="hibernate.format_sql">true</property>
5、配置session绑定本地线程
<property name="hibernate.current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext</property>
6、配置事务隔离级别
<property name="hibernate.connection.isolation">4</property>
7、导入映射文件
<mapping resource="cn/lx/crm/domain/BaseDict.hbm.xml"/>
1.2.5 准备PO类及映射文件
  1、PO类的编写规范:
        1.  私有属性
        2.  提供公有的无参构造 
        3.  提供 私有属性的公有getter与setter
        4.  类名不能用final
        5.  实现java.io.Serailizable接口
        6.  是一个公有类
        7.  如果是基本类型的属性,请使用它的对应包装类
  2、映射文件命名 类名.hbm.xml
        <class name=”包名.类名” table=””>
           <id name=”” column=””>
             <generator class=”uuid,assigned,identity,increment,native,sequence”/>
              </id>
             <property name=”” column=”” not-null=”tru” type=”” length=”” />
            <property name=”” column=”” not-null=”tru” type=”” length=”” />

        </class>
 3、关联关系的配置  
    分别为一对多关系、多对一关系、多对多关系、一对一关旭
    Customer的类中:
    一对多
    Private Set<Linkman> linkmans = new HashSet<Linkman>(0);
    Customer.hbm.xml文件中
    <set name=” linkmans” cascade=”” inverse=””  fetch=”join|select” lazy=”true|false|extra”>
       <key column=”外键字段名”/>
      <one-to-many class=” Linkman” />
    </set>

    Cascade取值:all,save-update,delete,delete-orphan, delete-orphan-all
    Inverse取值:true,false,默认为false
    Cascade与inverse的区别?
    1.  cascade代表父子项操作时的级联关系
    2.  inverse代表控制权交给谁管理,true代表控制权交给对方管理
    3.  inverse一般 设置为true,交给多方维护,这样可以提高效率

    fetch的特点:fetch=”join”时lazy失效,同时它采用迫切左外连接实现的查询
    它可以解决noSession问题
     Fetch=select,它将采用多条sql语句的形式进行查询,发出sql的时机由lazy来决定,想立即发出sql就用lazy=”false”,希望在加载这个记录时才出现sql语句,就让lazy=”true|extra”


    多对一的配置:
    Linkman.java中配置:
    Private Customer customer;

    Linkman.hbm.xml文件
    <many-to-one name=”customer” class=” Customer”  column=”外键字段名”></ many-to-one>

    多对多的配置:
    SysUser与SysRole用户与角色
    SysUser.java
    Private Set<SysRole> sysRoles = new HashSet<SysRole>(0);
    SysUser.hbm.xml文件
    <set name=”” table=”” inverse=”true”>
         <key column=”关联到自身的来自中间表的外键”/>
         <many-to-many class=” SysRole” column=” 关联到SysRole来自中间表的外键”/>
    </set>
2 DAO模式
1.编写BaseDao<T>接口
2.编写实现类BaseDaoImpl
Public BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T>{
   Class clz;
  Public BaseDaoImpl(){
         Type type = this.getClass().getGenericSuperClass();
         ParameterizedType pt = (ParameterizedType)type;
         clz = (Class)Pt.getActualArgumentsType()[0];
 }

   Public List<Customer> findAll(){
      return this.getHibernateTemplate().find(“from    ”+clz.getName());
  }
}

Class CustomerDaoImpl extends BaseDaoImpl<Customer> implements CustomerDao{

}

getHibernateTemplate().find()内部的本质是什么执行的?
Session session = sessionFactory.openSession();
AOP:横向插入事务开启的代码
Query query = Session.createQuery(“from “+clz.getName());
Query.list();
AOP: 横向插入事务提交或回滚的代码

Hibernate实现数据检索的5种方式
get/load   加载时使用对象的OID(Object Identity Qualified  对象的唯一标识)
QBC  Query By Criteria          Criteria c = session.createCriteria(Customer.class);
HQL     Query query = session.createQuery(“”);
对象导航  前提:先配置好对象之间的关联关系  
Set<linkman> linkmans = customer.getLinkmans();
SQL   :SQLQuery query = session.createSQLQuery(“sql”).addEntity(Customer.class);


面试:get/load加载数据的区别?
1.  get立即加载,load延迟加载
2.  load加载的对象为代理对象,get加载的是真实对象
3.  load加载失败会出现异常,而get加载失败返回null
4.  get加载时就会出现sql语句,而load只会调用属性时才会真正加载(才会有sql)
5.  load方法也可以实现与get方法相同的效果:第一种方法只要在相应的映射文件中找到class结点,添加一个lazy=”false”   第二种方法:在PO定义时加上final
结论,加载数据失败时,load总是会抛出异常
3 Hibernate一级缓存
一级缓存:它是与session关联在一起的,如果session不存在了,一级缓存也就不存在了。

    一级缓存的内部结构:
    Hashtable,就是key-value对。
    结于持久态的对象,没有调用update()方法,也会实现更新操作?因为它会根据一级缓存中的快照区与真实对象进行比较,如果有更新,就会在事务提交时,将更新后的结果刷出到数据库中。(tx.commit();默认就会调用session.flush();)

    一级缓存中常用的操作方法:
    clear();清空一级缓存
    evict(Object obj)在一级缓存中清空指定的对象
    flush()可以做到一级缓存中数据与数据库中数据的同步更新
    refresh()再次将数据库中的数据查询出来,填充一级缓存

4 struts2的封装数据的方式

1.获取参数
   ServletActionContext.getRequest.getParameter(“custId”);
2解耦合方式获取参数
   ActionContext.getContext().getParameters().get(“custId”)[0];

3.属性驱动来实现参数封装(params拦截器)
  Customer/customerAction_find?age=10;
CustomerAction类中
Private int age;
Public void setAge(int age){
   This.age =age;
}

Customer/customerAction_find?customer.age=10;
private Customer customer;
//生成它的setter与getter

4.模型 驱动:(modelDriven拦截器)
1.模型驱动要求实现一个接口:ModelDriven<Customer>,同时还要重写getModel(),这个方法要求返回一个已存在的对象。

5 值栈

1.什么是值栈?
它是一个用于保存数据的容器,它本身只是一个叫做ValueStack接口,它的实现类是OgnlValueStack.
2.如何得到ValueStack实例?
 ValueStack vs1 =  ActionContext.getContext().getValueStack();
 ValueStack vs2 =  request.getAttribute(“struts.valueStack”);

针对同一次请求,不管用上面的哪个方法,获取的都是同一个对象。每次请求时,valueStack都是一个新的对象,action对象也是一个新的对象

3.ValueStack的内部结构
root  :类型 CompoundRoot  而CompoundRoot又继承了ArrayList父类
context:类型 OgnlContext ,而OgnlContext又实现Map接口

默认操作值栈都是在操作root



4.为什么EL表达式也能访问值栈?
  用到RequestWrapper对request进行包装,在包装类中可以找到一个getAttribute()而这个方法首先是在request域中找数据,如果没有就会找valueStack.
request = prepare.wrapRequest(request);

你可能感兴趣的:(框架,ssh)