Browse Source

threadlocal

pull/1/head
马府强 2 years ago
parent
commit
d161826f59
  1. 74
      threadconnectiondemo/pom.xml
  2. 12
      threadconnectiondemo/src/main/java/com/woniu/connection/MainApplication.java
  3. 46
      threadconnectiondemo/src/main/java/com/woniu/connection/config/DynamicDataSourceConfig.java
  4. 54
      threadconnectiondemo/src/main/java/com/woniu/connection/config/DynamicDataSourceFactory.java
  5. 26
      threadconnectiondemo/src/main/java/com/woniu/connection/config/WebConfig.java
  6. 7
      threadconnectiondemo/src/main/java/com/woniu/connection/constant/AuthServerConstant.java
  7. 37
      threadconnectiondemo/src/main/java/com/woniu/connection/dao/AccountDao.java
  8. 9
      threadconnectiondemo/src/main/java/com/woniu/connection/entity/User.java
  9. 40
      threadconnectiondemo/src/main/java/com/woniu/connection/interceptor/LoginUserInterceptor.java
  10. 202
      threadconnectiondemo/src/main/java/com/woniu/connection/properties/DataSourceProperties.java
  11. 33
      threadconnectiondemo/src/main/java/com/woniu/connection/properties/DynamicDataSourceProperties.java
  12. 15
      threadconnectiondemo/src/main/java/com/woniu/connection/service/AService.java
  13. 64
      threadconnectiondemo/src/main/java/com/woniu/connection/service/AccountService.java
  14. 28
      threadconnectiondemo/src/main/java/com/woniu/connection/service/DealService.java
  15. 21
      threadconnectiondemo/src/main/java/com/woniu/connection/service/LoginService.java
  16. 78
      threadconnectiondemo/src/main/java/com/woniu/connection/utils/JdbcUtils.java
  17. 64
      threadconnectiondemo/src/main/java/com/woniu/connection/utils/R.java
  18. 16
      threadconnectiondemo/src/main/java/com/woniu/connection/utils/ThreadSafeFormatterUtil.java
  19. 126
      threadconnectiondemo/src/main/java/com/woniu/connection/web/WebController.java
  20. 39
      threadconnectiondemo/src/main/resources/application.yml
  21. 39
      threadconnectiondemo/target/classes/application.yml
  22. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/MainApplication.class
  23. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/config/DynamicDataSourceConfig.class
  24. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/config/DynamicDataSourceFactory.class
  25. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/config/WebConfig.class
  26. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/constant/AuthServerConstant.class
  27. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/dao/AccountDao.class
  28. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/entity/User.class
  29. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/interceptor/LoginUserInterceptor.class
  30. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/properties/DataSourceProperties.class
  31. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/properties/DynamicDataSourceProperties.class
  32. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/service/AService.class
  33. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/service/AccountService.class
  34. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/service/DealService.class
  35. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/service/LoginService.class
  36. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/utils/JdbcUtils.class
  37. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/utils/R.class
  38. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/utils/ThreadSafeFormatterUtil$1.class
  39. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/utils/ThreadSafeFormatterUtil.class
  40. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/web/WebController$1.class
  41. BIN
      threadconnectiondemo/target/classes/com/woniu/connection/web/WebController.class
  42. 92
      threadconnectiondemo/threadconnectiondemo.iml

74
threadconnectiondemo/pom.xml

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.woniu.connection</groupId>
<artifactId>threadconnectiondemo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>2.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.15</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.13</version>
</dependency>
</dependencies>
</project>

12
threadconnectiondemo/src/main/java/com/woniu/connection/MainApplication.java

@ -0,0 +1,12 @@
package com.woniu.connection;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}

46
threadconnectiondemo/src/main/java/com/woniu/connection/config/DynamicDataSourceConfig.java

@ -0,0 +1,46 @@
/**
* Copyright (c) 2018 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有侵权必究
*/
package com.woniu.connection.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.woniu.connection.properties.DataSourceProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* 配置多数据源
*
* @author 蜗牛
*/
@Configuration
public class DynamicDataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
@Bean
public DruidDataSource dynamicDataSource(DataSourceProperties dataSourceProperties) {
//默认数据源
DruidDataSource defaultDataSource = DynamicDataSourceFactory.buildDruidDataSource(dataSourceProperties);
return defaultDataSource;
}
}

