# 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项目




2.在web服务中导入对应依赖(alibaba、nacos、mybatis...)
结果截图

```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等注解





2. 使用@GetMapping、@PostMapping、@RequestMapping等注解标注api
结果截图

```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


```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.编写业务方法

```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);
}
```

```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.使用控制层方法调用对应的业务方法

```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);
}
}
```


4. **创建服务消费者(通过RestTemplate调用服务生产者)**(20分)
搭建步骤
1.将RestTemplate注入Spring容器
结果截图

```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.在消费者端编写方法调用对应的生产者方法,并传递参数
结果截图

```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依赖,注意版本冲突问题


```xml
2.2.9.RELEASE
com.alibaba.cloud
spring-cloud-alibaba-dependencies
${spring-cloud-alibaba.version}
pom
import
```
2.使用`@EnableDiscoveryClient`注解标识启动类,开启服务的注册发现功能

```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地址


```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`启动项目**