# yjj-springcloud **Repository Path**: tongstyle/yjj-springcloud ## Basic Information - **Project Name**: yjj-springcloud - **Description**: 后端:RestTemplate+SpringBoot2.3.12.RELEASE+SpringCloudAlibaba2.2.9.RELEASE+nacos 前端:vue3+vite+pinia 简易图书管理系统 需要环境,mysql,nacos,nodejs(版本>16,本文采用16.13.2) - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-05-20 - **Last Updated**: 2023-05-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 要求 1. 请使用springCloudAlibaba+springBoot+mybatis+maven搭建微服务项目。(20分) 2. 创建公共api服务(20分) 3. 创建服务生产者(包含增删改查功能)(25分) 4. 创建服务消费者(通过RestTemplate调用服务生产者)(20分) 5. 使用nacos监控已注册的服务生产者和服务消费者(15分) ## 结果 1. **使用springCloudAlibaba+springBoot+mybatis+maven搭建微服务项目**。(20分) 搭建步骤 1.创建多个SpringBoot项目 ![image-20230530105614374](assets/image-20230530105614374.png) ![image-20230530105624485](assets/image-20230530105624485.png) ![image-20230530105633705](assets/image-20230530105633705.png) ![image-20230530105701241](assets/image-20230530105701241.png) 2.在web服务中导入对应依赖(alibaba、nacos、mybatis...) 结果截图 ![image-20230530105726339](assets/image-20230530105726339.png) ```xml 1.8 UTF-8 UTF-8 2.3.12.RELEASE 2.2.9.RELEASE 0.9.1 io.jsonwebtoken jjwt ${jjwt.version} com.example cloud-entity 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-web com.alibaba.cloud spring-cloud-starter-alibaba-nacos-config com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.4 mysql mysql-connector-java runtime org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine org.springframework.boot spring-boot-dependencies ${spring-boot.version} pom import com.alibaba.cloud spring-cloud-alibaba-dependencies ${spring-cloud-alibaba.version} pom import ``` 2. **创建公共api服务**(20分) 搭建步骤 1. 标注@RestController、@Service、@MapperScan等注解 ![image-20230530110038765](assets/image-20230530110038765.png) ![image-20230530110054940](assets/image-20230530110054940.png) ![image-20230530110121543](assets/image-20230530110121543.png) ![image-20230530110141633](assets/image-20230530110141633.png) ![image-20230530110206811](assets/image-20230530110206811.png) 2. 使用@GetMapping、@PostMapping、@RequestMapping等注解标注api 结果截图 ![image-20230530110241858](assets/image-20230530110241858.png) ```java import com.example.entity.BookDto; import com.example.entity.JsonData; import com.example.user.domain.User; import com.example.user.service.UserService; import com.example.user.util.JwtUtil; import io.jsonwebtoken.Claims; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; import javax.servlet.http.HttpServletRequest; import java.util.List; @RestController @RequestMapping("user") public class UserController { /** * 远程数据接口--服务提供者 */ private static final String BOOK_URL = "http://localhost:8082/book/"; /** * 远程服务调用 */ @Autowired private RestTemplate restTemplate; @Autowired private UserService userService; /** * 获取用户及其书本 * * @param id 用户id * @return {@link Object} */ @GetMapping("/{id}") public Object getUser(@PathVariable("id") Long id) { User user = userService.getUserById(id); List forObject = restTemplate.getForObject(BOOK_URL + id, List.class); user.setBookDtoList(forObject); return JsonData.buildSuccess(user); } @PostMapping("/login") public Object checkLogin(@RequestBody User user) { String username = user.getUsername(); String password = user.getPassword(); return userService.checkLogin(username, password); } @PostMapping("/add-book") public Object addBook(@RequestBody BookDto book, HttpServletRequest request) { String token = request.getHeader("token"); Integer userId = Integer.valueOf(getUserIdByToken(token)); book.setUserId(userId); return JsonData.buildSuccess(restTemplate.postForObject(BOOK_URL + "add", book, int.class)); } @DeleteMapping("/remove-book/{bookId}") public Object removeBook(@PathVariable("bookId") Long bookId) { restTemplate.delete(BOOK_URL + "remove/" + bookId, int.class); return JsonData.buildSuccess(); } @PostMapping("/update-book") public Object updateBookByBookId(@RequestBody BookDto book, HttpServletRequest request) { String token = request.getHeader("token"); Integer userId = Integer.valueOf(getUserIdByToken(token)); book.setUserId(userId); return JsonData.buildSuccess(restTemplate.postForObject(BOOK_URL + "update", book, int.class)); } @GetMapping("/getBookByBookId/{id}") public Object getBookByBookId(@PathVariable("id") Long id) { BookDto forObject = restTemplate.getForObject(BOOK_URL + "getBookByBookId/" + id, BookDto.class); return JsonData.buildSuccess(forObject); } @GetMapping("/getBookByBookName/{name}") public Object getBookByBookName(@PathVariable("name") String name, HttpServletRequest request) { String token = request.getHeader("token"); Integer userId = Integer.valueOf(getUserIdByToken(token)); List forObject = restTemplate.getForObject(BOOK_URL + "getBookByBookName/" + name + "/" + userId, List.class); return JsonData.buildSuccess(forObject); } public String getUserIdByToken(String token) { Claims claims = null; try { claims = JwtUtil.parseJWT(token); } catch (Exception e) { throw new RuntimeException(e); } return claims.getSubject().split("login:")[1]; } } ``` 3. **创建服务生产者(包含增删改查功能)**(25分) 搭建步骤 1.编写对应的数据访问层sql ![image-20230530110357482](assets/image-20230530110357482.png) ![image-20230530110315753](assets/image-20230530110315753.png) ```xml id ,name,user_id delete from book where id = #{id,jdbcType=INTEGER} insert into book (id, name, user_id) values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{userId,jdbcType=INTEGER}) insert into book id, name, user_id, #{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{userId,jdbcType=INTEGER}, update book name = #{name,jdbcType=VARCHAR}, user_id = #{userId,jdbcType=INTEGER}, where id = #{id,jdbcType=INTEGER} update book set name = #{name,jdbcType=VARCHAR}, user_id = #{userId,jdbcType=INTEGER} where id = #{id,jdbcType=INTEGER} ``` 2.编写业务方法 ![image-20230530110422210](assets/image-20230530110422210.png) ```java import com.example.book.domain.Book; import java.util.List; public interface BookService { /** * 根据用户id获取书本集合 */ List getBooksByUserId(Long userId); int addBook(Book book); /** * 根据书本id删除书本 */ int removeBookByBookId(Long bookId); /** * 根据书本id更新书本信息 */ int updateBookByBookId(Book book); /** * 根据书本id获取书本 */ Book getBookByBookId(Long id); /** * 根据书本名获取书本集合(模糊查询) */ List getBookByBookName(String name, Integer userId); } ``` ![image-20230530110439065](assets/image-20230530110439065.png) ```java import com.example.book.domain.Book; import com.example.book.mapper.BookMapper; import com.example.book.service.BookService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class BookServiceImpl implements BookService { @Autowired private BookMapper bookMapper; @Override public List getBooksByUserId(Long userId) { return bookMapper.selectBooksByUserId(userId); } @Override public int addBook(Book book) { return bookMapper.insert(book); } @Override public int removeBookByBookId(Long bookId) { return bookMapper.deleteByPrimaryKey(bookId); } @Override public int updateBookByBookId(Book book) { return bookMapper.updateByPrimaryKey(book); } @Override public Book getBookByBookId(Long id) { return bookMapper.selectBookByBookId(id); } @Override public List getBookByBookName(String name,Integer userId) { return bookMapper.selectBookByBookName(name,userId); } } ``` 3.使用控制层方法调用对应的业务方法 ![image-20230530110502903](assets/image-20230530110502903.png) ```java import com.example.book.domain.Book; import com.example.book.service.BookService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("book") public class BookController { @Autowired private BookService bookService; @GetMapping("/getBookByBookId/{id}") public Book getBookByBookId(@PathVariable("id")Long id){ return bookService.getBookByBookId(id); } @GetMapping("/getBookByBookName/{name}/{userId}") public List getBookByBookName(@PathVariable("name")String name,@PathVariable("userId")Integer userId){ return bookService.getBookByBookName(name,userId); } @GetMapping("/{userId}") public List getBooksByUserId(@PathVariable("userId")Long userId){ return bookService.getBooksByUserId(userId); } @PostMapping("/add") public int addBook(@RequestBody Book book){ return bookService.addBook(book); } @DeleteMapping("/remove/{bookId}") public int removeBookByBookId(@PathVariable("bookId")Long bookId){ return bookService.removeBookByBookId(bookId); } @PostMapping("/update") public int updateBookByBookId(@RequestBody Book book){ return bookService.updateBookByBookId(book); } } ``` ![image-20230530110647622](assets/image-20230530110647622.png) ![image-20230530111314515](assets/image-20230530111314515.png) 4. **创建服务消费者(通过RestTemplate调用服务生产者)**(20分) 搭建步骤 1.将RestTemplate注入Spring容器 结果截图 ![image-20230530110719265](assets/image-20230530110719265.png) ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class ApplicationContextConfig{ @Bean public RestTemplate getTemplate() { return new RestTemplate(); } } ``` 2.在消费者端编写方法调用对应的生产者方法,并传递参数 结果截图 ![image-20230530110748691](assets/image-20230530110748691.png) ```java import com.example.entity.BookDto; import com.example.entity.JsonData; import com.example.user.domain.User; import com.example.user.service.UserService; import com.example.user.util.JwtUtil; import io.jsonwebtoken.Claims; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; import javax.servlet.http.HttpServletRequest; import java.util.List; @RestController @RequestMapping("user") public class UserController { /** * 远程数据接口--服务提供者 */ private static final String BOOK_URL = "http://localhost:8082/book/"; /** * 远程服务调用 */ @Autowired private RestTemplate restTemplate; @Autowired private UserService userService; /** * 获取用户及其书本 * * @param id 用户id * @return {@link Object} */ @GetMapping("/{id}") public Object getUser(@PathVariable("id") Long id) { User user = userService.getUserById(id); List forObject = restTemplate.getForObject(BOOK_URL + id, List.class); user.setBookDtoList(forObject); return JsonData.buildSuccess(user); } @PostMapping("/login") public Object checkLogin(@RequestBody User user) { String username = user.getUsername(); String password = user.getPassword(); return userService.checkLogin(username, password); } @PostMapping("/add-book") public Object addBook(@RequestBody BookDto book, HttpServletRequest request) { String token = request.getHeader("token"); Integer userId = Integer.valueOf(getUserIdByToken(token)); book.setUserId(userId); return JsonData.buildSuccess(restTemplate.postForObject(BOOK_URL + "add", book, int.class)); } @DeleteMapping("/remove-book/{bookId}") public Object removeBook(@PathVariable("bookId") Long bookId) { restTemplate.delete(BOOK_URL + "remove/" + bookId, int.class); return JsonData.buildSuccess(); } @PostMapping("/update-book") public Object updateBookByBookId(@RequestBody BookDto book, HttpServletRequest request) { String token = request.getHeader("token"); Integer userId = Integer.valueOf(getUserIdByToken(token)); book.setUserId(userId); return JsonData.buildSuccess(restTemplate.postForObject(BOOK_URL + "update", book, int.class)); } @GetMapping("/getBookByBookId/{id}") public Object getBookByBookId(@PathVariable("id") Long id) { BookDto forObject = restTemplate.getForObject(BOOK_URL + "getBookByBookId/" + id, BookDto.class); return JsonData.buildSuccess(forObject); } @GetMapping("/getBookByBookName/{name}") public Object getBookByBookName(@PathVariable("name") String name, HttpServletRequest request) { String token = request.getHeader("token"); Integer userId = Integer.valueOf(getUserIdByToken(token)); List forObject = restTemplate.getForObject(BOOK_URL + "getBookByBookName/" + name + "/" + userId, List.class); return JsonData.buildSuccess(forObject); } public String getUserIdByToken(String token) { Claims claims = null; try { claims = JwtUtil.parseJWT(token); } catch (Exception e) { throw new RuntimeException(e); } return claims.getSubject().split("login:")[1]; } } ``` 5. **使用nacos监控已注册的服务生产者和服务消费者**(15分) 搭建步骤 1.引入SpringCloudAlibaba依赖,注意版本冲突问题 ![image-20230530110813378](assets/image-20230530110813378.png) ![image-20230530110822115](assets/image-20230530110822115.png) ```xml 2.2.9.RELEASE com.alibaba.cloud spring-cloud-alibaba-dependencies ${spring-cloud-alibaba.version} pom import ``` 2.使用`@EnableDiscoveryClient`注解标识启动类,开启服务的注册发现功能 ![image-20230530110837134](assets/image-20230530110837134.png) ```java import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @EnableDiscoveryClient @MapperScan("com.example.user.mapper") @SpringBootApplication public class CloudUserApplication { public static void main(String[] args) { SpringApplication.run(CloudUserApplication.class, args); } } ``` 3.在`bootstrap.yml`内编写nacos地址 ![image-20230530111725527](assets/image-20230530111725527.png) ![image-20230530110850493](assets/image-20230530110850493.png) ```yaml spring: application: name: cloud-user cloud: nacos: # config: # serverAddr: localhost:8848 # group: DEFAULT_GROUP # fileExtension: yml discovery: serverAddr: localhost:8848 ``` ## 运行条件 > mysql **数据库名为`blue`** ```sql /* Navicat Premium Data Transfer Source Server : demo Source Server Type : MySQL Source Server Version : 80013 (8.0.13) Source Host : localhost:3306 Source Schema : blue Target Server Type : MySQL Target Server Version : 80013 (8.0.13) File Encoding : 65001 Date: 20/05/2023 12:17:54 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for book -- ---------------------------- DROP TABLE IF EXISTS `book`; CREATE TABLE `book` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '书名', `user_id` int(11) NULL DEFAULT NULL COMMENT '用户id', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of book -- ---------------------------- INSERT INTO `book` VALUES (1, '深入浅出MyBatis技术原理与实战', 1); INSERT INTO `book` VALUES (2, '深入浅出React和Redux', 1); INSERT INTO `book` VALUES (3, '《Spring Boot+Vue全栈开发实战》_王松_2018-12-01', 2); INSERT INTO `book` VALUES (4, 'Spring Boot 2+Thymeleaf企业应用实战', 2); INSERT INTO `book` VALUES (5, 'MongoDB游记之轻松入门到进阶', 2); INSERT INTO `book` VALUES (10, '测试ss', 1); INSERT INTO `book` VALUES (11, 'Spring长篇自传', 2); -- ---------------------------- -- Table structure for goods -- ---------------------------- DROP TABLE IF EXISTS `goods`; CREATE TABLE `goods` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '商品id', `img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '商品图片', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '商品名', `price` decimal(10, 2) NULL DEFAULT NULL COMMENT '商品价格', `ware` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '商品库存', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商品表' ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of goods -- ---------------------------- INSERT INTO `goods` VALUES (1, '0c2a419d-d09e-11ed-b7d4-b068e67533b2.jpg', '贴纸1', 5.00, '99'); INSERT INTO `goods` VALUES (2, '0cf1eb4e-d09e-11ed-b990-b068e67533b2.jpg', '王者荣耀皮肤', 88.00, '999'); INSERT INTO `goods` VALUES (3, '0ec56375-d09e-11ed-95cd-b068e67533b2.jpg', '小黑子', 15.00, '66'); INSERT INTO `goods` VALUES (4, '90b9763d-d09c-11ed-b7b7-b068e67533b2.jpg', '面具', 89.00, '59'); -- ---------------------------- -- Table structure for id_card -- ---------------------------- DROP TABLE IF EXISTS `id_card`; CREATE TABLE `id_card` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `id_card` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '身份证', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '姓名', `gender` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '性别', `birth` date NULL DEFAULT NULL COMMENT '生日', `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '地址', `user_id` int(11) NULL DEFAULT NULL COMMENT '用户id', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of id_card -- ---------------------------- INSERT INTO `id_card` VALUES (1, '11111111111111111', '黄永康', '男', '2023-05-03', '湖北', 2); INSERT INTO `id_card` VALUES (2, '2222222222222222222222', '黄晓美', '女', '2023-04-26', '湖南', 1); -- ---------------------------- -- Table structure for jwt -- ---------------------------- DROP TABLE IF EXISTS `jwt`; CREATE TABLE `jwt` ( `jwt_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'jwt主键', `jwt_content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'jwt内容', PRIMARY KEY (`jwt_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of jwt -- ---------------------------- INSERT INTO `jwt` VALUES ('login:1', 'eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI2NDgxMGZhYmZjNzM0ZjJlYWZmYTQ0NjBkYmVkN2M4ZSIsInN1YiI6ImxvZ2luOjEiLCJpc3MiOiJzZyIsImlhdCI6MTY4NDU1MTExMiwiZXhwIjoxNjg3MTQzMTEyfQ._di4aRwx-ykyOht-FEFXjMdxRupVGPYjowazSFlctGs'); INSERT INTO `jwt` VALUES ('login:2', 'eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI1NjBjOWVlNGY4MTM0MjU5YjJlNGEwYTc0NzI3ZjBjOSIsInN1YiI6ImxvZ2luOjIiLCJpc3MiOiJzZyIsImlhdCI6MTY4NDU1NjE5OSwiZXhwIjoxNjg3MTQ4MTk5fQ.oXQFqjO1rSUQQ8eN7VYtGkXaH1UgBtaoTkHY8pf__U0'); -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `username` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '账号', `password` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '密码', `nick_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '昵称', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `UK_sb8bbouer5wak8vyiiy4pf2bx`(`username` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES (1, 'admin', '123456', '大黄'); INSERT INTO `user` VALUES (2, 'abcde', '111111', '小王'); SET FOREIGN_KEY_CHECKS = 1; ``` > nacos > > 本项目SpringBoot版本为`2.3.12.RELEASE`、SpringCloudAlibaba版本为`2.2.9.RELEASE` > 对应的nacos版本为`2.1.0` > > [github](https://github.com/alibaba/nacos/releases?page=2)若无法打开,点击后方[下载链接](https://www.123pan.com/s/tMU0Vv-xTzUd.html) **在nacos文件夹内打开cmd**,输入如下命令启动 ```bash startup.cmd -m standalone ``` > nodejs版本>16 > > 本项目采用的是16.13.2 > 不建议直接下载nodejs,建议nvm后,使用nvm下载nodejs > 详情参考[本博客](https://blog.csdn.net/qq_39367410/article/details/126892822) **克隆本项目后,使用`npm install`命令下载依赖,使用`npm run dev`启动项目**