黑马程序员技术交流社区

标题: 【石家庄校区】框架知识点总结 [打印本页]

作者: 笑也要笑疯狂    时间: 2018-6-27 11:05
标题: 【石家庄校区】框架知识点总结
本帖最后由 小石姐姐 于 2018-7-17 13:56 编辑

struts2
引入步骤:
        1.导入jar(13个)
        2.在web.xml配置过滤器(StrutsPrepareAndExecuteFilter)
        3.配置struts.xml(action中有name, class, method属性,
                分别代表访问路径,类全名,类中方法名)
        4.创建Action(写逻辑)
        
解决:1.在Action中得到请求参数
                声明name属性,并提供get/set方法.
        2.实现路径跳转
                1.给Action添加String返回值
                2.在struts2中action标签中添加<result name="">标签.
                        name是Action中return的返回值.result中是路径.
eclipse导入本地dtd文件
eclipse导入本地xsd文件
        xml(可扩展标记语言)
        1.数据存储(不用,数据库)
        2.作为数据协议进行传输(xml/json)
        3.配置文件
        
约束:dtd约束,schema约束
        区别1. .dtd/.xsd
                2. schema约束支持命名空间
配置文件加载顺序:

      
[AppleScript] 纯文本查看 复制代码
  *1.default.properties声明常量
        *2.struts-default.xml(默认配置)声明interceptor  result  bean
                *struts-plugin.xml 插件配置声明
                *strtus.xml用于struts2(自定义配置)框架的配置
        3.struts.properties定制常量
        4.自定义配置提供
        5.web.xml
        6.bean相关配置

        
获取Servlet API

        1.通过ServletActionContext静态方法获取
            
[AppleScript] 纯文本查看 复制代码
    ServletActionContext.getRequest()
                ServletActionContext.getResponse()
                ServletActionContext.getServletContext()

        2.采用注入方式,实现interceptor中servletConfig参数中的接口

         
[AppleScript] 纯文本查看 复制代码
      ServletRequestAware
       ServletResponseAware
       ServletContextAware

               
Action如何接收前台页面的参数
        a)属性  提供get/set方法
        b)对象  提供对象,get/set方法  前台页面使用ognl 对象.属性
        c)模型驱动        ModelDriven  提供一个实例对象  实现getModel()方法,把实例对象进行返回
        d)使用servlet相关api获取
                ServletActionContext.getRequest().getParameter()
               
ognl:
        <%@ taglib prefix="s" uri="/struts-tags"%>
        <s:property value=""/>
        从根中获取,不需要加#
        从非根中获取,需要加#
        
        valueStack内部有root和context,它们分别是ArrayList和Map
                root中主要存储action的相关数据
                context中主要存储parameters,request,session,application的引用
        
        获取ValueStack:
                1.通过request对象来获取.(ValueStack保存在request中)
                ValueStack vs=(ValueStack)ServletActionContext.getRequest().getAttribut(
                        ServletActionContext.STRUTS_VALUESTACK_KEY);
                2.使用ActionContext获取.
                        ValueStack vs=ActionContext.getContext().getValueStack();
        向ValueStack中存储数据:(都是向root中存储)
                valueStack.push("hello");
                valueStack.set("username","tom");
               
               
request,action,actionContext,valueStack之间的关系:
        每一个请求访问一个action,action是多例,每一个action对应一个actionContext,
        每一个请求对应一个valueStack,valueStack中存放action对象和modelDriven中的Bean(如果实现的modeDriven接口),
        valueStack保存在request中.
        request-ActionContext-Action-ValueStack都对应一次请求(一个线程)

Ognl中的特殊字符:
        #:从非root中获取数据
        %:强制解析ognl表达式
        $:在配置文件中获取valueStack中的数据
        