54
threadconnectiondemo/src/main/java/com/woniu/connection/config/DynamicDataSourceFactory.java

@ -0,0 +1,54 @@
/**
* Copyright (c) 2018 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有侵权必究
*/
package com.woniu.connection.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.woniu.connection.properties.DataSourceProperties;
import java.sql.SQLException;
/**
* DruidDataSource
*
* @author 蜗牛
* @since 1.0.0
*/
public class DynamicDataSourceFactory {
public static DruidDataSource buildDruidDataSource(DataSourceProperties properties) {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(properties.getDriverClassName());
druidDataSource.setUrl(properties.getUrl());
druidDataSource.setUsername(properties.getUsername());
druidDataSource.setPassword(properties.getPassword());
druidDataSource.setInitialSize(properties.getInitialSize());
druidDataSource.setMaxActive(properties.getMaxActive());
druidDataSource.setMinIdle(properties.getMinIdle());
druidDataSource.setMaxWait(properties.getMaxWait());
druidDataSource.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRunsMillis());
druidDataSource.setMinEvictableIdleTimeMillis(properties.getMinEvictableIdleTimeMillis());
druidDataSource.setMaxEvictableIdleTimeMillis(properties.getMaxEvictableIdleTimeMillis());
druidDataSource.setValidationQuery(properties.getValidationQuery());
druidDataSource.setValidationQueryTimeout(properties.getValidationQueryTimeout());
druidDataSource.setTestOnBorrow(properties.isTestOnBorrow());
druidDataSource.setTestOnReturn(properties.isTestOnReturn());
druidDataSource.setPoolPreparedStatements(properties.isPoolPreparedStatements());
druidDataSource.setMaxOpenPreparedStatements(properties.getMaxOpenPreparedStatements());
druidDataSource.setSharePreparedStatements(properties.isSharePreparedStatements());
try {
druidDataSource.setFilters(properties.getFilters());
druidDataSource.init();
} catch (SQLException e) {
e.printStackTrace();
}
return druidDataSource;
}
}

26
threadconnectiondemo/src/main/java/com/woniu/connection/config/WebConfig.java

@ -0,0 +1,26 @@
package com.woniu.connection.config;
import com.woniu.connection.interceptor.LoginUserInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Description:
* @Created: with IntelliJ IDEA.
* @author: 蜗牛
* @createTime: 2020-07-02 18:38
**/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginUserInterceptor loginUserInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginUserInterceptor).addPathPatterns("/app/getUser");
}
}

7
threadconnectiondemo/src/main/java/com/woniu/connection/constant/AuthServerConstant.java

@ -0,0 +1,7 @@
package com.woniu.connection.constant;
public class AuthServerConstant {
public static final String LOGIN_USER = "loginUser";
}

37
threadconnectiondemo/src/main/java/com/woniu/connection/dao/AccountDao.java

@ -0,0 +1,37 @@
package com.woniu.connection.dao;
import com.woniu.connection.utils.JdbcUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@Service
public class AccountDao {
@Autowired
private JdbcUtils jdbcUtils;
//转出
public void out(String outUser, int money) throws SQLException {
String sql = "update account set money = money - ? where name = ?";
Connection conn = jdbcUtils.getConnection();
PreparedStatement pstm = conn.prepareStatement(sql);
pstm.setInt(1, money);
pstm.setString(2, outUser);
pstm.executeUpdate();
}
//转入
public void in(String inUser, int money) throws SQLException {
String sql = "update account set money = money + ? where name = ?";
Connection conn = jdbcUtils.getConnection();
PreparedStatement pstm = conn.prepareStatement(sql);
pstm.setInt(1, money);
pstm.setString(2, inUser);
pstm.executeUpdate();
}
}

9
threadconnectiondemo/src/main/java/com/woniu/connection/entity/User.java

@ -0,0 +1,9 @@
package com.woniu.connection.entity;
import lombok.Data;
@Data
public class User {
private String userName;
private String password;
}

40
threadconnectiondemo/src/main/java/com/woniu/connection/interceptor/LoginUserInterceptor.java

