ThreadLocal_OSIV模式_FIlter_Web ajax
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
1:OSIV模式 - Open Session In View
2:讓項(xiàng)目中的所有代碼成為單例。
?
?
1:在項(xiàng)目中一個(gè)Service調(diào)用多個(gè)Dao的情況下
?
解決方案1:
將所有代碼:
1:傳遞同一個(gè)Connection給每一個(gè)Dao。
2:在Serice里面控制事務(wù)。即try..catch..fnally。
??
?
?
?
上面的問題:
1:讓Connection這個(gè)連接對(duì)象暴露在了Service層。
2:在項(xiàng)目中,有N個(gè)Service,在每一個(gè)Service中都寫try..catch..finally代碼量太大,重復(fù)太多。
3:給每一個(gè)dao需要多傳遞一個(gè)參數(shù)。即Connection參數(shù)。
?
?
?
解決方案2:
???在Java中有一個(gè)類ThreadLocal - 維護(hù)線程局部的變量。
???此類看上去像是線程,但是本質(zhì)是容器即是一個(gè)HashMap。它的結(jié)構(gòu)是:Map<Thead,Object>即,以線程為key,以任意的對(duì)象為value保存值。
?
?
?
?
1:思想
???修改DSUtils類,維護(hù)一個(gè)唯一的線程局部的對(duì)象。
// 聲明ThreadLocal
private?static?ThreadLocal<Connection> tl;
static?{
tl?= new?ThreadLocal<>();
dataSource?= new?ComboPooledDataSource();
}
?
public?static?DataSource getDataSource() {
return?dataSource;
}
?
public?static?Connection getConnection() {
Connection con?= tl.get();// 先從tl獲取連接,查看當(dāng)前線程是否保存過連接
if?(con?== null) {
try?{
con?= dataSource.getConnection();
// 放到tl
tl.set(con);
} catch?(Exception e) {
throw?new?RuntimeException(e);
}
}
return?con;
}
?
2:添加過慮器 /stud
package?cn.filter;
?
import?java.io.IOException;
import?java.sql.Connection;
import?java.sql.SQLException;
?
import?javax.servlet.Filter;
import?javax.servlet.FilterChain;
import?javax.servlet.FilterConfig;
import?javax.servlet.ServletException;
import?javax.servlet.ServletRequest;
import?javax.servlet.ServletResponse;
import?javax.servlet.annotation.WebFilter;
?
import?cn.meeting.utils.DSUtils;
?
@WebFilter(urlPatterns = "/stud")
public?class?TxFilter implements?Filter {
?
@Override
public?void?init(FilterConfig filterConfig) throws?ServletException {
?
}
?
@Override
public?void?doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws?IOException, ServletException {
// 1:獲取
Connection con?= DSUtils.getConnection();
try?{
con.setAutoCommit(false);
chain.doFilter(request, response);
con.commit();
} catch?(Exception e) {
try?{
con.rollback();
} catch?(SQLException e1) {
e1.printStackTrace();
}
throw?new?RuntimeException(e);
} finally?{
try?{
con.close();
} catch?(SQLException e) {
e.printStackTrace();
}
DSUtils.remove();
}
}
@Override
public?void?destroy() {
// TODO?Auto-generated method stub
?
}
?
}
OSIV模式,將事務(wù)的控制做為Filter層。
?
?
上面的問題是:
??事務(wù)太靠前了。在過慮器層。
??如果在調(diào)用servlet時(shí),事務(wù)已經(jīng)開始。但是在servlet中出錯(cuò)了,即還沒有service/dao呢。
?轉(zhuǎn)發(fā)時(shí),如果不是SQL異常也回滾。
?
可以通過catch只對(duì)sql異常進(jìn)行rollback;
?
?
?
解決方案3:
???可以使用代理代理所有Service。
?
?
package?cn.utils;
?
import?java.lang.reflect.InvocationHandler;
import?java.lang.reflect.Method;
import?java.lang.reflect.Proxy;
import?java.sql.Connection;
?
import?cn.meeting.utils.DSUtils;
?
public?class?TxProxy {
public?static?Object newProxy(final?Object src) {
Object proxyObj?= Proxy.newProxyInstance(TxProxy.class.getClassLoader(), src.getClass().getInterfaces(),
new?InvocationHandler() {
@Override
public?Object invoke(Object proxy, Method method, Object[] args) throws?Throwable {
Connection con?= DSUtils.getConnection();
System.err.println("獲取連接.."?+ con);
Object returnValue?= null;
try?{
System.err.println("開始事務(wù)");
con.setAutoCommit(false);
returnValue?= method.invoke(src, args);// 放行
System.err.println("提交");
con.commit();
} catch?(Exception e) {
System.err.println("出錯(cuò)了回滾");
con.rollback();
throw?e;
} finally?{
con.close();
DSUtils.remove();
}
return?returnValue;
}
});
return?proxyObj;
?
}
}
?
?
?
?
?
?
?
@WebServlet("/stud")
public?class?StudServlet extends?HttpServlet {
private?static?final?long?serialVersionUID?= 1L;
private?IStudService service?= (IStudService) TxProxy.newProxy(new?StudServlet());
?
?
?
?
?
2:ThreadLocal
java.lang
類 ThreadLocal<T>
java.lang.Object
??java.lang.ThreadLocal<T>
直接已知子類:?
InheritableThreadLocal?
?
public class ThreadLocal<T>
extends Object
該類提供了線程局部 (thread-local) 變量
?
?
變量:
???三種: 1:局部,2:成員, 3:線程局部。
?
?
1:用ThreadLocal保存數(shù)據(jù)
@Test
public?void?test1() {
// 1:實(shí)例化容器Map<Thread,T>
ThreadLocal<Object> tl?= new?ThreadLocal<>();
tl.set("Jack");
// 獲取里面的值
Object val?= tl.get();
System.err.println(val);
}
?
?
// 1:實(shí)例化容器Map<Thread,T>
ThreadLocal<Object> tl?= new?ThreadLocal<>();//Map<Thread,T>
tl.set("Jack");//map.put(Thread.currentThread(),"Jack");
tl.set("Mary");//map.put(Thread.currentThread(),"Mary"); //后面覆蓋前面的值
// 獲取里面的值
Object val?= tl.get();//Mary
System.err.println(val);
?
2:單例化ThreadLocal
??保存當(dāng)前某個(gè)線程的局部的變量-線程局部的變量。
??在一個(gè)項(xiàng)目中,只要有一個(gè)TL對(duì)象,就可以為所有線程提供服務(wù)。
@Test
public?void?teest1() throws?Exception{
Object obj1?= TLUtils.random();
System.err.println("1:"+obj1);
abc();
?
?
new?Thread(){
public?void?run() {
Object obj1?= TLUtils.random();
System.err.println("3:"+obj1);
abc();
};
}.start();
?
System.in.read();
}
?
?
public?void?abc(){
Object obj1?= TLUtils.random();
System.err.println(Thread.currentThread().getName()+" 2:"+obj1);
}
}
?
3:自己開發(fā)ThreadLocal對(duì)象
?思想:
???自己開發(fā)一個(gè)集合Map<Thred,Object>
public?class?TLUtils2 {
private?static?Map<Thread, Object> tl;
static?{
tl?= new?HashMap<Thread, Object>();
}
?
public?static?Object get() {
Object obj?= tl.get(Thread.currentThread());
if?(obj?== null) {
obj?= new?Random().nextInt(100);
tl.put(Thread.currentThread(), obj);
}
return?obj;
}
}
?
上面的類的問題:
???1:做為HashMap,即集合類,只看到了不斷的獲取數(shù)據(jù),和不斷的保存數(shù)據(jù)
??????沒有看到從map中刪除數(shù)據(jù)。
??????則Map的中的值越來越多。最后總是會(huì)造成對(duì)象太多而崩潰。
?
???2:所以,當(dāng)某個(gè)對(duì)象不在被使用以后,應(yīng)該及時(shí)清理掉。
?????在ThreadLocal中是如何清理的:
?????
| ?void | remove()? |
?
?
???3:所以,上面的自己開發(fā)的線程局部,也必須要提供一個(gè)方法,用于刪除
?????public?class?TLUtils2 {
private?static?Map<Thread, Object> tl;
static?{
tl?= new?HashMap<Thread, Object>();
}
?
public?static?Object get() {
Object obj?= tl.get(Thread.currentThread());
if?(obj?== null) {
obj?= new?Random().nextInt(100);
tl.put(Thread.currentThread(), obj);
}
return?obj;
}
?
public?static?void?remove(){
tl.remove(Thread.currentThread());
}
}
?
上面的問題是:
???用戶必須要顯式的調(diào)用remove才可以。
?
?
2.2、對(duì)象的引用
對(duì)象的引用為分為四種:
強(qiáng)引用
????Person p = new Person();
????此時(shí)p變量,new Person()叫對(duì)象,此時(shí) new Peson這個(gè)對(duì)象被 p這個(gè)變量強(qiáng)引用。
????在Java代碼中, 如果內(nèi)存不夠了則 GC會(huì)回收內(nèi)存。但是如果對(duì)象有強(qiáng)引用。但是內(nèi)存又不夠用了,JVM直接崩潰也不會(huì)回收強(qiáng)引用的內(nèi)存。
弱
????如果內(nèi)存不夠了,則會(huì)回收這個(gè)內(nèi)存。
軟
????如果內(nèi)存不夠了,則會(huì)回收這個(gè)內(nèi)存。放到回收隊(duì)列。
虛
????內(nèi)存無論是否足夠,則直接回收這個(gè)內(nèi)存。
java.lang.ref
類 WeakReference<T>
java.lang.Object
??java.lang.ref.Reference<T>
??????java.lang.ref.WeakReference<T>
?
public class WeakReference<T>
extends Reference<T>
弱引用對(duì)象,它們并不禁止其指示對(duì)象變得可終結(jié),并被終結(jié),然后被回收。弱引用最常用于實(shí)現(xiàn)規(guī)范化的映射。
public?class?Demo02_Weak {
@Test
public?void?test1(){
WeakReference<Dog> weak?= new?WeakReference<Dog>(new?Dog());
//從引用里面獲取這個(gè)對(duì)象
System.gc();
Dog dog?= weak.get();
System.err.println("程序執(zhí)行完成了:"+dog);
}
}
class?Dog {
protected?void?finalize() {
System.err.println("被回收了 :"+this);
}
}
?
?
?
?
?
3:ajax
Asynchronized Javascrpt And XML - 異步的JS與XML/JSON文件。
?
功能:
???異步的請(qǐng)求數(shù)據(jù)。瀏覽器開線程向后臺(tái)發(fā)送請(qǐng)求。
???頁面的局部刷新。
?
組成部分:
???1:XMLHttpRequest對(duì)象 腳本對(duì)象 核心對(duì)象,用于發(fā)送get/post請(qǐng)求。
???2:XML文件,向服務(wù)器發(fā)送XML數(shù)據(jù)。
???3:CSS 控制顯示的樣式。
???4:JS 用于控制XHR對(duì)象發(fā)送請(qǐng)求。
?
1:如何創(chuàng)建XHR對(duì)象
<html>
?
??<script type="text/javascript">
??????//1:聲明xhr對(duì)象
??????var xhr = null;
??????//2:判斷是否可以通過new的方式來創(chuàng)建xhr對(duì)象
??????//IE9以下的版本使用new ActiveXObject的方式來創(chuàng)建
??????//其他的瀏覽器都是通過new XMLHttpRequest的方式來創(chuàng)建
??????if(window.XMLHttpRequest){//IE10,FF,Chome,
??????????xhr ?= new XMLHttpRequest();
??????????console.log("IE10,ff,chrome");
??????}else{
???????????xhr = new ActiveXObject("Microsoft.XMLHttp");
???????????console.log("<IE9");
??????}
??????alert(xhr);
??</script>
</html>
?
?
2:發(fā)送請(qǐng)示到后臺(tái),獲取返回的字符串?dāng)?shù)據(jù)
??readyState
| 0 (未初始化) | 對(duì)象已建立,但是尚未初始化(尚未調(diào)用open方法) |
| 1 (初始化) | 對(duì)象已建立,尚未調(diào)用send方法 |
| 2 (發(fā)送數(shù)據(jù)) | send方法已調(diào)用,但是當(dāng)前的狀態(tài)及http頭未知 |
| 3 (數(shù)據(jù)傳送中) | 已接收部分?jǐn)?shù)據(jù),因?yàn)轫憫?yīng)及http頭不全,這時(shí)通過responseBody和responseText獲取部分?jǐn)?shù)據(jù)會(huì)出現(xiàn)錯(cuò)誤, |
| 4 (完成) | 數(shù)據(jù)接收完畢,此時(shí)可以通過通過responseBody和responseText獲取完整的回應(yīng)數(shù)據(jù) |
?
function?_get() {
//1:聲明訪問的地址
var?url = "/20160515/random";
//2:設(shè)置如何訪問這個(gè)url
xhr.open("GET", url, true);//默認(rèn)值就是異步
//3:注冊(cè)服務(wù)器成功以后的回調(diào)函數(shù)
//
xhr.onreadystatechange = function() {
if(xhr.readyState==4){//判斷是否接收到了數(shù)據(jù)
//判斷服務(wù)器的狀態(tài)
if(xhr.status==200){
//如果數(shù)據(jù)成功,就返回
var?txt = xhr.responseText;
document.getElementsByName("name")[0].value=txt;
}else{
alert("失敗:"+xhr.status);
}
}
};
//4:開始請(qǐng)求數(shù)據(jù)
xhr.send();
?
?
?
@WebServlet("/random")
public?class?RandomServlet extends?HttpServlet {
private?static?final?long?serialVersionUID?= 1L;
protected?void?doGet(HttpServletRequest request, HttpServletResponse response) throws?ServletException, IOException {
System.err.println("請(qǐng)示過來的");
Random r?= new?Random();
int?a?= r.nextInt(100);
//輸出文本
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().print(a);
}
}
?
?
?
?
?
轉(zhuǎn)載于:https://my.oschina.net/dtz/blog/679195
總結(jié)
以上是生活随笔為你收集整理的ThreadLocal_OSIV模式_FIlter_Web ajax的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaScript权威设计--事件冒泡
- 下一篇: shiro自定义Realm