Interceptor拦截器:
        Struts执行过程:
                当发送请求访问Action时,会被StrutsPrepareAndExecuteFilter监听器拦截,
                在监听器中采用动态代理方法加载struts.xml配置文件,对所有的interceptor进行遍历,每一个拦截器又采用递归.

        自定义拦截器:(使用自定义拦截器时,必须添加默认的拦截器)
                1.实现Interceptor接口 (对所有方法都拦截)
                        <interceptors>
                                <interceptor name="myInterceptor" class=""/>
                                <interceptor-stack name="myStack">
                                        <interceptor-ref name="myInterceptor"/>
                                        <interceptor-ref name="defaultStack"/> // 添加默认拦截器
                                </interceptor-stack>
                        </interceptors>
                        
                        可以在action标签中为特定的Action添加拦截器:
                                <action>
                                        <interceptor-ref name="myStack">
                                </action>
                2.继承MethodFilterInterceptor (对指定方法拦截)
                        <interceptor name="myInterceptor" class="">
                                <param name="includeMethods">showProduct</param>
                                <param name="encludeMethods">addProduct</param>
                        </interceptor>

文件上传:
        1.重要三点:表单method="POST",enctype=""multipart/form-data,<input type="file" name="upload">,
        2.对应的action中提供三个属性和get/set方法:
                private File upload; // 名称要与表单中<input>的name属性一致
                private String uploadContentType;
                private String uploadFileName;
        3.在执行方法中,将上传文件复制到服务器
                String path = ServletActionContext.getServletContext().getRealPath("/up");
                File dest = new File(path, uploadFileName);
                FileUtils.copyFile(upload, dest);
        4.在对应action中设置input视图,页面可设置<s:filederror/><s:actionerror/>查看错误信息
                <result name="input">/error.jsp</result>
        5.设置文件上传大小,上传类型等
                <constant name="struts.multipart.maxSize" value="20971520"></constant>
                <inperceptor-ref name="fileUpload">
                        <param name="allowedExtensions">bmp,txt</param>
                </interceptor-ref>
                <interceptor-ref name="defaultStack"/>

        多文件上传,action采用数组(或List<File>,List<String>)的形式.复制文件时单个存放:
                String path = ServletActionContext.getServletContext().getRealPath("/up");
                for(int i=0;i<upload.length;i++){
                        File dest = new File(path,uploadFileName);
                        FileUtils.copyFile(upload,dest);
                }

Fastjson:
        JSONObject.toJSONString();
        JSONArray.toJSONString();
        
        处理日期:
                在属性上添加@JSONField(format="yyyy-MM-dd")注解
Jackson:
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString();
        
        处理日期:
                mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
               
使用插件完成ajax操作:
        1.配置文件中<package extends="json-default">
        2.将元素压入栈顶.
                ActionContext.getContext().getValueStack().set("ps",ps);
        3.Action的返回视图<result name="" type="json">
                                        <param name="root">ps</param>

普通ajax操作和插件操作的区别:
        在服务器端:普通操作只需要使用json三方工具将对象转换成字符串response发送到客户端
                而插件操作将对象压入栈顶,配置 包继承,数据返回格式等.
        相比之下,使用三方工具包更方便容易.

注解:
        @Namespace("/")
        @ParentPackage("struts-default")
        @Action(value="名称",results={@Result(name="",type="",location="")})

Hibernate

ORM(Object Relation Mapping):对象关系映射

配置文件:
        类名.hbm.xml        映射配置文件. 与类在同一个包下
        hibernate.cfg.xml        核心配置文件,项目src下,根据project\etc\hibernate.properties配置
        
hibernate执行原理:
        1.通过Configuration().configure()读取并解析hibernate.cfg.xml配置文件,
                在这个配置文件中通过<mapping resource="xxx/xxx/类名.hbm.xml">读取解析
                映射信息.
        2.config.buildSessionFactory()得到sessionFactory对象
        3.sessionFactory.openSession()得到session对象
        4.session.beginTransaction()开启事务
        5.持久化操作
        6.session.getTransaction().commit()提交事务
        7.关闭session
        8.关闭sessionFactory
        
        总结:通过configuration依次解析读取hibernate.cfg.xml和xxx.hbm.xml配置文件,
                然后建立sessionFactory.通过sessionFactory打开session.session开启事务后,
                可以执行持久化操作,然后session再关闭事务.最后关闭session,关闭sessionFactory.
        