@ -0,0 +1,40 @@
package com.woniu.connection.interceptor;
import com.woniu.connection.constant.AuthServerConstant;
import com.woniu.connection.entity.User;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
@Component
public class LoginUserInterceptor implements HandlerInterceptor {
public static ThreadLocal<User> loginUser = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取登录的用户信息
User attribute = (User) request.getSession().getAttribute(AuthServerConstant.LOGIN_USER);
if (attribute != null) {
//把登录后用户的信息放在ThreadLocal里面进行保存
loginUser.set(attribute);
return true;
} else {
//未登录,返回登录页面
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<script>alert('请先进行登录,再进行后续操作!')</script>");
return false;
}
}
}

202
threadconnectiondemo/src/main/java/com/woniu/connection/properties/DataSourceProperties.java

@ -0,0 +1,202 @@
/**
* Copyright (c) 2018 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有侵权必究
*/
package com.woniu.connection.properties;
/**
* 多数据源属性
*
* @author 蜗牛
* @since 1.0.0
*/
public class DataSourceProperties {
private String driverClassName;
private String url;
private String username;
private String password;
/**
* Druid默认参数
*/
private int initialSize = 2;
private int maxActive = 10;
private int minIdle = -1;
private long maxWait = 60 * 1000L;
private long timeBetweenEvictionRunsMillis = 60 * 1000L;
private long minEvictableIdleTimeMillis = 1000L * 60L * 30L;
private long maxEvictableIdleTimeMillis = 1000L * 60L * 60L * 7;
private String validationQuery = "select 1";
private int validationQueryTimeout = -1;
private boolean testOnBorrow = false;
private boolean testOnReturn = false;
private boolean testWhileIdle = true;
private boolean poolPreparedStatements = false;
private int maxOpenPreparedStatements = -1;
private boolean sharePreparedStatements = false;
private String filters = "stat,wall";
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getInitialSize() {
return initialSize;
}
public void setInitialSize(int initialSize) {
this.initialSize = initialSize;
}
public int getMaxActive() {
return maxActive;
}
public void setMaxActive(int maxActive) {
this.maxActive = maxActive;
}
public int getMinIdle() {
return minIdle;
}
public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}
public long getMaxWait() {
return maxWait;
}
public void setMaxWait(long maxWait) {
this.maxWait = maxWait;
}
public long getTimeBetweenEvictionRunsMillis() {
return timeBetweenEvictionRunsMillis;
}
public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
}
public long getMinEvictableIdleTimeMillis() {
return minEvictableIdleTimeMillis;
}
public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
}
public long getMaxEvictableIdleTimeMillis() {
return maxEvictableIdleTimeMillis;
}
public void setMaxEvictableIdleTimeMillis(long maxEvictableIdleTimeMillis) {
this.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis;
}
public String getValidationQuery() {
return validationQuery;
}
public void setValidationQuery(String validationQuery) {
this.validationQuery = validationQuery;
}
public int getValidationQueryTimeout() {
return validationQueryTimeout;
}
public void setValidationQueryTimeout(int validationQueryTimeout) {
this.validationQueryTimeout = validationQueryTimeout;
}
public boolean isTestOnBorrow() {
return testOnBorrow;
}
public void setTestOnBorrow(boolean testOnBorrow) {
this.testOnBorrow = testOnBorrow;
}
public boolean isTestOnReturn() {
return testOnReturn;
}
public void setTestOnReturn(boolean testOnReturn) {
this.testOnReturn = testOnReturn;
}
public boolean isTestWhileIdle() {
return testWhileIdle;
}
public void setTestWhileIdle(boolean testWhileIdle) {
this.testWhileIdle = testWhileIdle;
}
public boolean isPoolPreparedStatements() {
return poolPreparedStatements;
}
public void setPoolPreparedStatements(boolean poolPreparedStatements) {
this.poolPreparedStatements = poolPreparedStatements;
}
public int getMaxOpenPreparedStatements() {
return maxOpenPreparedStatements;
}
public void setMaxOpenPreparedStatements(int maxOpenPreparedStatements) {
this.maxOpenPreparedStatements = maxOpenPreparedStatements;
}
public boolean isSharePreparedStatements() {
return sharePreparedStatements;
}
public void setSharePreparedStatements(boolean sharePreparedStatements) {
this.sharePreparedStatements = sharePreparedStatements;
}
public String getFilters() {
return filters;
}
public void setFilters(String filters) {
this.filters = filters;
}
}

