OSIV模式优化方案 与单例

1:OSIV模式 - Open Session In View

2:让项目中的所有代码成为单例。

 

 

1:在项目中一个Service调用多个Dao的情况下

 

解决方案1:

将所有代码:

1:传递同一个Connection给每一个Dao。

2:在Serice里面控制事务。即try..catch..fnally。

  

 

 

 

上面的问题:

1:让Connection这个连接对象暴露在了Service层。

2:在项目中,有N个Service,在每一个Service中都写try..catch..finally代码量太大,重复太多。

3:给每一个dao需要多传递一个参数。即Connection参数。

 

 

 

解决方案2:

   在Java中有一个类ThreadLocal - 维护线程局部的变量。

   此类看上去像是线程,但是本质是容器即是一个HashMap。它的结构是:Map<Thead,Object>即,以线程为key,以任意的对象为value保存值。

 

 

 

 

1:思想

   修改DSUtils类,维护一个唯一的线程局部的对象。

// 声明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获取连接,查看当前线程是否保存过连接

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模式,将事务的控制做为Filter层。

 

 

上面的问题是:

  事务太靠前了。在过虑器层。

  如果在调用servlet时,事务已经开始。但是在servlet中出错了,即还没有service/dao呢。

 转发时,如果不是SQL异常也回滚。

 

可以通过catch只对sql异常进行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("开始事务");

con.setAutoCommit(false);

returnValue = method.invoke(src, args);// 放行

System.err.println("提交");

con.commit();

} catch (Exception e) {

System.err.println("出错了回滚");

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保存数据

@Test

public void test1() {

// 1:实例化容器Map<Thread,T>

ThreadLocal<Object> tl = new ThreadLocal<>();

tl.set("Jack");

// 获取里面的值

Object val = tl.get();

System.err.println(val);

}

 

 

// 1:实例化容器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

  保存当前某个线程的局部的变量-线程局部的变量。

  在一个项目中,只要有一个TL对象,就可以为所有线程提供服务。

@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:自己开发ThreadLocal对象

 思想:

   自己开发一个集合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,即集合类,只看到了不断的获取数据,和不断的保存数据

      没有看到从map中删除数据。

      则Map的中的值越来越多。最后总是会造成对象太多而崩溃。

 

   2:所以,当某个对象不在被使用以后,应该及时清理掉。

     在ThreadLocal中是如何清理的:

     

 void

remove() 
          移除此线程局部变量当前线程的值。

 

 

   3:所以,上面的自己开发的线程局部,也必须要提供一个方法,用于删除

     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());

}

}

 

上面的问题是:

   用户必须要显式的调用remove才可以。

 

 

2.2、对象的引用

对象的引用为分为四种:

强引用

    Person p = new Person();

    此时p变量,new Person()叫对象,此时 new Peson这个对象被 p这个变量强引用。

    在Java代码中, 如果内存不够了则 GC会回收内存。但是如果对象有强引用。但是内存又不够用了,JVM直接崩溃也不会回收强引用的内存。

    如果内存不够了,则会回收这个内存。

    如果内存不够了,则会回收这个内存。放到回收队列。

    内存无论是否足够,则直接回收这个内存。

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>

弱引用对象,它们并不禁止其指示对象变得可终结,并被终结,然后被回收。弱引用最常用于实现规范化的映射。

public class Demo02_Weak {

@Test

public void test1(){

WeakReference<Dog> weak = new WeakReference<Dog>(new Dog());

//从引用里面获取这个对象

System.gc();

Dog dog = weak.get();

System.err.println("程序执行完成了:"+dog);

}

}

class Dog {

protected void finalize() {

System.err.println("被回收了 :"+this);

}

}

 

 

 

 

 

3:ajax

Asynchronized Javascrpt And XML - 异步的JS与XML/JSON文件。

 

功能:

   异步的请求数据。浏览器开线程向后台发送请求。

   页面的局部刷新。

 

组成部分:

   1:XMLHttpRequest对象 脚本对象 核心对象,用于发送get/post请求。

   2:XML文件,向服务器发送XML数据。

   3:CSS 控制显示的样式。

   4:JS 用于控制XHR对象发送请求。

 

1:如何创建XHR对象

<html>

 

  <script type="text/javascript">

      //1:声明xhr对象

      var xhr = null;

      //2:判断是否可以通过new的方式来创建xhr对象

      //IE9以下的版本使用new ActiveXObject的方式来创建

      //其他的浏览器都是通过new XMLHttpRequest的方式来创建

      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:发送请示到后台,获取返回的字符串数据

  readyState

0 (未初始化)

对象已建立,但是尚未初始化(尚未调用open方法)

1 (初始化)

对象已建立,尚未调用send方法

2 (发送数据)

send方法已调用,但是当前的状态及http头未知

3 (数据传送中)

已接收部分数据,因为响应及http头不全,这时通过responseBody和responseText获取部分数据会出现错误,

4 (完成)

数据接收完毕,此时可以通过通过responseBody和responseText获取完整的回应数据

 

function _get() {

//1:声明访问的地址

var url = "/20160515/random";

//2:设置如何访问这个url

xhr.open("GET", url, true);//默认值就是异步

//3:注册服务器成功以后的回调函数

//

xhr.onreadystatechange = function() {

if(xhr.readyState==4){//判断是否接收到了数据

//判断服务器的状态

if(xhr.status==200){

//如果数据成功,就返回

var txt = xhr.responseText;

document.getElementsByName("name")[0].value=txt;

}else{

alert("失败:"+xhr.status);

}

}

};

//4:开始请求数据

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("请示过来的");

Random r = new Random();

int a = r.nextInt(100);

//输出文本

response.setContentType("text/plain;charset=UTF-8");

response.getWriter().print(a);

}

}

 

 

 

 

 

转载于:https://my.oschina.net/dtz/blog/679643

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值