ThreadLocal是什么?在mybatic如何应用?

2 篇文章 0 订阅

ThreadLocal

ThreadLocal是一个本地线程副本变量工具类。主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别适用于各个线程依赖不通的变量值完成操作的场景。

从数据结构入手

从数据结构入手
从上面的结构图,我们已经窥见ThreadLocal的核心机制:

每个Thread线程内部都有一个Map。
Map里面存储线程本地对象(key)和线程的变量副本(value)
但是,Thread内部的Map是由ThreadLocal维护的,由ThreadLocal负责向map获取和设置线程的变量值。

所以对于不同的线程,每次获取副本值时,别的线程并不能获取到当前线程的副本值,形成了副本的隔离,互不干扰。

上面这些都太抽象辽,我们来点简单的例子

package com.test;

public class Test {
	/**
	 * 主线程
	 * main方法里面都是一个线程 
	 * @param 大欧
	 */
	public static void main(String[] args) {
		/**
		 * 线程容器,给线程绑定一个Object内容,后只要线程不变,可以随时取出。
		 * final :匿名内部类需要final的,防止改变对象地址。final修饰的不允许重新实例化
		 * 用起来非常简单:一个set往里放值,一个是get往里取值。
		 */
		final ThreadLocal<String> threadLocal = new ThreadLocal<>();
		threadLocal.set("测试");
		String result1 = threadLocal.get();
		System.out.println(result1);
		/**创建一个子线程
		 *  run是线程体:执行的功能
		 *  start是启动
		 */
		new Thread() {
			public void run() {
				/**
				 * 改变线程,无法去除内容。
				 */
				String result2 = threadLocal.get();
				System.out.println("结果:"+result2);
			};
		}.start();
	}
}

运行结果:
在这里插入图片描述

ThreadLocal在mybatis中的应用

我在service层中,我们经常频繁写到在这里插入图片描述
在这里插入图片描述
所有我们可以运用一个工具类解决这个问题

util工具类

MyBatisUtil.java

package com.util;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MyBatisUtil {
	//factory实例化的过程是一个比较耗费性能的过程.
	//保证有且只有一个factory
	private static SqlSessionFactory factory;
	private static ThreadLocal<SqlSession> tl = new ThreadLocal<>();
	static{
		try {
			InputStream is = Resources.getResourceAsStream("mybatis.xml");
			factory = new SqlSessionFactoryBuilder().build(is);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
	 * 获取SqlSession的方法
	 */
	public static SqlSession getSession(){
		SqlSession session = tl.get();
		if(session==null){
			tl.set(factory.openSession());
		}
		return tl.get();
	}
	
	public static void closeSession(){
		SqlSession session = tl.get();
		if(session!=null){
			session.close();
		}
		tl.set(null);
	}
}

filter过滤器

OpenSessionInView.java

package com.filter;

import java.io.IOException;

import java.io.InputStream;

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 org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.util.MyBatisUtil;


/**
 * 最开始是由Spring框架提出的.整合Hibernate框架是使用的是OpenSessionInView
 * 
 * 
 * @author 大欧
 *
 */
@WebFilter("/*")
public class OpenSessionInView implements Filter{

	@Override
	public void init(FilterConfig filterconfig) throws ServletException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest servletrequest, ServletResponse servletresponse, FilterChain filterchain)
			throws IOException, ServletException {
//		InputStream is = Resources.getResourceAsStream("mybatis.xml");
//		SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//		SqlSession session = factory.openSession();		
		SqlSession session = MyBatisUtil.getSession();
		try {
			filterchain.doFilter(servletrequest, servletresponse);
			session.commit();
		} catch (Exception e) {
			session.rollback();
			e.printStackTrace();
		}finally{
			MyBatisUtil.closeSession();
		}
//		session.commit();
//		session.close();
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

}

不要忘记在web.xml配置filter

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">
	<!-- <filter>
		<filter-name>opensession</filter-name>
		<filter-class>com.filter.OpenSessionInView</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>opensession</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>  -->
</web-app>

mapper层

LogMapper.java

package com.mapper;

import com.pojo.Log;

public interface LogMapper {
	int ins(Log log);
}

LogMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mapper.LogMapper">
	<insert id="ins" parameterType="log">
		insert into log values(default,#{accOut},#{accIn},#{money})
	</insert>
</mapper>

pojo层

Log.java

package com.pojo;

public class Log {
	private int id;
	private String accIn;
	private String accOut;
	private double money;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getAccIn() {
		return accIn;
	}
	public void setAccIn(String accIn) {
		this.accIn = accIn;
	}
	public String getAccOut() {
		return accOut;
	}
	public void setAccOut(String accOut) {
		this.accOut = accOut;
	}
	public double getMoney() {
		return money;
	}
	public void setMoney(double money) {
		this.money = money;
	}
}

sql:

CREATE TABLE `log` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `accout` varchar(18) DEFAULT NULL,
  `accin` varchar(18) DEFAULT NULL,
  `money` double DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10005 DEFAULT CHARSET=utf8;

Selvlet层

InsertServlet.java

package com.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.pojo.Log;
import com.service.LogService;
import com.service.impl.LogServiceImpl;

@WebServlet("/insert")
public class InsertServlet extends HttpServlet{
	private LogService logService = new LogServiceImpl();
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("utf-8");
		Log log = new Log();
		log.setAccIn(req.getParameter("accin"));
		log.setAccOut(req.getParameter("accout"));
		log.setMoney(Double.parseDouble(req.getParameter("money")));
		int index = logService.ins(log);
		if(index>0){
			resp.sendRedirect("success.jsp");
		}else{
			resp.sendRedirect("error.jsp");
		}
	}
}

service层

LogService.java

package com.service;

import com.pojo.Log;

public interface LogService {
	int ins(Log log);
}

LogServiceImpl .java
这里就简化了很多了,做项目也就是写的东西最多

package com.service.impl;

import org.apache.ibatis.session.SqlSession;

import com.mapper.LogMapper;
import com.pojo.Log;
import com.service.LogService;
import com.util.MyBatisUtil;

public class LogServiceImpl implements LogService{

	@Override
	public int ins(Log log) {
		SqlSession session = MyBatisUtil.getSession();
		LogMapper mapper = session.getMapper(LogMapper.class);
		return mapper.ins(log);
	}

}

mybatis.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<settings>
		<setting name="logImpl" value="LOG4J"/>
	</settings>
	<typeAliases>
		<package name="com.bjsxt.pojo"/>
	</typeAliases>
	<environments default="default">
		<environment id="default">
			<transactionManager type="JDBC"></transactionManager>
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://localhost:3306/***"/>
				<property name="username" value="root"/>
				<property name="password" value="******"/>
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<package name="com.mapper"/>
	</mappers>
</configuration>

jsp

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="insert" method="post">
	<input type="text" name="accin"/><br/>
	<input type="text" name="accout"/><br/>
	<input type="text" name="money"/><br/>
	<input type="submit" value="提交"/>
</form>
</body>
</html>

success.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
success
</body>
</html>

error.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
error
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值