hibernate的核心类和接口共有6个,分别为
        Configuration,SessionFactory,Session,Transaction,Query,Criteria
        
        1.Configuration
                主要加载配置文件
                new Configuration().config()加载hibernate.cfg.xml核心配置文件
                new Configuration()加载hibernate.properties文件
        2.SessionFactory
                通过config.buildSessionFactory()得到,属于重量级,通常一个项目一个SessionFactory
                SessionFactory通过openSession()/getCurrentSession()得到Session.
               
                可以通过工具类控制SessionFactory唯一:
                        public class HibernateUtils {
                                private static Configuration config;
                                private static SessionFactory sessionFactory;
                                static{
                                        config=new Configuration().config();
                                        sessionFactory=config.buildSessionFactory();
                                }
                                public static Session openSession(){
                                        return sessionFactory.openSession();
                                }
                        }
                SessionFactory内还维护了一个连接池,要想导入其他连接池,需要配置核心文件
        3.Session
                可以通过session.beginTransaction()获得Transaction.
                用于持久化操作(方法):
                        save()/saveOrUpdate()
                        delete()
                        update()
                        get/load()
                        
                        createQuery()
                        createSQLQuery()
        4.Transaction
                用于管理事务
                commit事务提交
                rollback事务回滚
        5.Query
                查询(两种):HQL语言,本地SQL语句.        
                        分别通过session.createQuery(hql),session.createSQLQuery(sql)获得
                查询所有:
                        Query query=session.createQuery("from Customer");
                        List<Customer> list=query.list();
                分页查询:
                        query.setFirstResult(10);
                        query.setMaxResults(10);
                查询指定列:
                        Query query=session.createQuery("select new Customer(name,address) from Customer");
                        List<Customer> list=query.list();
                条件查询:
                        Query query=session.createQuery("from Customer where name=:myname");
                        query.setParameter("myname","xxx");
                        Customer c=(Customer)query.uniqueResult(); // 如果只有一条返回值,可以使用uniqueResult(),否则只能用list()
                        
                        无名称参数,对?的赋值从0开始
                        有名称的参数,对名称赋值.
                执行本地SQL:
                        SQLQuery sqlQuery=session.createSQLQuery("select * from t_customer where name=?");
                        sqlQuery.setParameter(0,"xxx");
                        sqlQuery.addEntity(Customer.class);// 必须装入实体,进行封装
                        Customer c=(Customer)sqlQuery.uniqueResult();
                        
                hql和sql在查询某列的时候,hql不需要装入实体,而sql需要装入.


Hibernate持久化类与主键生成策略
        
持久化类Persistent Object(PO)                 
PO=POJO+hbm映射配置

PO编写规则:
        1.无参的public构造方法
        2.private属性,并且get/set方法
        3.与数据库主键对应的标识属性OID
        4.基本数据类型尽量使用包装类
        5.PO类不能使用final修饰符
        
PO类不可以使用final修饰?(hibernate中的get/load方法的区别)
        Get/Load方法都是根据id去查询对象.
        1.get直接得到持久化类型对象,是立即查询操作.
                load得到的是持久化类型的代理对象(子类对象),采用延迟策略查询数据
        2.get方法查询结果不存在返回null
                load方法查询结果不存在产生ObjectNotFoundException异常
        
主键生成策略:
        主键分为:自然主键(具有业务含义),代理主键(不具有业务含义!!!必用!!!)
        代理主键:
                identity:mysql
                sequence:oracle
                native:根据数据库自动选择identity,sequence
                uuid:保证生成主键的唯一性(建议采用)
               