33
threadconnectiondemo/src/main/java/com/woniu/connection/properties/DynamicDataSourceProperties.java

@ -0,0 +1,33 @@
/**
* Copyright (c) 2018 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有侵权必究
*/
package com.woniu.connection.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 多数据源属性
*
* @author 蜗牛
* @since 1.0.0
*/
@ConfigurationProperties(prefix = "dynamic")
public class DynamicDataSourceProperties {
private Map<String, DataSourceProperties> datasource = new LinkedHashMap<>();
public Map<String, DataSourceProperties> getDatasource() {
return datasource;
}
public void setDatasource(Map<String, DataSourceProperties> datasource) {
this.datasource = datasource;
}
}

15
threadconnectiondemo/src/main/java/com/woniu/connection/service/AService.java

@ -0,0 +1,15 @@
package com.woniu.connection.service;
import org.springframework.stereotype.Service;
@Service
public class AService {
public void C() {
String s = DealService.threadLocal.get();
//做处理
System.out.println(s);
DealService.threadLocal.remove();
}
}

64
threadconnectiondemo/src/main/java/com/woniu/connection/service/AccountService.java

@ -0,0 +1,64 @@
package com.woniu.connection.service;
import com.woniu.connection.dao.AccountDao;
import com.woniu.connection.utils.JdbcUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.sql.Connection;
import java.sql.SQLException;
/*
*
* 事务的使用注意点:
* 1. service层和dao层的连接对象保持一致
* 2. 每个线程的connection对象必须前后一致, 线程隔离
*
* 常规的解决方案
* 1. 传参 : 将service层的connection对象直接传递到dao层
* 2. 加锁
*
* 常规解决方案的弊端:
* 1. 提高代码耦合度
* 2. 降低程序性能
* */
@Service
public class AccountService {
@Autowired
private AccountDao accountDao;
@Autowired
private JdbcUtils jdbcUtils;
//转账
public boolean transfer(String outUser, String inUser, int money) {
Connection conn = null;
try {
//1. 开启事务
conn = jdbcUtils.getConnection();
conn.setAutoCommit(false);
// 转出
accountDao.out(outUser, money);
//算术异常: 模拟转出成功,转入失败
int i = 1 / 0;
// 转入
accountDao.in(inUser, money);
//2. 成功提交
jdbcUtils.commitAndClose(conn);
} catch (Exception e) {
e.printStackTrace();
//2. 或者失败回滚
jdbcUtils.rollbackAndClose(conn);
return false;
}
return true;
}
}

28
threadconnectiondemo/src/main/java/com/woniu/connection/service/DealService.java

@ -0,0 +1,28 @@
package com.woniu.connection.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class DealService {
static final ThreadLocal<String> threadLocal = new ThreadLocal();
@Autowired
private AService aService;
public void dealTransfer() {
String address = "nanjing";
threadLocal.set(address);
A();
}
private void A() {
B();
}
private void B() {
aService.C();
}
}

21
threadconnectiondemo/src/main/java/com/woniu/connection/service/LoginService.java

@ -0,0 +1,21 @@
package com.woniu.connection.service;
import com.woniu.connection.entity.User;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@Service
public class LoginService {
public User login(String userName, String passWord) {
//假设登录成功
if (!StringUtils.isEmpty(userName)&& !StringUtils.isEmpty(passWord)) {
User user1 = new User();
user1.setUserName("蜗牛");
return user1;
}
return null;
}
}

78
threadconnectiondemo/src/main/java/com/woniu/connection/utils/JdbcUtils.java

