文档章节

OSIV模式优化方案 与单例

CarlDing
 CarlDing
发布于 2016/05/23 09:00
字数 1914
阅读 44
收藏 1

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

}

}

 

 

 

 

 

© 著作权归作者所有

上一篇: Ajax2
下一篇: Ajax_XML_JSON
CarlDing
粉丝 5
博文 106
码字总数 78103
作品 0
济南
其他
私信 提问
单例模式 - Singleton Pattern

简介 什么是单例?为什么需要单例? 单例模式的目的是设计出一个类,能提供全局唯一的对象。 举个例子,程序中需要一个类用做管理配置项。这样一个类显然希望是全局只有一个,在任何地方都能...

齐晋
2017/08/22
0
0
《从零开始学Swift》学习笔记(Day 63)——Cocoa Touch设计模式及应用之单例模式

原创文章,欢迎转载。转载请注明:关东升的博客 什么是设计模式。设计模式是在特定场景下对特定问题的解决方案,这些解决方案是经过反复论证和测试总结出来的。实际上,除了软件设计,设计模...

智捷课堂
2016/01/22
34
0
1.单例模式

设计模式并非是难以理解, 或是难以应用到实践中的, 相反的, 设计模式恰恰代表了某些场景下的最佳实践! 这些设计模式通常被有经验的开发者们所采用。 设计模式是开发者们在开发过程中面临的一...

mtshen
2018/01/04
0
0
使用合适的设计模式一步步优化前端代码

作者:晓飞 本文原创,转载请注明作者及出处 在后端语言中,设计模式应用的较为广泛。如Spring中常见的工厂模式、装饰者模式、单例模式、迭代器模式。但是在日常的前端开发中,设计模式使用的...

iKcamp
2017/10/27
0
0
ThreadLocal_OSIV模式_FIlter_Web ajax

1:OSIV模式 - Open Session In View 2:让项目中的所有代码成为单例。 1:在项目中一个Service调用多个Dao的情况下 解决方案1: 将所有代码: 1:传递同一个Connection给每一个Dao。 2:在Ser...

CarlDing
2016/05/21
8
0

没有更多内容

加载失败,请刷新页面

加载更多

Mybatis Plus删除

/** @author beth @data 2019-10-17 00:30 */ @RunWith(SpringRunner.class) @SpringBootTest public class DeleteTest { @Autowired private UserInfoMapper userInfoMapper; /** 根据id删除......

一个yuanbeth
今天
4
0
总结

一、设计模式 简单工厂:一个简单而且比较杂的工厂,可以创建任何对象给你 复杂工厂:先创建一种基础类型的工厂接口,然后各自集成实现这个接口,但是每个工厂都是这个基础类的扩展分类,spr...

BobwithB
今天
5
0
java内存模型

前言 Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚。比如本文我们要讨论的JVM内存结构、Java内存模...

ls_cherish
今天
4
0
友元函数强制转换

友元函数强制转换 p522

天王盖地虎626
昨天
5
0
js中实现页面跳转(返回前一页、后一页)

本文转载于:专业的前端网站➸js中实现页面跳转(返回前一页、后一页) 一:JS 重载页面,本地刷新,返回上一页 复制代码代码如下: <a href="javascript:history.go(-1)">返回上一页</a> <a h...

前端老手
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部