持久化对象的三种状态:
        1.瞬时态(临时态,自由态):new出来的对象,不存在OID,与session无关联
        2.持久态:具有OID,与session有关联.
        3.托管态(游离态,离线态):具有OID,与session无关联
        
        持久化对象会自动更新数据库:(采用快照)
                Customer c=session.get(Customer.class,1);
                c.setName("tom");
               
        三种状态切换:
                new出来的对象是瞬时态,
                session的get(),load(),find()等查询出来的对象是持久态
                瞬时态通过save(),saveOrUpdate()变为持久态
                持久态通过evict(),close(),clear()变为游离态

一级缓存:
        session进行save,get,update等进行操作时,就会将持久化对象保存到session中.
        下次进行session的load,get,Query的list等方法时就直接从session缓存中获取.
        当调用session的close方法时,session缓存清空.
        
        clear()清空一级缓存
        evict()清空缓存中指定的对象
        refresh()重新查询数据库,用数据库中的信息更新一级缓存与快照
        
关联映射:
        一对一:
                唯一外键对应:在任意一方添加外键描述对应关系
                主键对应:一方的主键作为另一方的主键
                Class Employee{
                        private Archives archives;
                }
                Class Archives{
                        private Employee employee;
                }
        一对多:
                在多的一方添加外键描述对应关系
                Class Customer{
                        private Set<Order> orders;
                }
                Class Order{
                        private Customer c;
                }
        多对多:
                通过中间表描述对应关系
                Class Student{
                        Set<Teacher> ts;
                }
                Class Teacher{
                        Set<Student> ss;
                }
               
        多方(.hbm.xml):
                <many-to-one name="一方的对象名" class="一方全类名" column="外键名"></many-to-one>
        一方(.hbm.xml):
                <set name="对象名">
                        <key column="外键名"/>
                        <one-to-many class="多方全类名"/>
                </set>
        双向关联:
                在<many-to-one>,<set>标签中添加cascade="save-update"表示级联添加,cascade="delete"表示级联删除
                inverse="true"只能在一方的<set>标签中存在,主要作用是,让多方维护外键.
        核心配置文件中:
                <mapping resource=""/> 使用/分隔路径
               
cascade总结:
        none:默认值
        save-update:底层使用save,update或save-update完成操作
        delete:级联删除
        delete-ophan:删除与当前对象解除关系的对象.
        all:包含save-update,delete操作
        all-delete-orphan:包含delete-orphan与all操作.(只能在一方设置)
               
cascade与inverse有什么区别?
        cascade主要完成级联操作
        inverse在双向关联情况下,用来指定由哪一方维护外键,true为让对方维护.
        

注解开发
类上:
        @Entity
        @Table(name="",catalog="")
主键上:
        @id
        @GenerateValue 默认native
                @GenerateValue(strategy=GenerationType.IDENTITY)
                        还有sequence等,uuid特殊须自行引入
                                @GenericGenerator(name="myuuid",strategy="uuid")
                                @GenerateValue(generator="myuuid")
属性上:(属性不写注解也会生成在表中)
        @Column(name="",length="",nullable=true) //name为关键字时,必须使用Column注解
        @Temporal(TemporalType.TIMESTAMP)
                还有DATE,TIME
        @Transient 不生成属性
        @Type(type="") 定义类型

一对多配置:
        一方:
        @OneToMany(targetEntity=Order.class,mappedBy="c",orphanRemoval=true)
                //targetEntity相当于<one-to-many class="">.Order.class是多方的类
                //mappedBy相当于inverse=true.c是多方持有一方的对象名        
                //orphanRemoval=true 相当于cascade="delete-orphan"
        @Cascade(CascadeType.ALL)!!!推荐使用
        多方:
        @ManyToOne(targetEntity=Customer.class)
        @JoinColumn(name="c_customer_id")  //指定生成外键名.
        @Cascade(CascadeType.SAVE_UPDATE)

多对多配置(不能做删除操作):
teachers表(放弃维护外键):
        @ManyToMany(targetEntity=Student.class,mappedBy="teachers")
                //mappedBy="teachers" 另一方持有本方的对象
        @Cascade(CascadeType.SAVE_UPDATE)
