• ssh


    基础加强(反射)

    枚举(了解)

    私有化有参和无参的构造方法,用于多选一

    enum Grade{

             A("90-100"),B("80-90"),C("70-80"),D("60-70"),E("<60");

            

             private String score;

             private Grade(String score){

                       this.score=score;

             }

             public String toString() {

                       return "Grade [score=" + score + "]";

             }

    }

    等同于在普通类里进行公有化的new对对象

    public static Grade A = new Grade("90-100");

             public static Grade B = new Grade("80-90");

             public static Grade C = new Grade("70-80");

             public static Grade D = new Grade("60-70");

             public static Grade E = new Grade("<60");

    反射(重点)

    概念

    java世界里的万物皆对象。

    读取类的过程:  由类加载器(ClassLoader)读取class字节码文件,把字节码文件的信息读取进内存,就会被构造成一个Class对象,利用Class对象去构造对象,调用方法,给属性赋值或获取属性值等等操作,这个过程就是反射!!

    不通过new获取类对象

    Class stu = Class.forName(输入完整包名);   //推荐常用

    Class stu = Student.class;   类名+class

    Class stu = new Student().getClass();

    Class对象,代表一个类

    getName()    //获取完整包名加类名

                       getSimpleName()  //获取类名

                       getSuperClass()    //得到普通父名

                       getGenericSuperClas()  //得到泛型父名

                       getInterfaces()  //得到普通类的接口名

                       getGenericIntefaces();    //得到泛型接口

    getDeclaredConstructor(输入属性名可多个)  //没输入就是得到无参,有输入就是得到有参

    getDeclareMethod(输入get set方法,输入类型+class)  //可以拿到get 、set方法

    getDeclareField(输入成员属性名)   //可以得到成员属性

    Constructor对象:代表一个构造方法

                                newInstance()   获取构造对象

    Method对象: 代表一个普通方法

                                invoke(obj,参数值)  调用方法

    Filed对象:代表一个属性         

                                set(obj,参数)  赋值

                                get(obj)   获取值

    Type         对象:所有类型的公共高级接口

    GenericArrayType   数组类型子接口

    ParameterizedType   参数类型子接口(常用)

    TypeVariable<D>    变量的子接口

    WildcardType   通用的子接口

    泛型

    用处:把运行时异常转化为编译时异常,减少类型转换。

    泛型语法

                       泛型方法(*)

                                public <T> T method(T t){

                                }                          

                      

                       好处:为了写出通用方法

            

                       泛型类/泛型接口

                                public class Demo<T>{

                                }

                       好处:为了减少泛型方法的声明

    ?:  任意类型,为了保证泛型语法的完整性

    extends: 当前类型或者当前类型的子类   向下取

    super: 当前类型或者当前类型的父类    向上取

    组合使用:(List<? super Number> list)  

     

    泛型+反射

    getGenericSuperClass()   //获取dao的泛型父列:BaseDao<Student>

    应用:反射+泛型写出通用代码

     

    //用于抽取业务dao的通用方法

    //规则:表名称和类名保存一致(大小写不区别)

    public class BaseDao<T> {

             private Class targetClass;//需要封装的类型

             private String tableName;//需要查询的表名称

            

             //在BaseDao中如何接收泛型类?

             public BaseDao(){

                      //System.out.println(this.getClass());// this: StudentDao 或者TeacherDao

                      

                       Class clz = this.getClass();//当前运行的dao:StudentDao

                       Type type = clz.getGenericSuperclass();//获取dao的泛型父列:BaseDao<Student>

                       ParameterizedType pt = (ParameterizedType)type;//类型转换:转换成参数化类型的子类

                       Type[] tps = pt.getActualTypeArguments();  // 取出参数化类型的参数:<Student>

                       targetClass = (Class)tps[0]; // 取出第一个参数: Student.class

                      

                       //表名

                       tableName = targetClass.getSimpleName().toLowerCase();

             }

            

            

             QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());

             public List<T> findAll(){

                       try {

                                return qr.query("select * from "+tableName+"", new BeanListHandler(targetClass));

                       } catch (SQLException e) {

                                e.printStackTrace();

                                throw new RuntimeException(e);

                       }

             }

            

             public T findById(int id){

                       try {

                                return (T)qr.query("select * from "+tableName+" where id=?", new BeanHandler(targetClass),id);

                       } catch (SQLException e) {

                                e.printStackTrace();

                                throw new RuntimeException(e);

                       }

             }

    }

    Struts2框架

    struts2概念

             struts2是一个基于MVC思想的表现层框架!!!

             struts2的底层来源于另一个表现层框架webwork  (xwork-core.jar)      

             struts2是struts1+webwork的整合框架

    步骤1)struts2的jar包(最少)
    commons-fileupload-1.3.1.jar  【上传组件】

    commons-io-2.2.jar      【上传组件】

    commons-lang3-3.2.jar    【字符串处理工具类】

    freemarker-2.3.22.jar    【freemarker框架包】

    javassist-3.11.0.GA.jar  【字节码处理工具类】

    ognl-3.0.6.1.jar          【ognl表达式的支持包】

    struts2-core-2.3.24.3.jar  【struts2自身的支持包】

    xwork-core-2.3.24.3.jar   【wbeworkd框架的支持包】

    步骤2)在web.xml中配置struts2的过滤类

    org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter(在导入包中)

    配置内容:

    <web-app version="2.5"

             xmlns="http://java.sun.com/xml/ns/javaee"

             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

             http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

            

      <display-name></display-name>        

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

     </web-app>

    步骤3)写一个业务逻辑操作类

             Public class XXXX(){

                       Public String xxx(){

             (内容)

    }

    }

    步骤4)写一个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>

             <!-- struts-default:不要修改 /: 不要修改-->

                                                                             继承包名需要加后缀分辨

             <package name="(任意名字)" extends="struts-default" namespace="/">  //包名

                                           可以用通配符*或*_*

    <action name="(任取:路径访问名)" class="(完整包名)" method="(方法名)"> //类名

                                                方法返回名一致          可以多个方法

    <result name="success" type="redirect">/index.jsp</result> //方法名

                       </action>

             </package>

            

    </struts>

    Struts2执行流程

    项目启动:

                       1)创建StrutsPrepareAndExecuteFilter核心过滤器对象

                       2)调用StrutsPrepareAndExecuteFilter的init方法

                                 init_DefaultProperties();  读取default.properties (常量文件)

                                                                     (or/apache/struts2/default.properties)

                                 init_TraditionalXmlConfigurations() 读取struts的核心xml配置文件

                                         struts-default.xml   struts2的默认配置文件 (业务功能的声明)

                                         struts-plugin.xml   struts2的插件配置文件

                                         **struts.xml**      struts2的核心流程的配置文件(自行修改的)

    每次发出请求(访问资源):

                       1)调用StrutsPrepareAndExecuteFilter的doFilter方法

                       2)根据用户的请求uri在struts.xml文件的内容匹配对应的action

                       3)创建一个action配置的class的类对象(Action类对象)

                       4)调用Action类对象的指定的method方法

                       5)返回一个视图的字符串

                       6)根据视图的字符串查找匹配的result

                       7)跳转到具体的result的路径

    解读struts-default.xml

    业务功能声明文件

    <result-types>

                                常用的视图类型:

                                dispatcher: 转发页面

                                redirect:重定向页面

                                chain: 转发到Action

                                redirectAction:重定向到Action   (内容写另一个Action的name属性)

                                stream: 用于文件下载的  

                       </result-types>                 

    拦截器(重要的概念)

    在struts.xml配置中如何引用拦截器

    <action name="demo" class="cn.itcast.interceptor.ActionDemo" method="admin">

                       <interceptor-ref name="(打包拦截器名)"></interceptor-ref> //引用打包后的拦截器

                       <result>/uploe.jsp</result>

    </action>

    //全局使用拦截器

    <default-interceptor-ref name="(打包拦截器名)"></default-interceptor-ref>

                                拦截器效果类似于过滤器

                                拦截器 vs 过滤器

                                过滤器:是servlet的组件,用于过滤请求和响应

                                拦截器:是struts2的组件,只能用于拦截action

                       -->

                       <interceptors>

                                com.opensymphony.xwork2.interceptor.ParametersInterceptor:参数拦截器

                                org.apache.struts2.interceptor.FileUploadInterceptor:文件上传拦截器

                                com.opensymphony.xwork2.interceptor.I18nInterceptor:国际化拦截器

                                .......

                       </interceptors>

    创建拦截器类一个普通类继承MethodFilterInterceptor也可以继承AbstractInterceptor类

    public class HelloInterceptor extends MethodFilterInterceptor{

             //执行业务逻辑方法:doIntercept类似Filter的doFilter方法

             //ActionInvocation类似Filter的FilterChain

             @Override

             protected String doIntercept(ActionInvocation invocation) throws Exception {

                       System.out.println("1.执行拦截器的前面代码");

                       /**

                        * 放行:

                        * 调用下一个拦截器,或者是目标的action

                        */

                       invocation.invoke();

                       System.out.println("3.执行拦截器的后面代码");

                       return null;

             }

    Struts.xml中配置拦截器(在package包中)

    <interceptors>

    <interceptor name="(自定义拦截器的名字)" class="(完整包名)"></interceptor> //引用拦截器

    <interceptor-stack name="(输入任意拦截器名字)">  //相当于打包拦截器

                                <!-- 引用拦截器 -->

             <interceptor-stackname="defaultStack"></interceptor-ref> //默认18个拦截器

    <interceptor-ref name="(与自定义拦截器名字一致才能使用)"></interceptor-ref> 

    </interceptor-stack>

    <interceptors>

    Struts2常量配置

    Struts2项目启动时加载default.properties常量文件
    struts.i18n.encoding: struts2项目中设置的编码

                                         请求:request.setCharacterEncoding("utf-8")

                                         响应: response.setContentType("text/html;charset=utf-8");

    struts.multipart.parser: struts2使用的上传组件 (默认jakarta:commons-fileUpload)

    struts.multipart.saveDir: 文件上传时缓存目录

    struts.multipart.maxSize: 文件上传文件当前请求最大值

    struts.action.extension    struts2的action访问后缀配置

    struts.devMode   是否打印对象信息

    struts.enable.DynamicMethodInvocation: 是否开启struts2的动态方法调用机制(默认关闭)

    动态方法调用机制,用来简化action的配置,可以使用一个action配置来实现多个方法的调用注意:struts2不推荐开启,因为存在一定的安全漏洞!测试代码的时候可以开启使用!

    修改(覆盖)struts常量

    在struts.xml配置文件中添加

    <constant name=” struts.i18n.encoding” value=”utf-8”></constant>

    <!-- 修改struts的UI模块 -->

             <constant name="struts.ui.theme" value="simple"></constant> //设置为简单模式把全部el表达式替代成ognl表达式

    配置全局视图(包里面,action外面)对当前包下面的所有action起作用的

    <global-results>

             <result>/succ.jsp</result>

    </global-results>

    Acation读取参数

    1:在方法内私有化需要接收的数据提供get和set的方法,相当于getParameter()方法

    private String savePath;

    public void setSavePath(String savePath) {

                       this.savePath = savePath;

    }

    2:在方法内私有化对象提供get和set方法,jsp页面数据前面必须带对象(常用)

    用户名:<input type="text" name="type.name"></br>

      密码:<input type="password" name="type.password"></br>

    3:方法实现一个ModelDriven<对象名>接口,私有化对象必须new,然后让方法等于对象

    private Type types=new Type();

    @Override

             public Type getModel() {

                       return types;   (返回私有对象)

             }

    上传图片读取

    表单的3 个必要条件

    1:<input type="file" name="attach"/>

    2:<form enctype="multipart/form-data" method="post">  //post提交 重写enctype

    在方法里写出以下私有方法接收,提供get和set方法

    private String savePath;  //文件传输的过去的地址

    public String getSavePath() {

                       return savePath;

             }

    public void setSavePath(String savePath) {

             this.savePath = savePath;

    }

    Struts.xml 配置

    <param name="savePath">F:/金山打字通/</param>  //需要复制过去的地址

    //1.接收上传的文件

    private File attach;            //<input type="file/>的name属性名称

    //2.接收文件类型

    private String attachContentType;  //名称:name属性+ContentType

    //3.接收文件名称

    private String attachFileName;  //名称:name属性+FileName

    文件上传细节配置

    <!-- 修改文件上传拦截器参数 -->

                                <interceptor-ref name="fileUpload">   //默认的不能写错

                                <!-- 修改最大文件大小参数:1M -->

                                <param name="maximumSize">1048576</param>

                                <!-- 修改允许的文件类型 -->

                                <param name="allowedTypes">image/jpeg,image/x-png,image/bmp</param>

                                </interceptor-ref>

    <!-- 必须放在后面,因为先修改了fileUpload文件上传 拦截器的参数,再进行默认拦截器-->

    下载文件

    Struts.xml中如何配置文件(下载文件全部为配置)

    <action name="down" class="gz.itcast.a_down.DownAction" method="down">

                                <!-- 配置下载视图 :stream-->

                                <result name={自定义名称}" type="(属性为下载)stream">

                                         <!-- 修改视图的参数 -->

                                         <!-- 下载的文件类型 :设置通用二进制类型-->

                                         <param name="contentType">application/octet-stream(全部格式)</param>

                                         <!-- 下载提示框 ${fileName}:读取Action中的getFileName()方法 -->

                                <param name="contentDisposition">attachment;filename=${fileName}</param>

                                         <!-- 设置下载的缓存区大小 -->

                                         <param name="bufferSize">512(不改默认1024)</param>

                                         <!-- 需要下载的文件输入流: Action中的getter方法名称 -->

                                         <param name="inputName">fileStream(getInput方法)</param>                

                                </result>

                       </action>

    Action中如何写方法

    public class DownAction extends ActionSupport{

             //private InputStream fileStream;

            

             private String fileName;

             //下载方法

             public String down(){

                       //返回下载视图

                       return "down";

             }

            

             //给struts.xml的inputName配置

             public InputStream getFileStream() throws Exception{

                       File file = new File("E:/图片/1-111119121254.jpg");

                       fileName = file.getName();

                       return new FileInputStream(file);

             }

            

             //通过getter方法把名称输出给struts.xml文件

             public String getFileName() throws Exception{

                       return URLEncoder.encode(fileName,"utf-8");   //如果图片有中文名字

             }

    }

    国际化(了解)及自定义异常

    struts2国际化

             原理

                       com.opensymphony.xwork2.interceptor.I18nInterceptor 国际化拦截器

                      

             步骤:

                       在struts.xml文件中配置国际化资源文件的路径

                       <!-- 加载国际化资源文件 -->

             <constant name="struts.custom.i18n.resources" value="i18n.message"></constant>

                       在jsp页面使用struts2标签引用国际化文件内容

    jsp页面使用: <s:text name="user"/>       

    action使用: getText("key")   (注意:前提Action继承ActionSupport)

    自定义异常

                                                                                                             包名只能用点

    <constant name="struts.custom.i18n.resources" value="cn.itcast.list.message"></constant>

    在struts.xml中“input”是报错配置

    <result name="input">/actionList.jsp</result>

    传输数据给页面

    1:使用原生的域对象进行共享                

    request,session,application

                      //得到域对象

    HttpServletRequest request = ServletActionContext.getRequest();

    HttpSession session = request.getSession();

    ServletContext application = ServletActionContext.getServletContext();

    2:使用三种Map集合共享数据

    RequestMap:重新封装了HttpServletRequest

    SessionMap: 重新封装了HttpSession

    ApplicationMap: 重新封装了ServletContext

    ActionContext类:工具类                      

                               

    //先得到ActionContext对象

    //RequestMap

    ActionContext ac = ActionContext.getContext();

    Map requestMap = (Map)ac.get("request");

    requestMap.put("r_prods", prods);

    //System.out.println(requestMap.getClass());

                      

    //SessionMap

    Map sessionMap = ac.getSession();

    sessionMap.put("s_prods", prods);

                      

    //ApplicationMap

    Map applicationMap = ac.getApplication();

    applicationMap.put("a_prods", prods);

    3:通过实现接口的方法使用三种Map集合(推荐)

    私有化3个map<String,Object>参数

    在Action类上面实现三个接口

    RequestAware,   SessionAware,     ApplicationAware

    写出get 和set方法

    public class BaseAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{

       public Map<String, Object> requestMap;

       public Map<String, Object> sessionMap;

       public Map<String, Object> applicationMap;

    值栈和ognl表达式

    值栈

    Struts2改变servlet+jsp

    Action -> 把数据保存到*值栈*  -> jsp  -> 使用struts2标签+ognl表达式

    值栈是struts2存取数据的核心

    值栈是一个对象,这个对象实现接口 ValueStack

                       实现类:OgnlValueStack

    值栈分为两个部分:

    1:对象栈(Object Stack): ArrayList集合

                                作用:存放struts2运行过程的action对象,国际化对象.....

    2:映射栈(Context (Map) Stack): HashMap集合

                                作用:存在struts2运行过程的固定的映射数据

                                存放的映射数据:

                                key               value             

                                ===============================

                                request          RequestMap对象(封装request域对象)

                                session          SessionMap对象(封装session域对象)

                                application      ApplicationMap对象(封装context域对象)

                                parameters       ParametersMap对象(封装用户参数数据)

                                attr             AttributeMap对象(封装三个Map集合)

                                                            (request : RequestMap

                                                            session: SessionMap

                                                            application: ApplicationMap)

    获取值栈:

    struts2框架在运行每个Action的方法前都会创建一个值栈对象。把这个值栈对象放入ActionContext对象中。

                       运行Action的方法 -> 创建值栈对象 -> 放入到ActionContext对象中 -> 执行代码

    ActionContext ac = ActionContext.getContext();

    ValueStack vs = ac.getValueStack();  //获取值栈

    操作值栈

                       push(Object o) :压栈

                       pop(): 推栈

                      往Action添加一个属性:提供一个getter方法

    操作映射栈

    ValueStack.getContext().put("key",Object) 往映射栈添加一个元素

                        操作requestMap

                       Map rm = (Map)ac.get("request");

                       rm.put("rm", p);

                       //2.3 往session元素(SessionMap)添加一个元素

                       Map sm = ac.getSession();

                       sm.put("sm", p);

                       //2.4 往application元素(ApplicationMap)添加一个元素

                       Map am = ac.getApplication();

                       am.put("am", p);

    ognl表达式

    ognl表达式需要借助struts标签:<s:property value="ognl表达式"/>

    取对象栈: 不带#号的ognl表达式

    查询对象栈的对象顺序:

    从栈的指定元素位置开始查询对应,直到栈底(最后一个元素)为止,把所有元素返回。

                                        

                                取某个对象: [0]   (取对象栈的第一个元素后面的元素)

                                取某个对象的属性:[0].name    (注意:查询getName()方法) 

                                name  默认就是从第一个元素开始查属性

    取映射栈: 带#号的ognl表达式

                                取映射栈的request的元素:#request.product

                                取映射栈的session的元素:#session.product

                                取映射栈的application的元素:#application.product

                                取映射栈的paraemters的元素:#parameters.product

                                取映射栈的attr的元素:

                                         #attr.request

                                         #attr.session

                                         #attr.application

    Struts标签

    Struts逻辑标签

    数据标签:

                                <s:set/>   赋值到值栈中

                                <s:property/> 从值栈获取数据

    条件判断:

                                <s:if>

                                <s:elseif>

                                <s:else>

    循环:

                                <s:iterator>  //类似迭代器

    Ui类标签

    用于简化页面的html输出

                       表单标签:

    <s:form>   

    <s:textfield/> //就是input输入框 type=”text”

    <s:password/>  //类似input输入密码type=”password”

    <s:radio/>   

    <s:checkbox/>    //存单个的多选框

    //可以存集合的多选框(以Map集合存储进去,id键,对象为值)

    <s:checkbostlist list="#request.types" name="types" listKey="key" listValue="value.name" value="curTypes"/>

    //下拉框

    <s:select list="#request.types" listKey="key" listValue="value.name"  value="curTypes"/>

    Action传输内容

    private List curTypes;

             public List getCurTypes() {

                       curTypes = new ArrayList();

                       curTypes.add(2);

                       curTypes.add(3);

                       return curTypes;

             }

             public void setCurTypes(List curTypes) {

                       this.curTypes = curTypes;

             }

            

             //查询

             public String query(){

                       Map<Integer,Types> types = new HashMap<Integer,Types>();

                       types.put(1,new Types(1,"图书类"));

                       types.put(2,new Types(2,"男装"));

                       types.put(3,new Types(3,"电器类"));

                       requestMap.put("types", types);

                      

                      

                       return "tags";

             }

    表单验证

    步骤:

    (了解)方法1:Action必须继承actionSupport类,覆盖重写validate方法,里面验证信息和页面数据一致

    方法2:配置

    把一个验证文件(Action名称-validation.xml)放在对应Action的目录下

    内容:

    <?xml version="1.0" encoding="utf-8"?>

    <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.dtd">

    <validators>

             <!-- struts2提供了一些常用的属性验证器

                       requiredstring: 必须填写字符串

                       regex: 正则表达式

                       email: 邮箱格式验证器

             -->

             <!-- field:需要验证的字段 -->

             <field name="user.name">   //页面数据

                       <!-- 属性验证器 -->

                       <field-validator type="requiredstring">

                                <!-- 错误发生时,错误提示 -->

                                <message>用户名必须填写2222</message> //input错误提示语句

                       </field-validator>

             </field>

             <field name="user.name">

                       <!-- 属性验证器 -->

                       <field-validator type="regex">

                                <param name="regexExpression">[a-zA-Z0-9]{4,16}</param> //正则

                                <!-- 错误发生时,错误提示 -->

                                <message>用户名格式有误:4-16位字母或者数字222</message>

                       </field-validator>

             </field>

            

             <field name="user.email">

                       <!-- 属性验证器 -->

                       <field-validator type="requiredstring">

                                <!-- 错误发生时,错误提示 -->

                                <message>邮箱必须填写2222</message>

                       </field-validator>

             </field>

    </validators>

    注意

    Xml配置文件的注意事项:

    1)Action名称-validation.xml对Action的所有方法生效!

    2)如果需要局部验证Action某个方法:Action名称-方法访问名-validation.xml

    注意:如果有错误,则调用addFieldError放入错误信息,struts2会自动跳转到input视图

    必须在struts.xml配置一个input的视图(否则报错)    

                       <action name="user_*" class="gz.itcast.a_validate.UserAction" method="{1}">

                                <result>/succ.jsp</result>

                                *<result name="input">/user.jsp</result>*

                       </action>

    Jsp:页面显示错误信息

                       <s:fielderror></s:fielderror>

    Hibernate框架

    Orm 思想(对象关系映射)

    关系领域(关系型数据)   对象领域(java)    

                 一张表               一个类

                 一个字段             类的一个属性

                一条记录              一个类的对象

    启动步骤

    1:导包

    1)hibernate的lib里面的required目录的10个jar

    2)对应数据库的驱动程序*

     

    2:编写hibernate的启动配置文件(包括数据库连接信息)

    在src目录建立一个hibernate.cfg.xml

    <?xml version="1.0" encoding="utf-8"?>

    <!DOCTYPE hibernate-configuration PUBLIC

             "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

             "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

    <hibernate-configuration>

    <session-factory>

    <!-- 第一部分:数据库连接信息 -->

    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/day31?useUnicode=true&amp;characterEncoding=utf-8</property>

    <property name="hibernate.connection.username">root</property>

    <property name="hibernate.connection.password">root</property>

                      

    <!-- 2.第二部分:hibernate环境参数配置 -->

    <!-- 数据库方言 : hiberbate最终转换成什么数据库的sql语句-->

    <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>

            

    <!-- 3.第三部分:映射文件信息 -->

    <mapping resource="gz/itcast/entity/Student.hbm.xml"/>  //类似struts2配置

            

    </session-factory>

    </hibernate-configuration>

     

    3:编写实体类javabean(必须有无参构造)

     

    4:创建关系型映射文件(通常把 对象.hbm.xml文件放在和实体类同目录)

    <?xml version="1.0"?>

    <!DOCTYPE hibernate-mapping PUBLIC

             "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

             "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

    <hibernate-mapping>  //底下如果单类名就要加个package="(包名)"           表名

                       <class name="gz.itcast.entity.Student(完整类名,也可以单类名)" table="t_student">

                                <!-- 主键配置 -->

                                <id name="id" column="sid">

                                         <!-- 主键维护策略 :

                                                   assigned:程序分配id

                                         -->

                                         <generator class="assigned"></generator> 

                                </id>

                                <property name="name" column="sname"></property>

                                <property name="age" column="sage"></property>

                       </class>

    </hibernate-mapping>   

                                                                                                                   

     

    5:代码部分(主要获取对象) 可以写一个hibernateUtil.java工具包

    //1.获取Session对象

                       //1.1 加载hibernate.cfg.xml文件

                       Configuration config = new Configuration().configure();

                      

                       //1.2 创建一个服务注册器(4.0新特性)

    StandardServiceRegistry serviceRegistry =

                                         new StandardServiceRegistryBuilder().applySettings(config.getProperties()).build();

                      

                       //1.3 创建SessionFactory对象

                       SessionFactory sessionFactory =config.buildSessionFactory(serviceRegistry);

                      

                       //1.4 获取一个Session

                       Session session = sessionFactory.openSession();

                      

                       //注意:hibernate强制使用事务

                       //开启事务

                       session.getTransaction().begin();

                      

                       执行操作xxxxx

                      

                       //提交事务

                       session.getTransaction().commit();

                       //发生错误回滚事务 try /catch

                       session.getTransaction().rollback();

                       注意关闭资源

                       session.close();

                       sessionFactory.close();

    hibernate.cfg.xml配置

    <hibernate-configuration>  

                       <session-factory>  -- 连接一个数据库的项目信息

                                第一部分: 连接参数

                                <property name="hibernate.connection.driver_class"></property>

                                <property name="hibernate.connection.url"></property>

                                <property name="hibernate.connection.username"></property>

                                <property name="hibernate.connection.password"></property>        

                                第二部分:hibernate环境参数

    hibernate.dialect: 数据库方言。为了hibernate适应不同的数据库,方便生成不同数据库                        例如:sql语句核心包: org.hibernate.dialect.MySQL5InnoDBDialect

                                <property name="(写入底下语句)"></property>

                                hibernate.show_sql: 是否显示执行sql语句(方便测试而已) //值:true

                                hibernate.format_sql: 是否格式化sql语句(方便测试而已) //值:true

                                hbm2ddl.auto: 是否需要hibernate维护数据库。默认不维护

                                             值:create:  每次会自动创建表结构

                                             值:  update: 每次会更新(先对比)表结构

                                          

                                第三部分:对象关系映射文件

                                <mapping resource="(hibernate.hbm.xml 完整包名)"/>

    *.hbm.xml解读配置(核心)

    第一种:配置文件注入

    <hibernate-mapping>

                       package: 类所在的包

                       <class>   -- 代表需要映射一个类

                                name:  代表映射类名(如果没有配置package,必须写全名)

                                table: 代表需要映射到的表名

                                <id name="(实体ID)" column="(对应表单ID)">  代表主键配置

                                         <generator class="assigned">  主键维护策略

    <property  name=”属性名称” column=”字段名称” length=”字段长度”>  代表普通属性映射

    第二种:注解注入(常用)

    Hibernate注解

    概念:

    hibernate注解是代替xml配置的另一个参数配置方案

    步骤:

    1:在实体类指定位置上指定注解

    2:在hibernate.cfg.xml加入映射类 <mapping class="gz.itcast.b_annotation.Product(实体类)"/>

    常见注解:

    @Entity          声明当前类是一个映射类  (如果需要映射的类必须加)

             @Table(name="t_product", indexes={@Index(columnList="NAME", name="IDX_USER_NAME")}(增加索引值在查询时会比较快))    声明表名 (可以省略不写,表与实体属性名一致)

    @Table(name="OA_ID_USER(表名)", indexes={@Index(columnList="NAME", name="IDX_USER_NAME")})

             @Id     声明主键

    +@GeneratedValue(strategy=GenerationType.AUTO)(可以选择谁负责增长AUTO代表自动选择)    声明注解维护策略    默认数据库生成id值

    @Column(name="p_id",length=”指定字段长度”)    声明字段名   

             @OneToMany(cascade={CascadeType.ALL},mappedBy="user")  一对多

            

    @ManyToOne(fetch=FetchType.LAZY(是否延迟加载,必须填), targetEntity=User.class(关联的实现化类))  多对一

             +@JoinColumn(name="MODIFIER(取外键列的列名)", referencedColumnName="USER_ID(引用主表的那个主键列名)", foreignKey=@ForeignKey(name="FK_DEPT_MODIFIER")(更改外键约束名,不写的话自动生成))

             @JoinColumn(name="MODIFIER", referencedColumnName="USER_ID",

             foreignKey=@ForeignKey(name="FK_DEPT_MODIFIER"))

    @ManyToMany(fetch=FetchType.LAZY(懒加载), targetEntity=Role.class(需要引用的实习化类), mappedBy="users(中间表由角色来维护,没加代表自己维护)")  多对多

       +@JoinTable(name="OA_ID_USER_ROLE(多对多需要生成外表,外表的名字)", joinColumns=@JoinColumn(name="ROLE_ID(没有加mappedBy的列名)", referencedColumnName="ID(需要关联的主键id)"),                                                 inverseJoinColumns=@JoinColumn(name="USER_ID(加了mappedBy的列名)", referencedColumnName="USER_ID(需要关联的主键id)"))

     

    @JoinTable(name="OA_ID_USER_ROLE", joinColumns=@JoinColumn(name="ROLE_ID", referencedColumnName="ID"),                inverseJoinColumns=@JoinColumn(name="USER_ID", referencedColumnName="USER_ID"))

                     

    @OneToOne  一对一

            

             @Temporal(TemporalType.TIMESTAMP)指定数据库为时间格式,TIMESTAMP(年月日时分秒)

    Session对象基本CRUD操作

    1:保存save

    session.save(放入存储的对象)

    2:修改数据get拿set直接改

    Product p = (Product)session.get(Product.class, 2);   //对象.class和对应ID号

    修改数据

    p.setName("iphone6s");

    3:查询get数据

    Product p = (Product)session.get(Product.class, 1);   //get一调用就执行

    Product p = (Product)session.load(Product.class, 1);  //调用不执行,需要才执行

    Hql语句

    List<Product> list = session.createQuery("from Product p").list();

                       for (Product product : list) {

                                System.out.println(product);}

    4:删除delete

    Product p = new Product();

             p.setId(1);

             session.delete(p);

            

    方式二:(推荐)

    Product p = (Product)session.get(Product.class, 1);

    if(p!=null){

             session.delete(p);

             }

    主键维护策略

    <generator class="assigned"></generator>

    开发者:

                       assigned    开发者自觉给

             数据库:(类型必须是int或Integer)

                       identity  利用自增长策略,只能用在mysql或者sql server

                       sequence  利用序列增长策略,只能在oracle或者db2

                       *native (推荐)自动根据具体的数据库增长策略,选择最优的一个

             hibernate:

                       *increment:hibernate的自增长策略   (每次先查表的最大id值,然后+1)(int)

                       uuid:  hibernate提供的uuid算法策略   (String)

    hibernate.hbm.xml映射不同类型

             type="integer"

                                hibernate类型         java类型      

             *整数        int/integer       java.lang.Integer

             *小数         double         java.lang.Double            

             *字符                   string         java.lang.String

             *日期                   date          java.util.Date

             字符文件       text          java.lang.String

             字节文件      binary                 byte[]

    集合映射

    Set集合映射

    <set name="实体类set名" table="对应表名">

                                <!-- 外键 -->

                                <key column="uid"></key> //外键的id

                                <!-- 集合里面元素的字段 -->

                                <element column="address" type="string"></element> //string小写

                       </set>

    List集合映射

    <list name="实体类set名" table="对应表名">

                                <!-- 外键 -->

                                <key column="uid"></key>

                                <!-- 排序索引自动 -->

                                <index column="任意名"></index>

                                <element column="任意名" type="string"></element>

                       </list>

    Map集合映射

    <map name="实体类set名" table="对应表名">

                                <!-- 外键 -->

                                <key column="uid"></key>

                                <!-- map的key字段 key值,map主键 -->

                                <map-key type="string" column="任意名"></map-key>

                                <!-- map的value字段 -->

                                <element column="任意名" type="string"></element>

                       </map>

    对象关系映射

    一对多单向

    例子

    对象:这个对象有其他对象信息        这个没有

                       class User{                class Address{

                                int id;                                 int id;

                                String name;                 String name;

                                int age;                String zipcode;

                                *Set<Address>*                  String phone;

                                                                      String address;

                       }       

    Hibernate.hbm.xml配置映射

             <!-- set对象集合(一对多) -->

                       <set name="实体类set集合名字">

                                <!-- 外键 -->

                                <key column="uid"></key>

                                <!-- set集合元素:Address对象 -->

    <one-to-many class="gz.itcast.c_one2many_single.Address(完整全名)" />//一对多关键语句

                       </set>

    级联映射  在set里加个cascade="all " 全部自动更新

    <set name="实体类set集合名字" cascade="all ">

    save-update:  当保存/更新会员(User)的数据时,同时保存/更新起关联的收货地址

    delete : 当删除会员(User)的数据时,同时删除起关联的收货地址(Address)对象

    all: save-update + delete

    多对一单向

    对象: 这没有外面实体信息           关联了外面实体信息

                       class User{                  class Address{

                                int id;                                  int id;

                                String name;               String name;

                                int age;                 String zipcode;

                                                                  String phone;

                                                                       String address;

                                                                       *User user;*  

                       }

    Hibernate.hbm.xml配置映射

    <many-to-one name="实体名user" class="gz.itcast.many2one_single.User(完整包名)"

                                column="uid(另个实体id值)" cascade="all" (自动)></many-to-one>

    一对多及多对多双向

    一对多(多对一)双向

                       <!-- 一对多集合映射 -->

                       <set name="(set实体名) " cascade="all" inverse =”true”>

                                <!-- 外键 -->

                                <key column="(外键字段)"></key>

                       <one-to-many class="gz.itcast.a_many2one_double.Address(对多的对象)"/>

                       </set>

                       <!-- 多对一配置

                                column: 值和一对多的key保持一致!!

                        -->

                       <many-to-one name="user(一对多的对象)"

                                         class="gz.itcast.a_many2one_double.User(对一的对象)"

                                         column="uid(一对多的Key值)"

                                         cascade="all"/>

    多对多双向(相当于重新建立一个关系表)

    inverse: 是否需要反转关系的维护权

                       false: 不反转,由当前方维护

                       true:需要反转,由对方维护

             hibernate在一对多的关心中,默认由一方维护(inserse="false"),为了提高效率(节省了update语句),可以把一方的insevse设置为true,把维护权给多方。   

    Student

    <set name="(set实体名) " table="student_teacher(建立的关系表)" cascade="all" inverse="true">

                                <!-- 当前方在关系表的外键 -->

                                <key column="sid(当前表首字+id,关系表里的字段)"></key>

                                <!-- set元素

                                         class: set集合的元素的类型

                                         column: set元素的表在关系表的外键

                                 -->

    <many-to-many class="gz.itcast.b_many2many_double.Teacher(关联的表)" column="tid(关联表的key值)"></many-to-many>

                       </set>

    Teacher

    <set name="(set实体名)" table="(关系表一致)">

                                <key column="tid(关系表里的id字段)"></key>

    <many-to-many class="gz.itcast.b_many2many_double.Student(关联的表)" column="sid(关联表的key值)"></many-to-many>

                       </set>

    一对一双向

                       <!-- 一对一的主键关联配置:一对一配置

                                constrained: 是否把主键设置为外键

                                         false:否

                                         true: 是

                        -->

    例如:一人对一身份证

    <one-to-one name="idcard"

                                class="gz.itcast.c_one2one_double.IdCard"

                                cascade="all"/>

                       <!-- 一对一的主键关联配置:一对一配置

                                constrained: 是否把主键设置为外键

                                         false:否

                                         true: 是

                        -->

                       <one-to-one

                          name="person"

                          class="gz.itcast.c_one2one_double.Person"

                          constrained="true"></one-to-one>

    hibernate查询(hql语句)

    全表查询返回list集合      from (对象名)

    指定字段查询 默认情况下,返回一个List<Object[]>需要遍历两次才能拿数据,可以封装成List<Employee>,在Employee里有参构造(有参的值写需要返回封装的对象属性)

    select e.(对象属性),e.(对象属性) from (对象名) e(自定义别名)

    条件查询返回list

    from (对象名) e(自定义别名) where e.(对象属性)=? and e.(对象属性)=?

    设置属性?

    q.setParameter(0, "李_");

    q.setParameter(1, 6500.0);

    from (对象名) e(自定义别名) where e.(对象属性) like ?         //like模糊查询

    q.setParameter(0, "%李%");   //%表示省略前后

    查询排序返回list    排序: order by    asc: 升序  desc : 降序

    from (对象名) e(自定义别名) order by e.(对象属性) asc   

    聚合查询返回一个对象(max,min avg,count...

    select max(e.对象属性) from (对象名) e(自定义别名)

    统计查询可以设置约束条件(变成分页查询)返回int

    select count(e) from (对象名) e(自定义别名)

    设置分页

                                q.setFirstResult(0);    //起始位置

                                q.setMaxResults(3);   //查询条数

     

    分组查询 (group by)

    select e.(对象属性1),count(*) from (对象名) e(自定义对象别名) where e.(对象属性1) is not null and e.(对象属性1)<>'' group by e.(对象属性1)

    分组后筛选(having)

    select e.(对象属性1),count(*) from (对象名) e(自定义对象别名) where e.(对象属性1) is not null and e.(对象属性1)<>'' group by e.(对象属性1) having count(*)>2(条件)

    多表查询  内连接(inner join)  外右连接(right outer join)

    (内连接)select e.name,e.dept.deptName from (对象名) e(自定义对象别名) inner join e.dept

    (外右连接) select e.dept.deptName,e.name from (对象名) e(自定义对象别名) right outer join e.dept

    原生sql查询

             SQLQuery sq = session.createSQLQuery("select * from employee");  //原来sql语句表名

                       //封装成什么对象

                       sq.addEntity(Employee.class);

                      

                       List<Employee> list = sq.list();

             注意:如果该查询需要比较高的性能要求,可以使用sql查询

    细节

    一级缓存

    概念

    一级缓存,也称之为Session级别的缓存,在Session对象内部设计的一个缓存,只能在Session范围内使用。

    默认情况下,一级缓存是打开和使用,我们不能关闭它。

    操作一级缓存

    1:session.flush()  同步一级缓存的数据 (经常跟第3一起用,刷完内存里东西,然后删除内存对象)

    2:session.evict(obj)  从一级缓存清除某个对象

    3:session.clear()  清空一级缓存的所有对象

    Hibernate对象状态

    临时状态

    例如: Student stu=new Student()   新new对象

    不在一级缓存中

    数据库找不到对应记录

    持久对象

    例如:Admin admin = session.get(Admin.class, 1); 从session中直接取出来的数据

    在一级对象中

    数据库找得到对应记录

    游离对象

    例如:Student s = (Student) session.get(Student.class, 1); // s:持久对象  session.evict(s);//删除一级缓存里的数据

    不在一级缓存中

    游离对象的数据和数据库的数据保持一致,但是不能用于任何修改操作

    删除对象

    例如:Student s = (Student) session.get(Student.class, 3); // s:持久对象 session.delete(s);

    不在一级缓存中

    数据库数据不一致

    延迟加载

    get和load的区别

    get

    (1)Get方法执行后立即查询数据库数据,返回数据库数据(真实对象)

    (2)get方法如果查询数据库没有对应数据时,返回null

    Load

    (1)     load方法执行之后,没有查询数据库(返回的是一个代理对象),而是在使用对象的属性数据

    (2)     load方法如果查询数据库没有对应数据时,返回ObjectNotFound异常

    延迟加载

    <!-- lazy: 延迟加载。默认情况下就是延迟加载 -->

                       <set name="addresses" cascade="all" lazy="true">

                                <key column="sid"></key>

                                <one-to-many class="gz.itcast.d_lazy.Address"/>

                       </set>

    二级缓存

    步骤1:导入二级缓存的jar

    ehcache-core-2.4.3.jar

    hibernate-ehcache-4.3.8.Final.jar

    slf4j-api-1.7.2.jar

    slf4j-log4j12-1.7.2.jar

    步骤2:配置开启二级缓存(hibernate.cfg.xml).

    <!-- 启用二级缓存 -->

             <property name="hibernate.cache.use_second_level_cache">true</property>

             <!-- 引入二级缓存插件(提供者) -->

             <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

             <mapping xxxx/> //需要引用的二级缓存必须放在mapping后面

             <!-- 把指定类使用二级缓存 -->(可以使用注解在实体类上写入@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)

    <class-cache usage="read-write" region="itCache" class="gz.itcast.d_lazy.Address(需要二级缓存的实体)"/>

    步骤3:提供配置文件.

    src/ehcache.xml

    配置查询缓存(效果不大)

    -- 提高查询速度.(二级缓存的基础之上).

          缓存的是查询语句.

       -- 配置开启查询缓存(hibernate.cfg.xml).

          <!-- 配置开启查询缓存 -->

          <property name="hibernate.cache.use_query_cache">true</property>

       -- 指定哪些查询语句做缓存.

          getSession().createQuery(hql).setCacheable(true);

    连接池插件(c3p0)

    1: 导入c3p0插件包 optional\ehcache\(hibernate的lib包中)

             c3p0-0.9.2.1.jar

             hibernate-c3p0-4.3.8.Final.jar

             mchange-commons-java-0.2.3.4.jar

    2: 在hibernate.cfg.xml配置

    <!-- 使用c3p0插件 -->

             <property name="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>

             <property name="connection.url">jdbc:mysql://localhost:3306/day34?useUnicode=true&amp;characterEncoding=utf-8</property>

             <property name="connection.driver_class">com.mysql.jdbc.Driver</property>

             <property name="connection.username">root</property>

             <property name="connection.password">root</property>

             <!-- 初始连接数 -->

             <property name="c3p0.min_size">5</property>

             <!-- 最大连接数 -->

             <property name="c3p0.max_size">20</property>

             <!-- 等待时间 -->

             <property name="c3p0.timeout">3000</property>

    Spring框架

    概念

    spring是一个JavaEE应用程序的一站式(full-stack)框架,是一个轻量级的*IOC*和*AOP*的容器框架,主要用于解决应用中javabean对象的生命周期管理和对象之间的依赖关系问题,还可以整合其他如struts2,hibernate等框架,简化这些框架的使用。

    Spring的         IOC

    设计一个beanFactory(实例工厂)解决项目管理问题

    Spring IOC开发步骤

    1:导入jar包

    commons-logging-1.1.1.jar

                       spring-beans-4.2.0.RELEASE.jar

                       spring-context-4.2.0.RELEASE.jar

                       spring-core-4.2.0.RELEASE.jar

                       spring-expression-4.2.0.RELEASE.jar

    2:编写一个类

    public class UserDao {

             public void save(){

                       System.out.println("userDao.save()....");

             }

    }

    3:在src目录里建立一个applicationContext.xml  (或者beans.xml或者sprirng.xml)

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"

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

    <!-- 使用springIOC工厂创建一个对象 -->

              <bean id="userDao" class="gz.itcast.a_hello.UserDao"></bean>

    </beans>

    4:获取对象

    //使用类路径方式读取spring的xml文件

                       ApplicationContext ac =

                      new ClassPathXmlApplicationContext("/gz/itcast/a_hello/applicationContext.xml");

                      

                       //2.从springIOC工厂中获取一个对象

                       UserDao userDao = (UserDao)ac.getBean("userDao");

    等同于UserDao user =new UserDao

    SpringIOC的简介

    springIOC,主要解决的是对象管理问题,以及对象之间的依赖关系问题!!!!

             IOC, Inversion Of Control 控制反转    (解决对象创建问题)

                       没有IOC:new Student() 直接获取一个对象 依赖性太强,耦合性太大

                       有IOC: getBean("xxx")  把对象的控制器托管给BeanFactory(springIOC)

             DI,dependency injection 依赖注入     (解决对象之间的依赖关系问题)

                       没有DI: IUserDao usrDao = new UserDao()

                       有DI: IUserDao userDao;                         

                                public void setUserDao(IUserDao userDao){

                                         this.userDao = userDao;

                                }

    对象创建问题(IOC)

    使用无参构造方法创建对象

             <bean id="userDao1" class="gz.itcast.a_hello.UserDao"></bean>

             注意:

                       在给对象提供了有参的构造方法的同时,不要忘记补上一个无参构造方法

    使用有参构造方法创建对象

                        <!-- 使用有参构造方法创建对象 -->

                <bean id="userDao" class="gz.itcast.b_bean.UserDao">

                            <constructor-arg index="0" value="狗娃"></constructor-arg>

                            <constructor-arg index="1" value="20"></constructor-arg>

                </bean>    

    使用工厂类创建对象

                       成员方法

                                <!-- 使用工厂类的成员方法来创建对象 -->

                <!-- 1.1 创建工厂类对象 -->

                <bean id="factory" class="gz.itcast.b_bean.ObjectFactory"></bean>

                <!-- 1.2 调用工厂类的成员方法 -->

                <bean id="userDao2" factory-bean="factory" factory-method="getInstance"></bean>

    //工厂类

    public class ObjectFactory {

             //成员方法

             public UserDao getInstance(){

                       return new UserDao("张三",22);

             }

    }

                       静态方法

     <!-- 使用工厂类的静态方法来创建对象 -->

    <bean id="userDao3" class="gz.itcast.b_bean.ObjectFactory" factory-method="getStaitcInstance"></bean>

             //工厂类

    public class ObjectFactory {

    //静态方法

             public static UserDao getStaitcInstance(){

                       return new UserDao("李四",24);

             }

    }

    单例和多例问题

    scope

             single: 单例

             prototype:多例

              <bean id="userDao4" class="gz.itcast.b_bean.UserDao" scope="prototype"></bean>

    是否延迟创建对象

    lazy-init  是否需要延迟创建对象,默认fales,改成true就是延迟创建

    default-lazy-init="true": 设置全局的延迟创建bean

    注意:lazy-init只对单例(singleton)起作用

    依赖注入

    1:构造方法注入

    <bean id="user" class="gz.itcast.c_di.User">

                     <constructor-arg index="0" value="狗娃"></constructor-arg>

    </bean>

    构建有参构造

    public User(String name){

                       System.out.println("name="+name);

             }

    2:使用set方法注入数据(推荐)

    类里面提供set方法

    <bean id="user" class="gz.itcast.c_di.User">

                     <!-- name: set方法名称 例如setAge()的set方法名称:age-->

                     <property name="age" value="20"></property>

    </bean>

    注入不同的数据类型:

                       *String类型:<value>

                       *int类型: <value>

                       *double类型: <value>

                       数组类型:

                                <array>

                                        <value>广州天河</value>

                                        <value>广州番禺</value>

                                        <value>广州越秀</value>

                              </array>

                       List类型:

                                <list>

                                        <value>AAA</value>

                                        <value>BBB</value>

                                        <value>CCC</value>

                              </list>

                       Map类型:

                                <map>

                                        <entry key="key1" value="value1"/>

                                        <entry key="key2" value="value2"/>

                                        <entry key="key3" value="value3"/>

                              </map>

                       *Properties类型:

                                <props>

                                        <prop key="pro1">value1</prop>

                                        <prop key="pro2">value2</prop>

                                        <prop key="pro3">value3</prop>

                              </props>                  

                       *引用类型:

                                <property name="addr" ref="addr"></property>

    SpringIOC注解(重点)

    1:导入spring的aop的jar

                       spring-aop-4.2.0.RELEASE.jar

    2:applicationContext.xml引入context名称空间

    <?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:context="http://www.springframework.org/schema/context"

        xsi:schemaLocation="

                 http://www.springframework.org/schema/beans

            http://www.springframework.org/schema/beans/spring-beans.xsd

            http://www.springframework.org/schema/context

            http://www.springframework.org/schema/context/spring-context.xsd

            ">

    3:使用context的标签去扫描注解目录

    <context:component-scan base-package="gz.itcast.d_annotation"></context:component-scan>

    4:注解用法

    //@Component("user")等价于 <bean id="user" class="gz..xxxx.User"/>

    @Controller("user")

    public class User {

    @Resource(name="addr")  //name输入对象@Component的值

    private Address addr;

    // 类似于<property name="addr" ref="addr"/>,不同于property注入的是,@Resource使用的是 暴力反射直接注入属性

    <!-- 开启annotation实现字段注入  @Resource -->

         <context:annotation-config/>

         @Resource // byType

         @Resource(name="jobDao") // byName

         private JobDao jobDao;

    常用的注解:

             @Component("xxx")   在springIOC工厂中创建一个对象(底下3个效果等同,为了区分)

                       @Resource("xxx")  在当前对象中注入springIOC工厂中的一个对象

            

                       @Repository   作用同@Component; 在持久层使用

                       @Service      作用同@Component; 在业务逻辑层使用

                       @Controller    作用同@Component; 在控制层使用

    SpringAop

    springAOP概念

    AOP,Aspect Object Programing 面向切面编程,主要是用于分离核心业务代码 和 服务代码(重复代码)

    三种代理方式

    1:静态代理 (关键:手写代理类,要求:必须实现接口)

    写一个方法类接口

    public interface IUserDao {

             public void save();

             public void update();

    }

    public class UserDaoProxy implements IUserDao{

             private IUserDao userDao;

             //绑定目标对象

             public void bind(IUserDao userDao){

                       this.userDao = userDao;

             }

             @Override

             public void save() {

                       System.out.println("开启事务");   //代理类实现接口后可以修改属性

                       //执行核心业务:

                       userDao.save();

                       System.out.println("提交事务");

             }

             @Override

             public void update() {

                       System.out.println("开启事务");

                       //执行核心业务:

                       userDao.update();

                       System.out.println("提交事务");

             }

    }

    2:jdk动态代理

    //可以生成任意对象的代理类对象的工具

    public class ProxyFactory {

             private Object target;

             //绑定被代理对象

             public void bind(Object target){

                       this.target = target;

             }

            

             //生成一个被代理对象的代理类对象

             public Object getProxyInstance(){

                       return Proxy.newProxyInstance(

                                         ProxyFactory.class.getClassLoader(),  // 指定类加载器,随意指定   

                                         target.getClass().getInterfaces(), // 指定代理类实现的接口(通常和被代理对象相同的接口)

                                         new InvocationHandler() { //new一个内部类,指定代理后的处理程序

             @Override      //生成的代理对象          //当前方法的参数

             public Object invoke(Object proxy, Method method, Object[] args) // invoke()执行处理程序

                                                                     throws Throwable {

                                                            System.out.println("当前执行的方法:"+method.getName());

                                                            //目标: 在每个业务方式执行事务代理

                                                            System.out.println("开启事务");

                                                            //执行核心业务方法

                                                            Object result = method.invoke(target, args);

                                                            System.out.println("提交事务");

                                                            return result;

                                                   }

                                         }

                                         );  // 指定代理后的处理程序 (代理后要怎么做???);

             }

    }

    3: CGLIB子类代理方式

    关键:不需要实现接口,直接生成目标对象的子类代理

             步骤:

             导入cglib的jar包

                       spring-core包

                       spring-aop包

             编写生成子类对象的程序

    //生成子类代理对象的工厂类

    public class ProxyFactoryCGLIB implements MethodInterceptor{

             private Object target;

             //绑定目标对象

             public void bind(Object target){

                       this.target = target;

             }

             //生成目标的子类代理对象

             public Object getProxyInstance(){

                       //1.创建工具类

                       Enhancer en = new Enhancer();

                       //2.指定父类

                       en.setSuperclass(target.getClass());

                       //3.指定回调函数(底层实现需要类加载器)

                       en.setCallback(this);

                       //4.创建子类代理对象

                       return en.create();

             }

             /**

              * proxy: 子类代理对象

              * method: 当前调用的方法

              * value: 当前调用的方法的参数

              * mp: 当前方法的代理对象

              */

             @Override

             public Object intercept(Object proxy, Method method, Object[] value,

                                MethodProxy mp) throws Throwable {

                       System.out.println("开启事务");

                      

                       //调用核心业务:

                       Object result = method.invoke(target, value);

                      

                       System.out.println("提交事务");

                       return result;

             }

    }

    SpringAOP实现

    SpringAOP底层使用CGLIB子类代理方式实现

    SpringAOP关键词

             连接点(jointPoint):需要关注的核心业务方法( save()  update() )

             切入点(pointcut):需要切入服务代码的业务方法 ( save())

                       注意:

                       1)切入点一定是连接点

                       2)连接点不一定是切入点

             通知(advice):

                       需要在切入点上面执行的代码逻辑

             *切面(aspect/advisor):

                       切入点+通知   :  在某些方法(切入点)执行通知代码

    导入jar

                       spring-core

                       spring-aop

    1:编写目标对象(专注核心业务)

    public class UserDao {

                       public void save(){

                                System.out.println("保存数据");

                       }

                       public void update(){

                                System.out.println("更新数据");

                       }

    }

    2:编写切面类,里面写不同类型的通知

    public class MyAspect {

             //定义通知

             /**

              * 前置通知(在业务方法前面切入)

              * 后置通知(在业务方法后面切入)

              * 环绕通知(在业务方法前后切入))

              */

             public void before(){

                       System.out.println("执行前置通知");

             }         

    }

    3:配置切面

           <!-- 创建目标对象 -->

         <bean id="userDaoID" class="gz.itcast.dao.UserDao"></bean>

         <!-- 创建切面对象-->

         <bean id="myAspect" class="gz.itcast.dao.MyAspect"></bean>

         <!-- 定义切面配置 -->

         <aop:config>

                    <!-- 定义一个切面 -->

                    <aop:aspect ref="myAspect(切面类id)">

                           <!-- 通知 -->

                                    <!-- 前置通知 -->

                             <!-- 切入点 -->

                           <aop:pointcut id="myptID(自定义ID)" expression="execution(*(通配方法修饰符,方法返回值) gz.itcast.dao.UserDao.*(通配任意方法名)(..)(两个点省略全部参数))" />

                                    <!-- 切面类中的方法名称 -->

                    <aop:before method="before(插入的方法)" pointcut-ref="myptID(写入切面ID)"/>

                    </aop:aspect>

         </aop:config>

    Spring整合hibernate事务

    <!-- 创建一个spring提供Hibernate的事务管理器 : 用于管理每次操作的事务代码-->

             <bean id="hbmTxID" class="org.springframework.orm.hibernate4.HibernateTransactionManager">

                       <!-- 必须注入SessionFactory -->

                       <property name="sessionFactory" ref="sfID"/>

             </bean>

            

             <!-- 事务通知 : 环绕通知-->

             <!--

                      id: 事务通知的标记

                       transaction-manager: 事务管理器

              -->

             <tx:advice id="txID" transaction-manager="hbmTxID">

                       <!-- 事务属性 -->

                       <tx:attributes>

                                <!-- propagation: 事务传播属性

                                         REQUIRED: 如果上一个方法有事务,则加入上个方法的事务,如果没有,则新建一个事务。 通常更新方法设置为这个属性

                                         SUPPORTS:如果上个方法有事务,则加入事务,如果没有,则不加入事务。通常查询方法设置这个属性

                                 -->

                       <tx:method name="set*" read-only="true"/> : 代表没开启事务,只能做查询.

               <tx:method name="set*" read-only="false"/> : 代表开启了事务,CURD都可以做.

                                <tx:method name="save" propagation=" SUPPORTS "/>//可以指定方法

                                <tx:method name="*" propagation=" REQUIRED "/>//通配全部方法

                       </tx:attributes>

             </tx:advice>

       <!-- 配置切面 -->

       <aop:config>

                   <!-- 切入点 -->

                   <aop:pointcut id="myptID" expression="execution(* gz.itcast.dao.UserDao.save(..))" />

                   <!-- 切面 -->

                   <aop:advisor advice-ref="txID" pointcut-ref="myptID"/>

       </aop:config>   

    注意事项:

    1:如果使用了spring的事务管理,则在Dao中自行获取Session时,必须使用getCurrentSession()方法

    2:也可以是spring提供的HibernateTemplate工具类模板

    在Dao中写用private HibernateTemplate ht;替换private SessionFactory sf;

    <bean id="hbmTempID" class="org.springframework.orm.hibernate4.HibernateTemplate">

                       <property name="sessionFactory" ref="sfID"/>

             </bean>

                       常见方法:

                       ht.save()

                       ht.update()

                       ht.get()

                       ht.find("hql",Object... value); 相当于createQuery(“hql”).setParameter(0,value)

                       ht.execute();   使用回session对象

    (重点)步骤

    1.事务管理器: HibernateTarnsactinManager

    2.通知: tx:advice

    3.切入点: point-cut

    4.切面: <advisor advice-ref="通知" pointcur-ref="切入点"/>

    String整合Struts2

    在web.xml启动struts2和spring容器

    <!-- 启动struts2 -->

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

            

    <!-- 启动spring容器 :ContextLoaderListener用于启动spring的容器-->//相当于监视器

    <listener>

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

    </listener>

    关键: 创建struts2中使用到的Action对象

    <?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:context="http://www.springframework.org/schema/context"

        xsi:schemaLocation="

                 http://www.springframework.org/schema/beans

            http://www.springframework.org/schema/beans/spring-beans.xsd

            http://www.springframework.org/schema/context

            http://www.springframework.org/schema/context/spring-context.xsd

            ">

             <!-- 创建struts2的Action对象

                       scope="prototype": action必须是多例的

              -->

    <bean id="userActionID(两边要一致)" class="gz.itcast.action.UserAction" scope="prototype">

                       <property name="userService" ref="userServiceID"/>

             </bean>  

    </beans>

    在struts.xml文件引用spring容器的对象

    <package name="user" namespace="/" extends="struts-default">

                       <action name="user_*" class=" userActionID(两边要一致)" method="{1}">

                                <result>/succ.jsp</result>

                       </action>

    </package>

    Spring记录日志 

    第一种

    1:写一个类与数据库对应值一致:

    2:写一个util工具类,记录进入用户的操作。

    //系统日志工具类

    public class LogUtil {

             //注入日志业务类

             private ISystemlogService systemlogService;

             public void setSystemlogService(ISystemlogService systemlogService) {

                       this.systemlogService = systemlogService;

             }

             //写日志

             public void writeLog(JoinPoint jp){ //JoinPoint:连接点

                       Object target = jp.getTarget();//目标对象

                       String calledClassName = target.getClass().getName();//目标类的类名

                       String calledMethodName = jp.getSignature().getName();//调用的方法名

                       String func = calledClassName+":"+calledMethodName;//操作名称

                      

                       if(target instanceof ISystemlogService){//遇到日志业务,则退出

                                return;

                       }

                       Systemlog log = new Systemlog(); //创建记录对象

                      //操作者:当前登录的用户

                       Employee operator = (Employee)ActionContext.getContext().getSession().get("loginInfo");

                      

                       log.setOperator(operator);

                       log.setOptTime(new Date());          

                       log.setFunc(func);

                       //获取ip

                       String ip = ServletActionContext.getRequest().getRemoteHost();

                       log.setIp(ip);

                       systemlogService.save(log); //调用service保存方法

             }

    }

    3:spring的aop配置

    <!— 需要插入的类配置 -->

              <bean id="logUtil" class="gz.itcast.crm.util.LogUtil">

                     <property name="systemlogService" ref="systemlogService"/>

              </bean>

    <!-- 系统日志切面 -->

              <aop:config>

                     <aop:aspect ref="logUtil">

                              <!-- 切入点 -->

                              <aop:pointcut id="logpt" expression="execution(* gz.itcast.crm.service.impl.*.*(..))" />

                              <!-- 通知 -->

                              <aop:after method="writeLog" pointcut-ref="logpt"/>

                     </aop:aspect>

              </aop:config>

    第二种

    aop日志切面.

       -- 记录业务层方法执行的速度(效率).

       -- 记录业务层方法的异常信息.

        commons-logging-xxx.jar: 只是在控制台输出日志信息.

        private Log logger = LogFactory.getLog(LogAdvice.class);

    提供日志文件来记录日志.

    log4j框架:

         logging for java : apache组织.

         log4j-1.2.17.jar

         /** 定义日志记录器对象 */

         private Logger logger = Logger.getLogger(LogAdvice.class);

                logger.info(message);

             logger.debug(message);

             logger.error(message);

        

         log4j.properties: 属性文件://设置存储路径

         第一个部分:

           log4j.rootLogger = info,a,b

           log4j.rootLogger = [日志级别],输出端1,输出端2

         第二个部分:

           log4j.logger.com.opensymphony.xwork2=error

           log4j.logger.包名=日志级别

         第三个部分(输出端):

           org.apache.log4j.ConsoleAppender:将日志信息输出到控制台.

           org.apache.log4j.DailyRollingFileAppender:

             将日志信息输出到一个日志文件,并且每天输出到一个新的日志文件.

    6. slf4j框架:

         simple logging fade for java : java的日志门面(日志规范).

    <!-- 日志切面 -->

     <bean id="logAdvice" class="cn.itcast.oa.core.aop.LogAdvice"/>

        

         <!-- 切面(aop) -->

         <aop:config>

           <!-- 配置切入点 (切业务层) -->

           <aop:pointcut expression="execution(* cn.itcast.oa.*.*.service.impl.*.*(..))" id="pointcut"/>

           <!-- 事务切面将上面的声明式事务配置 txAdvice 运用到   哪个切入点pointcut  -->

           <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>

          

           <!-- 配置日志切入 -->

         <aop:aspect ref="logAdvice">

              切入方法

         <aop:around method="around" pointcut-ref="pointcut"/>

              配置异常后切入

    <aop:after-throwing method="error" pointcut-ref="pointcut" throwing="e"/>

           </aop:aspect>

         </aop:config>

  • 相关阅读:
    Appium运行时,error: Logcat capture failed: spawn ENOENT的解决办法
    pwntools使用简介3
    pwntools使用简介2
    pwnable.kr memcpy之write up
    pwnable.kr uaf之wp
    【笔记】objdump命令的使用
    pwnable.kr cmd2之write up
    pwnable.kr cmd1之write up
    pwnable.kr lotto之write up
    pwnable.kr blackjack之write up
  • 原文地址:https://www.cnblogs.com/maofa/p/6406881.html
Copyright © 2020-2023  润新知