diff --git a/book-service/pom.xml b/book-service/pom.xml index 0a054e5..45fe15c 100644 --- a/book-service/pom.xml +++ b/book-service/pom.xml @@ -21,7 +21,7 @@ com.alibaba.cloud - spring-cloud-starter-alibaba-sentinel + spring-cloud-starter-alibaba-seata com.alibaba.cloud diff --git a/book-service/src/main/java/com/test/BookApplication.java b/book-service/src/main/java/com/test/BookApplication.java index 7c25a8d..af8b52b 100644 --- a/book-service/src/main/java/com/test/BookApplication.java +++ b/book-service/src/main/java/com/test/BookApplication.java @@ -1,6 +1,7 @@ package com.test; import com.apple.eawt.Application; +import io.seata.spring.annotation.datasource.EnableAutoDataSourceProxy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -11,6 +12,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; * @author yovinchen * @Create 2023/8/14 16:23 */ +@EnableAutoDataSourceProxy @SpringBootApplication public class BookApplication { public static void main(String[] args) { diff --git a/book-service/src/main/java/com/test/controller/BookController.java b/book-service/src/main/java/com/test/controller/BookController.java index b8f6973..172213c 100644 --- a/book-service/src/main/java/com/test/controller/BookController.java +++ b/book-service/src/main/java/com/test/controller/BookController.java @@ -26,4 +26,15 @@ public class BookController { System.out.println("调用图书服务"); return service.getBookById(bid); } + + @RequestMapping("/book/remain/{bid}") + public int bookRemain(@PathVariable("bid") int uid){ + return service.getRemain(uid); + } + + @RequestMapping("/book/borrow/{bid}") + public boolean bookBorrow(@PathVariable("bid") int uid){ + int remain = service.getRemain(uid); + return service.setRemain(uid, remain - 1); + } } diff --git a/book-service/src/main/java/com/test/mapper/BookMapper.java b/book-service/src/main/java/com/test/mapper/BookMapper.java index c582126..2ac1ca7 100644 --- a/book-service/src/main/java/com/test/mapper/BookMapper.java +++ b/book-service/src/main/java/com/test/mapper/BookMapper.java @@ -3,6 +3,7 @@ package com.test.mapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import com.test.entity.Book; +import org.apache.ibatis.annotations.Update; /** * ClassName: BookMapper @@ -16,4 +17,10 @@ public interface BookMapper { @Select("select * from DB_BOOK where bid = #{bid}") Book getBookById(int bid); + + @Select("select count from DB_BOOK where bid = #{bid}") + int getRemain(int bid); + + @Update("update DB_BOOK set count = #{count} where bid = #{bid}") + int setRemain(int bid, int count); } diff --git a/book-service/src/main/java/com/test/service/BookService.java b/book-service/src/main/java/com/test/service/BookService.java index f5dcdaa..fd40516 100644 --- a/book-service/src/main/java/com/test/service/BookService.java +++ b/book-service/src/main/java/com/test/service/BookService.java @@ -11,4 +11,10 @@ import com.test.entity.Book; */ public interface BookService { Book getBookById(int bid); + + boolean setRemain(int uid, int i); + + int getRemain(int uid); + + } diff --git a/book-service/src/main/java/com/test/service/impl/BookServiceImpl.java b/book-service/src/main/java/com/test/service/impl/BookServiceImpl.java index a595169..0880e80 100644 --- a/book-service/src/main/java/com/test/service/impl/BookServiceImpl.java +++ b/book-service/src/main/java/com/test/service/impl/BookServiceImpl.java @@ -24,4 +24,14 @@ public class BookServiceImpl implements BookService { public Book getBookById(int bid) { return mapper.getBookById(bid); } + + @Override + public boolean setRemain(int bid, int count) { + return mapper.setRemain(bid, count) > 0; + } + + @Override + public int getRemain(int bid) { + return mapper.getRemain(bid); + } } diff --git a/book-service/src/main/resources/application.yml b/book-service/src/main/resources/application.yml index fe585bb..a89e1b6 100644 --- a/book-service/src/main/resources/application.yml +++ b/book-service/src/main/resources/application.yml @@ -14,8 +14,20 @@ spring: discovery: # 配置Nacos注册中心地址 server-addr: localhost:8848 - namespace: dd668135-0bfe-489f-ab2b-24aefb21d156 - sentinel: - transport: - # 添加监控页面地址即可 - dashboard: localhost:8858 +seata: + # 注册 + registry: + # 使用Nacos + type: nacos + nacos: + # 使用Seata的命名空间,这样才能正确找到Seata服务,由于组使用的是SEATA_GROUP,配置默认值就是,就不用配了 + namespace: c0495138-b5b3-440d-8f1c-dc8cc9ba5fbc + username: nacos + password: nacos + # 配置 + config: + type: nacos + nacos: + namespace: c0495138-b5b3-440d-8f1c-dc8cc9ba5fbc + username: nacos + password: nacos diff --git a/borrow-service/pom.xml b/borrow-service/pom.xml index 988ad69..d5af544 100644 --- a/borrow-service/pom.xml +++ b/borrow-service/pom.xml @@ -20,7 +20,7 @@ com.alibaba.cloud - spring-cloud-starter-alibaba-sentinel + spring-cloud-starter-alibaba-seata org.springframework.cloud diff --git a/borrow-service/src/main/java/com/test/BorrowApplication.java b/borrow-service/src/main/java/com/test/BorrowApplication.java index 3ed43f3..ff6570a 100644 --- a/borrow-service/src/main/java/com/test/BorrowApplication.java +++ b/borrow-service/src/main/java/com/test/BorrowApplication.java @@ -1,5 +1,6 @@ package com.test; +import io.seata.spring.annotation.datasource.EnableAutoDataSourceProxy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; @@ -12,6 +13,7 @@ import org.springframework.cloud.openfeign.EnableFeignClients; * @Create 2023/8/14 16:25 */ @EnableFeignClients +@EnableAutoDataSourceProxy @SpringBootApplication public class BorrowApplication { public static void main(String[] args) { diff --git a/borrow-service/src/main/java/com/test/controller/BorrowController.java b/borrow-service/src/main/java/com/test/controller/BorrowController.java index 1fb5027..c368cee 100644 --- a/borrow-service/src/main/java/com/test/controller/BorrowController.java +++ b/borrow-service/src/main/java/com/test/controller/BorrowController.java @@ -1,14 +1,10 @@ package com.test.controller; -import com.alibaba.csp.sentinel.annotation.SentinelResource; -import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.fastjson.JSONObject; -import com.test.entity.User; import com.test.entity.UserBorrowDetail; import com.test.service.BorrowService; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @@ -28,58 +24,20 @@ public class BorrowController { @Resource BorrowService service; - @RequestMapping("/borrow1/{uid}") - UserBorrowDetail findUserBorrows1(@PathVariable("uid") int uid) { + @RequestMapping("/borrow/{uid}") + UserBorrowDetail findUserBorrows(@PathVariable("uid") int uid){ return service.getUserBorrowDetailByUid(uid); } - @RequestMapping("/borrow2/{uid}") - @SentinelResource(value = "findUserBorrows2", blockHandler = "test") - UserBorrowDetail findUserBorrows2(@PathVariable("uid") int uid) throws InterruptedException { - throw new RuntimeException(); - } + @RequestMapping("/borrow/take/{uid}/{bid}") + JSONObject borrow(@PathVariable("uid") int uid, + @PathVariable("bid") int bid){ + service.doBorrow(uid, bid); - UserBorrowDetail test(int uid, BlockException e) { -// 输出降级异常 - System.out.println(e.getClass()); - return new UserBorrowDetail(new User(), Collections.emptyList()); - } - - @RequestMapping("/blocked") - JSONObject blocked() { JSONObject object = new JSONObject(); - object.put("code", 403); - object.put("success", false); - object.put("massage", "您的请求频率过快,请稍后再试!"); + object.put("code", "200"); + object.put("success", true); + object.put("message", "借阅成功!"); return object; } - - // @RequestMapping("/test") -// @SentinelResource(value = "test", fallback = "except", //fallback指定出现异常时的替代方案 -// blockHandler = "blocked", -//// 特别注意这种方式会在没有配置blockHandler的情况下,将Sentinel机制内(也就是限流的异常)的异常也一并处理了,如果配置了blockHandler,那么在出现限流时,依然只会执行blockHandler指定的替代方案(因为限流是在方法执行之前进行的) -// exceptionsToIgnore = IOException.class) -// //忽略那些异常,也就是说这些异常出现时不使用替代方案 -// String test() { -// throw new RuntimeException("HelloWorld!"); -// } -// -// //替代方法必须和原方法返回值和参数一致,最后可以添加一个Throwable作为参数接受异常 -// String except(Throwable t) { -// return t.getMessage(); -// } - @RequestMapping("/test") - @SentinelResource("test") - //注意这里需要添加@SentinelResource才可以,用户资源名称就使用这里定义的资源名称 - String findUserBorrows2(@RequestParam(value = "a", required = false) String a, @RequestParam(value = "b", required = false) String b, @RequestParam(value = "c", required = false) String c) { - return "请求成功!a = " + a + ", b = " + b + ", c = " + c; - } - - //模拟慢调用 - @RequestMapping("/slowCall/{uid}") - String slowCall(@PathVariable("uid") int uid) throws InterruptedException { - //模拟慢调用 - Thread.sleep(1000); - return "Hello World"; - } } diff --git a/borrow-service/src/main/java/com/test/mapper/BorrowMapper.java b/borrow-service/src/main/java/com/test/mapper/BorrowMapper.java index 385ef15..99084e0 100644 --- a/borrow-service/src/main/java/com/test/mapper/BorrowMapper.java +++ b/borrow-service/src/main/java/com/test/mapper/BorrowMapper.java @@ -1,6 +1,7 @@ package com.test.mapper; import com.test.entity.Borrow; +import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; @@ -23,4 +24,7 @@ public interface BorrowMapper { @Select("select * from DB_BORROW where bid = #{bid} and uid = #{uid}") Borrow getBorrow(int uid, int bid); + + @Insert("insert into db_borrow(uid, bid) values (#{uid},#{bid})") + int addBorrow(int uid, int bid); } diff --git a/borrow-service/src/main/java/com/test/service/BorrowService.java b/borrow-service/src/main/java/com/test/service/BorrowService.java index 4561123..8020e60 100644 --- a/borrow-service/src/main/java/com/test/service/BorrowService.java +++ b/borrow-service/src/main/java/com/test/service/BorrowService.java @@ -13,4 +13,5 @@ import com.test.entity.UserBorrowDetail; public interface BorrowService { UserBorrowDetail getUserBorrowDetailByUid(int uid); + boolean doBorrow(int uid, int bid); } diff --git a/borrow-service/src/main/java/com/test/service/client/BookClient.java b/borrow-service/src/main/java/com/test/service/client/BookClient.java index 06e84bb..2421af0 100644 --- a/borrow-service/src/main/java/com/test/service/client/BookClient.java +++ b/borrow-service/src/main/java/com/test/service/client/BookClient.java @@ -17,4 +17,10 @@ public interface BookClient { @RequestMapping("/book/{bid}") Book getBookById(@PathVariable("bid") int bid); + + @RequestMapping("/book/borrow/{bid}") + boolean bookBorrow(@PathVariable("bid") int bid); + + @RequestMapping("/book/remain/{bid}") + int bookRemain(@PathVariable("bid") int bid); } diff --git a/borrow-service/src/main/java/com/test/service/client/UserClient.java b/borrow-service/src/main/java/com/test/service/client/UserClient.java index c167aa2..1784e03 100644 --- a/borrow-service/src/main/java/com/test/service/client/UserClient.java +++ b/borrow-service/src/main/java/com/test/service/client/UserClient.java @@ -17,4 +17,10 @@ public interface UserClient { @RequestMapping("/user/{uid}") User getUserById(@PathVariable("uid") int uid); + + @RequestMapping("/user/borrow/{uid}") + boolean userBorrow(@PathVariable("uid") int uid); + + @RequestMapping("/user/remain/{uid}") + int userRemain(@PathVariable("uid") int uid); } diff --git a/borrow-service/src/main/java/com/test/service/client/UserClientImpl.java b/borrow-service/src/main/java/com/test/service/client/UserClientImpl.java deleted file mode 100644 index 6f87680..0000000 --- a/borrow-service/src/main/java/com/test/service/client/UserClientImpl.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.test.service.client; - -import com.test.entity.User; -import org.springframework.stereotype.Component; - -/** - * ClassName: UserClientImpl - * Package: com.test.service.client - * - * @author yovinchen - * @Create 2023/8/17 22:25 - */ -@Component -public class UserClientImpl implements UserClient{ - @Override - public User getUserById(int uid) { - User user = new User(); - user.setName("我是替代方案"); - return user; - } -} diff --git a/borrow-service/src/main/java/com/test/service/impl/BorrowServiceImpl.java b/borrow-service/src/main/java/com/test/service/impl/BorrowServiceImpl.java index 5974465..0f5e93b 100644 --- a/borrow-service/src/main/java/com/test/service/impl/BorrowServiceImpl.java +++ b/borrow-service/src/main/java/com/test/service/impl/BorrowServiceImpl.java @@ -1,8 +1,5 @@ package com.test.service.impl; - -import com.alibaba.csp.sentinel.annotation.SentinelResource; -import com.alibaba.csp.sentinel.slots.block.BlockException; import com.test.entity.Book; import com.test.entity.Borrow; import com.test.entity.User; @@ -11,6 +8,7 @@ import com.test.mapper.BorrowMapper; import com.test.service.BorrowService; import com.test.service.client.BookClient; import com.test.service.client.UserClient; +import io.seata.spring.annotation.GlobalTransactional; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -38,7 +36,6 @@ public class BorrowServiceImpl implements BorrowService { BookClient bookClient; @Override - @SentinelResource(value = "details", blockHandler = "blocked") public UserBorrowDetail getUserBorrowDetailByUid(int uid) { List borrow = mapper.getBorrowsByUid(uid); User user = userClient.getUserById(uid); @@ -49,8 +46,26 @@ public class BorrowServiceImpl implements BorrowService { return new UserBorrowDetail(user, bookList); } - //替代方案,注意参数和返回值需要保持一致,并且参数最后还需要额外添加一个BlockException - public UserBorrowDetail blocked(int uid, BlockException e) { - return new UserBorrowDetail(null, Collections.emptyList()); + @Override + @GlobalTransactional + public boolean doBorrow(int uid, int bid) { + //1. 判断图书和用户是否都支持借阅 + if(bookClient.bookRemain(bid) < 1) + throw new RuntimeException("图书数量不足"); + if(userClient.userRemain(uid) < 1) + throw new RuntimeException("用户借阅量不足"); + //2. 首先将图书的数量-1 + if(!bookClient.bookBorrow(bid)) + throw new RuntimeException("在借阅图书时出现错误!"); + //3. 添加借阅信息 + if(mapper.getBorrow(uid, bid) != null) + throw new RuntimeException("此书籍已经被此用户借阅了!"); + if(mapper.addBorrow(uid, bid) <= 0) + throw new RuntimeException("在录入借阅信息时出现错误!"); + //4. 用户可借阅-1 + if(!userClient.userBorrow(uid)) + throw new RuntimeException("在借阅时出现错误!"); + //完成 + return true; } } diff --git a/borrow-service/src/main/resources/application.yml b/borrow-service/src/main/resources/application.yml index 4eed866..7382b23 100644 --- a/borrow-service/src/main/resources/application.yml +++ b/borrow-service/src/main/resources/application.yml @@ -17,17 +17,23 @@ spring: # 将ephemeral修改为false,表示非临时实例(用于持续监控) ephemeral: false cluster-name: Chengdu - namespace: dd668135-0bfe-489f-ab2b-24aefb21d156 loadbalancer: nacos: enabled: true - sentinel: - transport: - # 添加监控页面地址即可 - dashboard: localhost:8858 - # 关闭Context收敛,这样被监控方法可以进行不同链路的单独控制 - web-context-unify: false - block-page: /blocked -feign: - circuitbreaker: - enabled: true +seata: + # 注册 + registry: + # 使用Nacos + type: nacos + nacos: + # 使用Seata的命名空间,这样才能正确找到Seata服务,由于组使用的是SEATA_GROUP,配置默认值就是,就不用配了 + namespace: c0495138-b5b3-440d-8f1c-dc8cc9ba5fbc + username: nacos + password: nacos + # 配置 + config: + type: nacos + nacos: + namespace: c0495138-b5b3-440d-8f1c-dc8cc9ba5fbc + username: nacos + password: nacos diff --git a/commons/src/main/java/com/test/entity/Book.java b/commons/src/main/java/com/test/entity/Book.java index 111e64b..351f73e 100644 --- a/commons/src/main/java/com/test/entity/Book.java +++ b/commons/src/main/java/com/test/entity/Book.java @@ -14,4 +14,5 @@ public class Book { int bid; String title; String des; + int count; } diff --git a/commons/src/main/java/com/test/entity/User.java b/commons/src/main/java/com/test/entity/User.java index 08b2432..73127dd 100644 --- a/commons/src/main/java/com/test/entity/User.java +++ b/commons/src/main/java/com/test/entity/User.java @@ -14,18 +14,13 @@ public class User { int uid; String name; String sex; + int book_count; - /** - * ClassName: Book - * Package: com.test.entity - * - * @author yovinchen - * @Create 2023/8/14 17:01 - */ @Data public static class Book { int bid; String title; String desc; + int book_count; } } diff --git a/user-service/pom.xml b/user-service/pom.xml index b133a7c..1f7e69c 100644 --- a/user-service/pom.xml +++ b/user-service/pom.xml @@ -20,7 +20,7 @@ com.alibaba.cloud - spring-cloud-starter-alibaba-sentinel + spring-cloud-starter-alibaba-seata org.springframework.cloud diff --git a/user-service/src/main/java/com/test/UserApplication.java b/user-service/src/main/java/com/test/UserApplication.java index d5cae82..8f14edd 100644 --- a/user-service/src/main/java/com/test/UserApplication.java +++ b/user-service/src/main/java/com/test/UserApplication.java @@ -1,5 +1,6 @@ package com.test; +import io.seata.spring.annotation.datasource.EnableAutoDataSourceProxy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -11,6 +12,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; * @Create 2023/8/14 16:26 */ @SpringBootApplication +@EnableAutoDataSourceProxy public class UserApplication { public static void main(String[] args) { SpringApplication.run(UserApplication.class, args); diff --git a/user-service/src/main/java/com/test/controller/UserController.java b/user-service/src/main/java/com/test/controller/UserController.java index 996d24c..c1b1da9 100644 --- a/user-service/src/main/java/com/test/controller/UserController.java +++ b/user-service/src/main/java/com/test/controller/UserController.java @@ -27,4 +27,15 @@ public class UserController { System.out.println("调用用户服务"); return service.getUserById(uid); } + + @RequestMapping("/user/remain/{uid}") + public int userRemain(@PathVariable("uid") int uid) { + return service.getRemain(uid); + } + + @RequestMapping("/user/borrow/{uid}") + public boolean userBorrow(@PathVariable("uid") int uid) { + int remain = service.getRemain(uid); + return service.setRemain(uid, remain - 1); + } } diff --git a/user-service/src/main/java/com/test/mapper/UserMapper.java b/user-service/src/main/java/com/test/mapper/UserMapper.java index 130e282..0edba40 100644 --- a/user-service/src/main/java/com/test/mapper/UserMapper.java +++ b/user-service/src/main/java/com/test/mapper/UserMapper.java @@ -3,6 +3,7 @@ package com.test.mapper; import com.test.entity.User; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; /** * ClassName: UserMapper @@ -15,4 +16,10 @@ import org.apache.ibatis.annotations.Select; public interface UserMapper { @Select("select * from DB_USER where uid = #{uid}") User getUserById(int uid); + + @Select("select book_count from DB_USER where uid = #{uid}") + int getUserBookRemain(int uid); + + @Update("update DB_USER set book_count = #{count} where uid = #{uid}") + int updateBookCount(int uid, int count); } diff --git a/user-service/src/main/java/com/test/service/UserService.java b/user-service/src/main/java/com/test/service/UserService.java index eca1b5c..7377747 100644 --- a/user-service/src/main/java/com/test/service/UserService.java +++ b/user-service/src/main/java/com/test/service/UserService.java @@ -11,4 +11,8 @@ import com.test.entity.User; */ public interface UserService { User getUserById(int uid); + + int getRemain(int uid); + + boolean setRemain(int uid, int count); } diff --git a/user-service/src/main/java/com/test/service/impl/UserServiceImpl.java b/user-service/src/main/java/com/test/service/impl/UserServiceImpl.java index 5c50457..320302e 100644 --- a/user-service/src/main/java/com/test/service/impl/UserServiceImpl.java +++ b/user-service/src/main/java/com/test/service/impl/UserServiceImpl.java @@ -24,4 +24,15 @@ public class UserServiceImpl implements UserService { public User getUserById(int uid) { return mapper.getUserById(uid); } + + @Override + public int getRemain(int uid) { + return mapper.getUserBookRemain(uid); + } + + @Override + public boolean setRemain(int uid, int count) { + return mapper.updateBookCount(uid, count) > 0; + } + } diff --git a/user-service/src/main/resources/application.yml b/user-service/src/main/resources/application.yml index 72a74f1..b1d32ca 100644 --- a/user-service/src/main/resources/application.yml +++ b/user-service/src/main/resources/application.yml @@ -4,8 +4,20 @@ spring: discovery: # 配置Nacos注册中心地址 server-addr: localhost:8848 - namespace: dd668135-0bfe-489f-ab2b-24aefb21d156 - sentinel: - transport: - # 添加监控页面地址即可 - dashboard: localhost:8858 +seata: + # 注册 + registry: + # 使用Nacos + type: nacos + nacos: + # 使用Seata的命名空间,这样才能正确找到Seata服务,由于组使用的是SEATA_GROUP,配置默认值就是,就不用配了 + namespace: c0495138-b5b3-440d-8f1c-dc8cc9ba5fbc + username: nacos + password: nacos + # 配置 + config: + type: nacos + nacos: + namespace: c0495138-b5b3-440d-8f1c-dc8cc9ba5fbc + username: nacos + password: nacos