students表(描述中间表):
        @ManyToMany(targetEntity=Teacher.class)
        @JoinTable(name="s_t" joinColumns={@joinColumn(name="c_student_id")},inverseJoinColumns={@joinColumn(name="c_teacher_id")})
                //joinColumns 本方在中间表的列名
                //inverseJoinColumns 对方在中间表的列名
        @Cascade(CascadeType.SAVE_UPDATE)
一对一配置
User类:
        @OneToOne(targetEntity=IDCard.class,mappedBy="user")
        @Cascade(CascadeType.SAVE_UPDATE)
IDCard类:
        @OneToOne(targetEntity=User.class)
        @JoinColumn(name="c_user_id")  //外键
        @Cascade(CascadeType.SAVE_UPDATE)

核心配置文件中:
        <mapping class=""/> 不是/是.
        
检索方式(5种):
        1.导航图对象检索.(根据已加载的对象导航到其他对象)
                Customer c=session.get(Customer.class,2)
                c.getOrder().size()
        2.OID检索.(get/load )
        3.HQL检索.
        4.QBC检索.
        5.本地SQL检索
        
HQL检索:
完整句型:
        select/update/delete...from...where...group by...having...order by...asc/desc
        
基本检索:
        String hql="from Customer";
        List<Customer> list=session.createQuery(hql).list();
排序检索:
        String hql="from Order order by money desc";
        List<Order> list=session.createQuery(hql).list();
条件检索:
        String hql="from Order where money>?";
        List<Order> list=session.createQuery(hql).setParameter(0,2000d).list();
               
        String hql="from Order where money>:mymoney";
        List<Order> list=session.createQuery(hql).setParameter("mymoney",2000d).list();
分页检索:
        Query query=session.createQuery("from Order");
        query.setFirstResult((2-1)*6);
        query.setMaxResults(6);
        List<Order> list=query.list();
分组统计:
        String hql="select count(*) from Order";
        Object count=session.createQuery(hql).uniqueResult();
        
        String hql="select sum(money) from Order group by c";
        List list=session.createQuery(hql).list();
投影检索:
        String hql="select name from Customer";
        List list=session.createQuery(hql).list();
        
        //必须在PO类中提供对应的构造方法
        String hql="select new Customer(id,name) from Customer";
        List<Customer> cs=session.createQuery(hql).list();
命名检索:
        在Customer.hbm.xml中配置
                <query name="myHql">
                        from Customer
                </query>
        或在Customer类上添加注解
                @NamedQuery(name="myHql",query="from Customer")
        
        使用:
                Query query=session.getNamedQuery("myHql");
                List<Customer> list=query.list();
               
                Customer c=session.get(Customer.class,1);
                Query query=session.getNamedQuery("findOrderByCustomer");
                List<Order> list=query.setEntity("c",c).list();
离线条件检索:
        DetachedCriteria dc=DetachedCriteria.forClass(Customer.class);
        dc.add(Restrictions.like("name","%瑞_");
        
        Session session=HibernateUtils.openSession();
        session.beginTransaction();
        Criteria criteria=dc.getExecutableCriteria(session);
        List<Customer> list=criteria.list();
        
        
SQL多表操作
1.交叉连接(cross join)
        select * from t_customer cross join t_order;
2.内连接
        1)显示(join on)
                select * from t_customer c join t_order o on c.id=o.c_customer_id;
        2)隐式
                select * from t_customer c,t_order o where c.id=o.c_customer_id
3.外连接(outer可以省略)
        1)左外连接(left outer join on)
                select * from t_customer c left join t_order o on c.id=o.c_customer_id;
        2)右外连接(right outer join on)

HQL多表操作
1.内连接
        1)显示(join with)
                String hql="from Customer c join c.orders with c.id=1";
        2)隐式("."运算符关联)
                String hql="from Order o where o.c.id=1";
        3)迫切内连接(迫切内连接将结果封装到PO类,内连接得到Object[]数组)
