diff --git a/java/springboot系列/2.springboot事务处理(自动或手动).md b/java/springboot系列/2.springboot事务处理(自动或手动).md new file mode 100644 index 0000000..cda6aaf --- /dev/null +++ b/java/springboot系列/2.springboot事务处理(自动或手动).md @@ -0,0 +1,120 @@ +--- +id: "20190619" +date: "2019/06/19 10:38:00" +title: "springboot事务处理(自动/手动事务)" +tags: ["java", "springboot", "transaction"] +categories: + - "java" + - "spring boot学习" +--- + +![缇娜](https://raw.githubusercontent.com/FleyX/files/master/blogImg/20190619175857.png) + +今天写代码的时候遇到了这样的一个问题:通过`this.saveData()`调用`saveData`方法,这个方法被`@Transactional`注解,期望在 saveData 抛出错误时能够回滚数据库,结果事务并没有生效。然后便对 spring boot 的事务进行了一次更深入的学习。 + +学习笔记如下: + +要使用事务首先需要开启事务,在启动类中加入注解:`@EnableTransactionManagement` + +主要内容如下: + +- 自动事务及其原理 +- 手动事务的使用 + +# 自动事务 + +通过`@Transactional`开启事务。在`UserService`中定义一个事务方法`save`.然后在`UserController`中注入`UserDao`,并调用`save`方法。 + +```java +@Service +public class UserService{ + @Autowired + private UserDao dao; + + @Transactional(rollbackFor = Exception.class) + public void save(){ + //一些数据库操作 + } +} + +@RestController +public class UserController{ + + @Autowired + private UserService service; + + @GetMapping("/") + public String getInfo(){ + service.save(); + return "OK"; + } +} +``` + +如上是一个典型的自动事务调用过程。但是如果是这样一种情况呢?现在`UserService`中增加一个方法`saveAll`,并在该方法中循环调用`save`方法,然后想让每一次的`save`方法都有事务支持,且相互不影响。`saveAll`代码如下: + +```java +public void saveAll(){ + for(int i=0;i<10;i++){ + this.save(); + } +} + +``` + +通常会想当然的认为 save 方法被`@Transactional`注解了,那么它就是支持事务的了,这种写法能够实现我们想要的效果。然而实际是不行的。 + +## 为什么 this 调用就不行呢? + +原因就在**Spring**.spring 是一个 IOC 容器,它来统一管理所有的类,然后你想要用某个类的时候,它就会把这个类注入进入。关键就在这里:注入的这个类并**不是这个类本身**,然后这个类的**代理**。以代码来举例: + +```java +class UserController{ + + @Autowired + UserService userService; + + public void doSomeThing(){ + userService.save(); + } +} +``` + +通过`@Autowired`注入的 userService 实际上并不是 UserService 的实例,userService 指向地址和这个类实例中`this`所指向的并不相同。实际调用`save`方法的并不是`UserController`类,而是`Spring`,这也就能解释为什么 Spring 能够帮我进行进行很多操作,比如自动事务,错误处理等。 + +如果我们通过 this 来调用 save 方法,显然是直接调用,不经过 spring 的代理,也就没有自动事务了。 + +那么如何才能实现上面想要的效果呢? + +很简单,通过`AopContext.currentProxy()`来获取当前类的代理对象,这样调用`save`方法时就有自动事务了。 + +或者使用手动事务 + +# 手动事务 + +手动事务就是通过代码来显式的进行事务操作。使用方法如下: + +```java +// 需要先注入如下两个类 +@Autowired +DataSourceTransactionManager dataSourceTransactionManager; +@Autowired +TransactionDefinition transactionDefinition; + +public void saveAll(){ + //开启事务 + TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); + try{ + this.save(); + //提交事务 + dataSourceTransactionManager.commit(transactionStatus); + }catch(Exception e){ + //回滚事务 + dataSourceTransactionManager.rollback(transactionStatus); + } +} +``` + +OK! + +本文原创发布于:[www.tapme.top/blog/detail/20190619](https://www.tapme.top/blog/detail/20190619) diff --git a/java/springcloud实战/4.springCloud之Zuul服务路由.md b/java/springcloud实战/4.springCloud之Zuul服务路由.md index be51d90..9cd8ea4 100644 --- a/java/springcloud实战/4.springCloud之Zuul服务路由.md +++ b/java/springcloud实战/4.springCloud之Zuul服务路由.md @@ -2,20 +2,17 @@ id: "2019-01-03-19-19" date: "2019/01/03 19:19" title: "springCloud学习4(Zuul服务路由)" -tags: ["spring-boot", "spring-cloud","netflix-zuul","service-gateway"] -categories: -- "java" -- "springCloud实战" +tags: ["spring-boot", "spring-cloud", "netflix-zuul", "service-gateway"] +categories: + - "java" + - "springCloud实战" --- 镇博图 ![三笠](https://raw.githubusercontent.com/FleyX/files/master/blogImg/springcloud%E5%AE%9E%E6%88%98/20190108162523.jpeg) - **springcloud 总集:**[https://www.tapme.top/blog/detail/2019-02-28-11-33](https://www.tapme.top/blog/detail/2019-02-28-11-33) - - **本篇中 Zuul 版本为 1.x,目前最新的是 2.x,二者在过滤器的使用上有较大区别** **超长警告** @@ -176,7 +173,7 @@ zuul: routes: organizationservice: /org/** # 使用","分隔,“*”表示全部忽略 - ignored-services: 'organizationservice' + ignored-services: "organizationservice" ```   服务网关有一种常见模式是通过使用`/api`之类的标记来为所有服务调用添加前缀,可通过配置`prefix`属性来支持。用法如下: @@ -186,7 +183,7 @@ zuul: routes: organizationservice: /org/** # 使用","分隔,“*”表示全部忽略 - ignored-services: 'organizationservice' + ignored-services: "organizationservice" prefix: /api ``` @@ -229,7 +226,7 @@ zuul: serviceId: licensestatic organizationservice: /org/** # 使用","分隔,“*”表示全部忽略 - ignored-services: 'organizationservice' + ignored-services: "organizationservice" prefix: /api ribbon: @@ -247,7 +244,7 @@ licensestatic: **_问题又来了_** -  _禁用eureka支持会导致所有服务的地址都需要手动指定,ribbon不会再从eureka中获取服务实例信息。所以没办法混合使用_ +  _禁用 eureka 支持会导致所有服务的地址都需要手动指定,ribbon 不会再从 eureka 中获取服务实例信息。所以没办法混合使用_   目前有两种办法来规避这个问题: @@ -369,7 +366,6 @@ public class IdFilter extends ZuulFilter {   现在从 zuul 服务网关发往许可证服务的 http 请求已经携带了 id。 - ### b、后置过滤器   后置过滤器通常用于进行敏感信息过滤和响应记录。这里我们实现一个后置过滤器,将许可证服务请求的响应内容打印到控制台上同时把`id`header 插入到服务客户端请求的 response 中。 @@ -446,4 +442,4 @@ public class ResponseFilter extends ZuulFilter { **本篇代码存放于:**[github](https://github.com/FleyX/demo-project/tree/master/springcloud/spring-cloud%E6%9C%8D%E5%8A%A1%E8%B7%AF%E7%94%B1) -**本篇原创发布于:**[FleyX 的个人博客](tapme.top/blog/detail/2019-01-03-19-19) +**本篇原创发布于:**[https://tapme.top/blog/detail/2019-01-03-19-19](https://tapme.top/blog/detail/2019-01-03-19-19) diff --git a/二维码推广图.png b/二维码推广图.png new file mode 100644 index 0000000..816b3f0 Binary files /dev/null and b/二维码推广图.png differ