@ -0,0 +1,78 @@
package com.woniu.connection.utils;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.sql.Connection;
import java.sql.SQLException;
@Component
public class JdbcUtils {
static ThreadLocal<Connection> tl = new ThreadLocal<>();
@Autowired
private DruidDataSource dataSource;
// 获取连接
/*
* 原本: 直接从连接池中获取连接
* 现在:
* 1. 直接获取当前线程绑定的连接对象
* 2. 如果连接对象是空的
* 2.1 再去连接池中获取连接
* 2.2 将此连接对象跟当前线程进行绑定
* */
public Connection getConnection() throws SQLException {
Connection conn = tl.get();
if(conn == null){
conn = dataSource.getConnection();
tl.set(conn);
}
return conn;
}
//释放资源
public void release(AutoCloseable... ios){
for (AutoCloseable io : ios) {
if(io != null){
try {
io.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public void commitAndClose(Connection conn) {
try {
if(conn != null){
//提交事务
conn.commit();
//解绑当前线程绑定的连接对象
tl.remove();
//释放连接
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public void rollbackAndClose(Connection conn) {
try {
if(conn != null){
//回滚事务
conn.rollback();
//解绑当前线程绑定的连接对象
tl.remove();
//释放连接
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}

64
threadconnectiondemo/src/main/java/com/woniu/connection/utils/R.java

@ -0,0 +1,64 @@
/**
* Copyright (c) 2016-2019 人人开源 All rights reserved.
*
* https://www.renren.io
*
* 版权所有侵权必究
*/
package com.woniu.connection.utils;
import org.apache.http.HttpStatus;
import java.util.HashMap;
import java.util.Map;
/**
* 返回数据
*
* @author Mark sunlightcs@gmail.com
*/
public class R extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public R() {
put("code", 0);
put("msg", "success");
}
public static R error() {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
}
public static R error(String msg) {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
}
public static R error(int code, String msg) {
R r = new R();
r.put("code", code);
r.put("msg", msg);
return r;
}
public static R ok(String msg) {
R r = new R();
r.put("msg", msg);
return r;
}
public static R ok(Map<String, Object> map) {
R r = new R();
r.putAll(map);
return r;
}
public static R ok() {
return new R();
}
public R put(String key, Object value) {
super.put(key, value);
return this;
}
}

16
threadconnectiondemo/src/main/java/com/woniu/connection/utils/ThreadSafeFormatterUtil.java

@ -0,0 +1,16 @@
package com.woniu.connection.utils;
import java.text.SimpleDateFormat;
public class ThreadSafeFormatterUtil {
public static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal = new ThreadLocal<SimpleDateFormat>() {
//创建一份 SimpleDateFormat 对象
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
}
};
}

126
threadconnectiondemo/src/main/java/com/woniu/connection/web/WebController.java

@ -0,0 +1,126 @@
package com.woniu.connection.web;
import com.woniu.connection.constant.AuthServerConstant;
import com.woniu.connection.entity.User;
import com.woniu.connection.interceptor.LoginUserInterceptor;
import com.woniu.connection.service.AccountService;
import com.woniu.connection.service.DealService;
import com.woniu.connection.service.LoginService;
import com.woniu.connection.utils.R;
import com.woniu.connection.utils.ThreadSafeFormatterUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* 公众号 woniuxgg ,回复 源码
*/
@RestController
@RequestMapping("/app")
public class WebController {
@Autowired
private AccountService accountService;
/**
* ThreadLocal实战 代码演示 工作中是怎么使用的
* demo1 每个线程绑定一个连接 实现线程内隔离 控制事务
* @return
*/
@GetMapping("transfer")
public R transfer() {
// 模拟数据 : woniu 给 lili 转账 100
String outUser = "woniu";
String inUser = "lili";
int money = 100;
boolean result = accountService.transfer(outUser, inUser, money);
if (!result) {
System.out.println("转账失败!");
} else {
System.out.println("转账成功!");
}
return R.ok();
}
@Autowired
private LoginService loginService;
/**
* demo2 每个线程内需要保存全局变量例如在拦截器中获取用户信息可以让不同方法直接使用避免参数传递的麻烦
*
* @return
*/
@GetMapping("login")
public R login(@RequestParam String userName, @RequestParam String passWord, HttpServletRequest httpServletRequest) {
//用户登录 返回实体类
User userLogin = loginService.login(userName,passWord);
//放入session中
HttpSession session = httpServletRequest.getSession();
session.setAttribute(AuthServerConstant.LOGIN_USER, userLogin);
return R.ok();
}
/**
* 获得用户信息 localhost:8080/app/getUser
* @return
*/
@GetMapping("getUser")
public R getUser() {
User user = LoginUserInterceptor.loginUser.get();
return R.ok().put("user",user);
}
@Autowired
private DealService dealService;
/**
* demo3 在方法调用的过程中 用来代替参数传值
* @return
*/
@GetMapping("dealTransfer")
public R dealTransfer() {
dealService.dealTransfer();
return R.ok();
}
/**
* demo4 每个线程需要一个独享对象通常是工具类典型需要使用的类有SimpleDateFormat
* 每个Thread内有自己的实例副本不共享
* @return
*/
@GetMapping("dealDate")
public R dealDate() {
for (int i = 0; i < 30; i++) {
new Thread(new Runnable() {
@Override
public void run() {
SimpleDateFormat simpleDateFormat = ThreadSafeFormatterUtil.dateFormatThreadLocal.get();
String date = simpleDateFormat.format(new Date());
System.out.println(date);
}
}).start();
}
return R.ok();
}
}

39
threadconnectiondemo/src/main/resources/application.yml

@ -0,0 +1,39 @@
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: 123456
initial-size: 10
max-active: 100
min-idle: 10
max-wait: 60000
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
#Oracle需要打开注释
#validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
stat-view-servlet:
enabled: true
url-pattern: /druid/*
#login-username: admin
#login-password: admin
filter:
stat:
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: false
wall:
config:
multi-statement-allow: true
server:
port: 8080

39
threadconnectiondemo/target/classes/application.yml

@ -0,0 +1,39 @@
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: 123456
initial-size: 10
max-active: 100
min-idle: 10
max-wait: 60000
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
#Oracle需要打开注释
#validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
stat-view-servlet:
enabled: true
url-pattern: /druid/*
#login-username: admin
#login-password: admin
filter:
stat:
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: false
wall:
config:
multi-statement-allow: true
server:
port: 8080

BIN
threadconnectiondemo/target/classes/com/woniu/connection/MainApplication.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/config/DynamicDataSourceConfig.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/config/DynamicDataSourceFactory.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/config/WebConfig.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/constant/AuthServerConstant.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/dao/AccountDao.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/entity/User.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/interceptor/LoginUserInterceptor.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/properties/DataSourceProperties.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/properties/DynamicDataSourceProperties.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/service/AService.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/service/AccountService.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/service/DealService.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/service/LoginService.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/utils/JdbcUtils.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/utils/R.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/utils/ThreadSafeFormatterUtil$1.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/utils/ThreadSafeFormatterUtil.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/web/WebController$1.class

Binary file not shown.

BIN
threadconnectiondemo/target/classes/com/woniu/connection/web/WebController.class

Binary file not shown.

92
threadconnectiondemo/threadconnectiondemo.iml

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
<facet type="web" name="Web">
<configuration>
<webroots />
<sourceRoots>
<root url="file://$MODULE_DIR$/src/main/java" />
<root url="file://$MODULE_DIR$/src/main/resources" />
</sourceRoots>
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-boot-starter:3.5.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus:3.5.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-extension:3.5.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-core:3.5.2" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-annotation:3.5.2" level="project" />
<orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:4.4" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.5.10" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:2.0.7" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.71" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.2.71" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-common:1.2.71" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains:annotations:13.0" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.71" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.zaxxer:HikariCP:3.2.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-tx:5.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.projectlombok:lombok:1.18.24" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.13" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.12" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.11" level="project" />
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:8.0.29" level="project" />
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
<orderEntry type="library" name="Maven: jakarta.validation:jakarta.validation-api:2.0.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.11.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.11.2" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.28" level="project" />
<orderEntry type="library" name="Maven: javax.annotation:javax.annotation-api:1.3.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.1.9.RELEASE" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.23" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.9.9.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.9.0" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.9.9" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.9" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.9" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.9" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.1.8.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.24" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:9.0.24" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.24" level="project" />
<orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:6.0.17.Final" level="project" />
<orderEntry type="library" name="Maven: javax.validation:validation-api:2.0.1.Final" level="project" />
<orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.3.3.Final" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-web:5.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:fastjson:1.2.15" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:druid-spring-boot-starter:1.1.13" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:druid:1.1.13" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.28" level="project" />
</component>
</module>
Loading…
Cancel
Save