****(fetch与distanct连用,fetch不能单独与with连用,限定条件时使用where)
                String hql="select distinct c from Customer c join fetch c.orders";
                Query query=session.createQuery(hql);
                List<Customer> list=query.list();
2.外连接
        1)左连接
                List<Object[]> list=session.createQuery("from Customer c left join c.orders").list();
        2)迫切左外连接
                List<Customer> list=session.createQuery("select distinct c from Customer c left outer join fetch c.orders where c.id=1").list();
                for(Customer c:list){
                        syso(c);
                }
               
        迫切连接与普通连接的区别:
                迫切连接将结果封装到PO类,普通连接将结果装进Object[]数组.
        
事务管理
事务:事务就是逻辑上的一组操作,组成这组操作的各个单元要么全部成功,要么全都失败.
四大特性:
        原子性:不可分割
        一致性:执行前后,数据一致
        隔离性:不受其他事务干扰
        持久性:保存到数据库
隔离性产生的问题:
        脏读:读未提交数据
        不可重复读:读到update数据
        虚读/幻读:读到insert数据
问题解决(Hibernate中隔离级别(1,2,4,8)):
        READ_UNCOMMITTED:引发所有隔离问题
        READ_COMMITTED:防止脏读                oracle默认级别
        REPEATABLE_READ:防止脏读,不可重复读                mysql默认级别
        SERIALIZABLE:解决所有问题.(效率最低)

session管理
本地线程绑定session
        配置hibernate.cfg.xml:
                <property name="hibernate.current_session_context_class">thread</property>
        获取session
                sessionFactory.getCurrentSession();
                注意:这个方法获得的session会自动关闭.不需要手动关闭,否则会报错.
               
HQL优化:
        1.使用参数绑定:既节省CPU时间和内存又避免SQL注入
        2.尽量少使用NOT
        3.尽量使用where替换having
        4.在含有子查询的hql中,尽量减少对表的查询
        5.使用表别名
一级缓存优化:
        session.evict()
        session.clear()

检索策略
1.类级别检索(立即检索和延迟检索,默认是延迟检索true)
        1)配置hbm.xml:
                <class name="Customer" table="t_customer" lazy="true">
        2)在类上使用注解
                @Proxy(lazy=true)
               
        对延迟对象进行初始化:
                1)对象.get()
                2)hibernate.initialize(对象)
        ****3)openSessionInView filter (Spring框架)
        
2.关联级别检索
        查询到某个对象,获得其关联的对象或属性,这种称为关联级别检索.
                c.getOrders().size();
                c.getName();
        检索策略(fetch和lazy)
                一方:Fetch取值:1.SELECT 多条简单的sql (默认值)
                                        2.JOIN 迫切左外连接
                                        3.SUBSELECT 生成子查询的SQL
                        Lazy取值:1.TRUE 延迟加载 (默认值)
                                        2.FALSE 立即加载
                                        3.EXTRA 加强延迟加载,及其懒惰
                注意:采用Fetch采用JOIN时,Lazy失效,程序采用左外连接立即加载
                        注解:
                                @Fetch(FetchMode.JOIN)
                                @LazyCollection(LazyCollectionOpetion.FALSE)
                                
                 多方:Fetch取值:1.SELECT
                                                2.JOIN
                        Lazy取值:1.FALSE
                                        2.PROXY 需要另一方的类级别延迟策略来决定
                        注解:
                                @Fetch(FetchMode.SELECT)
                                @LazyToOne(LazyToOneOption.PROXY)
        
批量抓取
        解决N+1问题
                注解@BatchSize(size=4)
                配置文件在<class>标签上设置 batch-size
               
                注意:无论是根据哪一方来查询另一方,在进行批量抓取时,都是在父方来设置,
                        如果是要查询子信息,那么我们是在<set>上来设置batch-size,如果是从子方
                        来查询父方,也是在父方<class>设置batch-size.
        


作者: zyq191485684    时间: 2018-7-15 09:25
不错!!!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2