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>

posted on 2017-02-16 17:45  阿发仔  阅读(265)  评论(0编辑  收藏  举报

导航