ThreadLocal是什么?在mybatic如何应用?
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>