私有化有參和無參的構造方法,用於多選一html
enum Grade{java
A("90-100"),B("80-90"),C("70-80"),D("60-70"),E("<60");mysql
private String score;web
private Grade(String score){正則表達式
this.score=score;算法
}spring
public String toString() {sql
return "Grade [score=" + score + "]";數據庫
}express
}
等同於在普通類裏進行公有化的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是一個基於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>
項目啓動:
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的路徑
業務功能聲明文件
<result-types>
經常使用的視圖類型:
dispatcher: 轉發頁面
redirect:重定向頁面
chain: 轉發到Action
redirectAction:重定向到Action (內容寫另外一個Action的name屬性)
stream: 用於文件下載的
</result-types>
<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>
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;
}
<interceptors>
<interceptor name="(自定義攔截器的名字)" class="(完整包名)"></interceptor> //引用攔截器
<interceptor-stack name="(輸入任意攔截器名字)"> //至關於打包攔截器
<!-- 引用攔截器 -->
<interceptor-stackname="defaultStack"></interceptor-ref> //默認18個攔截器
<interceptor-ref name="(與自定義攔截器名字一致才能使用)"></interceptor-ref>
</interceptor-stack>
<interceptors>
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常量
<constant name=」 struts.i18n.encoding」 value=」utf-8」></constant>
<!-- 修改struts的UI模塊 -->
<constant name="struts.ui.theme" value="simple"></constant> //設置爲簡單模式把所有el表達式替代成ognl表達式
<global-results>
<result>/succ.jsp</result>
</global-results>
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;
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表達式須要藉助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邏輯標籤
數據標籤:
<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方法,裏面驗證信息和頁面數據一致
把一個驗證文件(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>
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&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-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 完整包名)"/>
<hibernate-mapping>
package: 類所在的包
<class> -- 表明須要映射一個類
name: 表明映射類名(若是沒有配置package,必須寫全名)
table: 表明須要映射到的表名
<id name="(實體ID)" column="(對應表單ID)"> 表明主鍵配置
<generator class="assigned"> 主鍵維護策略
<property name=」屬性名稱」 column=」字段名稱」 length=」字段長度」> 表明普通屬性映射
概念:
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(年月日時分秒)
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)
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>
全表查詢返回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
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() 清空一級緩存的全部對象
臨時狀態
例如: 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);
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&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是一個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;
}
使用無參構造方法建立對象
<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>
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概念
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底層使用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的事務管理器 : 用於管理每次操做的事務代碼-->
<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="切入點"/>
在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>
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>