reggie项目优化源码gitee
地址(优化的代码在标签v1、v2、v3):https://gitee.com/gaoqiangmath/reggie.git
本博客是瑞吉外卖项目–服务端开发以及瑞吉外卖项目–移动端开发的后续
瑞吉外卖项目–服务端开发的博客见:瑞吉外卖项目–服务端开发
瑞吉外卖项目–移动端开发的博客见:瑞吉外卖项目–移动端开发
本博客是根据b站瑞吉外卖视频(p157-p191)整理而来
视频链接:https://www.bilibili.com/video/BV13a411q753/?p=2&spm_id_from=pageDriver&vd_source=f4a032fee75744e378f4ac30c7e8ad39
打标签:
关于标签需要知道的操作:
git tag
git tag -a 标签名 -m "标签备注"
git push origin :refs/tags/标签名
git checkout -b 分支名(自己取) 标签名
(后续代码优化都在此分支上)
创建本地分支dev1(主分支的基础上在):
redis缓存优化在分支dev1 ,标签v1
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
hutool工具
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.8.15version>
dependency>
application.yml
spring:
redis:
host: 192.168.10.103
port: 6379
password: 123456
package com.gq.reggie.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gq.reggie.common.R;
import com.gq.reggie.entity.User;
import com.gq.reggie.service.UserService;
import com.gq.reggie.utils.SMSUtils;
import com.gq.reggie.utils.ValidateCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@RestController
@Slf4j
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 发送手机短信验证码
*/
@PostMapping("/sendMsg")
public R<String> sendMsg(@RequestBody User user, HttpSession session) {
//获取手机号
String phone = user.getPhone();
if (StringUtils.isNotEmpty(phone)) {
//随机生成的4为验证码
Integer integerCode = ValidateCodeUtils.generateValidateCode(4);
String code = integerCode.toString();
//这是模拟的,验证码发到控制台
log.info("手机验证码={}", code);
//调用阿里云提供的短信服务api完成发送短信 这里仅作学习使用,不需要真正发送验证码,所以关掉了
//参数分别是:阿里云创建的标签名、模板code、手机号码、验证码
SMSUtils.sendMessage("瑞吉外卖", "SMS_460655856", phone, code);
log.info("阿里云手机验证码发送成功");
//把验证码保存到redis中,并且设置为5分钟期限
//session.setAttribute(phone, code);
stringRedisTemplate.opsForValue().set(phone, code, 5L, TimeUnit.MINUTES);
return R.success("手机验证码发送成功");
}
return R.error("手机验证码发送失败");
}
/**
* 移动端用户登录
*/
@PostMapping("/login")
public R<User> login(@RequestBody Map map, HttpSession session) {
//log.info(map.toString());
//获取手机号
String phone = map.get("phone").toString();
//获取验证码
String code = map.get("code").toString();
//从redis中获取保存的验证码
String codeInSession = stringRedisTemplate.opsForValue().get(phone);
//进行验证码的比对(页面提交的验证码和Session中保存的验证码比对)
if (codeInSession != null && codeInSession.equals(code)) {
//如果能够比对成功,说明登录成功
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getPhone, phone);
//根据用户的手机号去用户表获取用户
User user = userService.getOne(queryWrapper);
if (user == null) {
//判断当前手机号对应的用户是否为新用户,如果是新用户就自动完成注册
user = new User();
user.setPhone(phone);
user.setStatus(1); //可设置也可不设置,因为数据库我们设置了默认值
//注册新用户
userService.save(user);
}
//这一行容易漏。。保存用户登录状态
session.setAttribute("user", user.getId()); //在session中保存用户的登录状态,这样才过滤器的时候就不会被拦截了
return R.success(user);
}
//如果登陆成功,则在redis中删除验证码
if (stringRedisTemplate.opsForValue().get(phone) != null) {
stringRedisTemplate.delete(phone);
}
return R.error("登录失败");
}
}
DishController
中的list
方法
@Autowired
private StringRedisTemplate stringRedisTemplate;
@GetMapping("/list")
public R<List<DishDto>> list(Dish dish) { //会自动映射的
//这里可以传categoryId,但是为了代码通用性更强,这里直接使用dish类来接受(因为dish里面是有categoryId的),以后传dish的其他属性这里也可以使用
//从redis中拿菜品
// 动态构造key
String key = "dish_" + dish.getCategoryId() + "_" + dish.getStatus();
String jsonDishs = stringRedisTemplate.opsForValue().get(key);
List<DishDto> dishDtoList = JSONUtil.toList(jsonDishs, DishDto.class);
//构造查询条件
LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId());
//添加条件,查询状态为1(起售状态)的菜品
queryWrapper.eq(Dish::getStatus, 1);
//添加排序条件
queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
List<Dish> list = dishService.list(queryWrapper);
//进行集合的泛型转化
dishDtoList = list.stream().map((item) -> {
DishDto dishDto = new DishDto();
//为一个新的对象赋值,一定要考虑你为它赋过几个值,否则你自己都不知道就返回了null的数据
//为dishDto对象的基本属性拷贝
BeanUtils.copyProperties(item, dishDto);
Long categoryId = item.getCategoryId();
Category category = categoryService.getById(categoryId);
if (category != null) {
String categoryName = category.getName();
dishDto.setCategoryName(categoryName);
}
//为dishdto赋值flavors属性
//当前菜品的id
Long dishId = item.getId();
//创建条件查询对象
LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper();
lambdaQueryWrapper.eq(DishFlavor::getDishId, dishId);
//select * from dish_flavor where dish_id = ?
//这里之所以使用list来条件查询那是因为同一个dish_id 可以查出不同的口味出来,就是查询的结果不止一个
List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);
dishDto.setFlavors(dishFlavorList);
return dishDto;
}).collect(Collectors.toList());
//将dishDtoList存入redis
stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(dishDtoList));
return R.success(dishDtoList);
}
/**
* 修改菜品以及口味信息
*
*/
@PutMapping
public R<String> update(@RequestBody DishDto dishDto) {
dishService.updateWithFlavor(dishDto);
//清理修改的菜品的缓存数据
String key = "dish_" + dishDto.getCategoryId() + "_" + dishDto.getStatus();
stringRedisTemplate.delete(key);
return R.success("菜品修改成功");
}
/**
* 新增菜品
*
*/
@PostMapping
public R<String> save(@RequestBody DishDto dishDto) {//前端提交的是json数据的话,我们在后端就要使用这个注解来接收参数,否则接收到的数据全是null
dishService.saveWhthFlavor(dishDto);
//清理修改的菜品的缓存数据
String key = "dish_" + dishDto.getCategoryId() + "_" + dishDto.getStatus();
stringRedisTemplate.delete(key);
return R.success("新增菜品成功");
}
Spring Cache
的依赖在 spring-boot-starter-web
中
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
/**
* CachePut:将方法返回值放入缓存
* value:缓存的名称,每个缓存下可以有多个key
* key:缓存的key
* @param user
* @return
*/
@CachePut(value = "userCache", key = "#user.id")
@PostMapping
public User save(User user){
userService.save(user);
return user;
}
/**
* CacheEvict:清理指定缓存,key有多种写法
* @param id
*/
@CacheEvict(value = "userCache", key = "#id")
//@CacheEvict(value = "userCache", key = "#root.args[0]")
//@CacheEvict(value = "userCache", key = "#p0")
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id){
userService.removeById(id);
}
@CacheEvict(value = "userCache", key = "#p0.id")
//@CacheEvict(value = "userCache", key = "#root.args[0].id")
//@CacheEvict(value = "userCache", key = "#user.id")
//@CacheEvict(value = "userCache", key = "#result.id")
@PutMapping
public User update(User user){
userService.updateById(user);
return user;
}
/**
* Cacheable:在方法执行前spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中
* 若数据库没有找到数据,以null为key
* unless:缓存条件,满足条件才缓存
* @param id
* @return
*/
@Cacheable(value = "userCache", key = "#id", unless = "#result == null")
@GetMapping("/{id}")
public User getById(@PathVariable Long id){
User user = userService.getById(id);
return user;
}
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-cacheartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
spring:
redis:
host: 192.168.10.103
port: 6379
password: 123456
cache:
redis:
time-to-live: 1800000 # 设置缓存有效时间,以毫秒为单位
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-cacheartifactId>
dependency>
application.yml
中
spring:
cache:
redis:
time-to-live: 1800000 # 设置缓存有效时间,以毫秒为单位
在启动类
上加上注解@EnableCaching
@EnableCaching // 开启Spring Cache缓存
common
包下R
类
public class R<T> implements Serializable
SetmealController
中list
/**
* 移动端套餐展示
*
* @param categoryId
* @param status
* @return
*/
@GetMapping("/list")
@Cacheable(value = "setmealCache",key = "#categoryId + '_' + #status")
public R<List<Setmeal>> listSetmeal(@RequestParam(value = "categoryId") long categoryId, @RequestParam(name = "status") int status) {
LambdaQueryWrapper<Setmeal> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();
setmealLambdaQueryWrapper.eq(Setmeal::getCategoryId, categoryId);
setmealLambdaQueryWrapper.eq(Setmeal::getStatus, status);
setmealLambdaQueryWrapper.orderByAsc(Setmeal::getCreateTime);
List<Setmeal> setmealList = setmealService.list(setmealLambdaQueryWrapper);
return R.success(setmealList);
}
SetmealController
中:
/**
* 套餐删除
* allEntries:清理value分类下所有缓存数据
* @param ids
* @return
*/
@DeleteMapping
@CacheEvict(value = "setmealCache",allEntries = true)
public R<String> deleteByIds(@RequestParam(name = "ids") List<Long> ids) {
setmealService.removeWithDish(ids);
return R.success("套餐删除成功!!");
}
/**
* 套餐管理模块中:保存新增的套餐
* allEntries:清理value分类下所有缓存数据
* @param setmealDto
* @return
*/
@PostMapping
@CacheEvict(value = "setmealCache",allEntries = true)
public R<String> saveSetmeal(@RequestBody SetmealDto setmealDto) {
setmealService.saveSetmeal(setmealDto);
return R.success("套餐添加成功!!");
}
redis缓存以及mysql主从复制在分支dev2 标签v2
第一:准备两台服务器,分别安装了mysql8
主服务器
:hadoop103 192.168.10.103
从服务器
:hadoop103salve 192.168.10.104
注意:从服务器mysql数据库里面的内容不要和主服务器mysql服务器的内容冲突,最好都是两个空的,等搭建好了主从结构,再从主服务器添加数据
一定要注意:从服务器是直接克隆的主服务器,一定要修改如下三个地方
从虚拟机
的ip地址
、uuid
cat /etc/sysconfig/network-scripts/ifcfg-ens33
从虚拟机
的hostname
sudo vi /etc/hostname
更新/etc/hosts文件 【更改主机名后】
在更改主机名后我们需要更新/etc/hosts解析文件。
sudo vi /etc/hosts
从虚拟机
mysql中的uuid
首先找到auto.cnf
文件
find / -iname auto.cnf
vim /usr/local/mysql-8.0.31/data/auto.cnf #注意,这里是自己的auto.cnf文件位置
配置主库:hadoop103 192.168.10.103
Myusql
数据库的配置文件/etc/my.cnf
[mysqld]
log-bin=mysql-bin #[必须]启用二进制日志
server-id=103 #[必须]服务器唯一ID,只需要确保其id是唯一的就好
systemctl restart mysql
mysql版本在8以及以上的,使用这个:
create user gaoqiang identified by 'Root@123456';
grant replication slave on *.* to gaoqiang;
mysql版本在8以下的,使用这个:
grant replication slave on *.* to 'gaoqiang'@'%' identified by 'Root@123456';
上面的SQL的作用是创建一个用户gaoqiang
,密码为Root@123456
,并且给gaoqiang
用户授予replication slave
权限,常用语建立复制时所需要用到的用户权限,也就是slave必须被master授权具有该权限的用户,才能通过该用户复制,这是因为主库和从库之间需要互相通信,处于安全考虑,只有通过验证的从库才能从主库中读取二进制数据。
show master status;
上面指令的作用是查看Master的状态,执行完此SQL后不要在执行任何操作,如果执行了别的操作的话会使得File和position发生变化
配置从库:hadoop103salve 192.168.10.104
/etc/my.cnf
[mysqld]
log-bin=mysql-bin #[必须]启用二进制日志
server-id=104 #[必须]服务器唯一ID,只需要确保其id是唯一的就好
systemctl restart mysql
change master to master_host='192.168.10.103',master_user='gaoqiang',master_password='Root@123456',master_log_file='mysql-bin.000004',master_log_pos=697,master_connect_retry=60, GET_MASTER_PUBLIC_KEY=1;
start slave;
show slave status \G;
(到这里就搭建好了主从数据库)
面对日益增加的系统访问量,数据库的吞吐量面临着巨大瓶颈。对于同一时刻有大量并发读操作和较少写操作类型的应用系统来说,将数据库拆分为主库和从库,主库主要负责处理事务性的增删改操作,从库负责处理查询操作,能够有效的避免由数据更新导致的行锁,使得整个系统的查询性能得到极大改善
<dependency>
<groupId>org.apache.shardingspheregroupId>
<artifactId>sharding-jdbc-spring-boot-starterartifactId>
<version>4.0.0-RC1version>
dependency>
- 步骤一:搭建好主从复制结构
主从复制结构见17.1.2 配置主从数据库
,
并且在主库中创建reggie数据库,导入数据(具体的sql文件见:瑞吉外卖项目–服务端开发中的3.1、数据库环境搭建)
- 步骤二:加入
maven
坐标
<dependency>
<groupId>org.apache.shardingspheregroupId>
<artifactId>sharding-jdbc-spring-boot-starterartifactId>
<version>4.0.0-RC1version>
dependency>
- 步骤三:修改
application.yml
配置文件
(注意在配置文件中配置允许bean定义覆盖配置项)
原本的application.yml
配置文件:
server:
port: 8080
spring:
application:
# 应用的名称,选择性配置
name: reggie_take_out
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 123456
redis:
host: 192.168.10.103
port: 6379
password: 123456
cache:
redis:
time-to-live: 1800000 # 设置缓存有效时间,以毫秒为单位
mybatis-plus:
configuration:
#在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
map-underscore-to-camel-case: true
# 把SQL的查询的过程输出到控制台
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
#主键的生成策略,雪花算法
id-type: ASSIGN_ID
#文件储存位置
reggie:
path: D:\Study\Items\reggie\pictures\
添加了主从复制的application.yml
配置文件
server:
port: 8080
spring:
application:
# 应用的名称,选择性配置
name: reggie_take_out
main:
allow-bean-definition-overriding: true #允许bean定义覆盖配置项
# datasource:
# druid:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
# username: root
# password: 123456
shardingsphere:
datasource:
names:
master,slave # 数据源名字,可自定义,只要上下对应即可
# 主数据源
master:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.10.103:3306/reggie?characterEncoding=utf-8&useSSL=false
username: root
password: 123456
# 从数据源
slave:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.10.104:3306/reggie?characterEncoding=utf-8&useSSL=false
username: root
password: 123456
masterslave:
# 读写分离配置
load-balance-algorithm-type: round_robin # 负载均衡策略:轮询
# 最终的数据源名称
name: dataSource
# 主库数据源名称
master-data-source-name: master
# 从库数据源名称列表,多个逗号分隔
slave-data-source-names: slave
props:
sql:
show: true #开启SQL显示,默认false
redis:
host: 192.168.10.103
port: 6379
password: 123456
cache:
redis:
time-to-live: 1800000 # 设置缓存有效时间,以毫秒为单位
mybatis-plus:
configuration:
#在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
map-underscore-to-camel-case: true
# 把SQL的查询的过程输出到控制台
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
#主键的生成策略,雪花算法
id-type: ASSIGN_ID
#文件储存位置
reggie:
path: D:\Study\Items\reggie\pictures\
步骤四:测试
重启项目,发现启动了两个数据源
(查询操作走的是slave从库)
(修改走的是master主库)
Windows 下载地址:http://nginx.org/,选择需要的版本下载即可
(本处使用的是linux
版本)
安装依赖包:
yum -y install gcc pcre-devel zlib-devel openssl openssl-devel
安装wget 以便于可以直接通过网址下载软件
yum install wget
下载nginx安装包 建议在/usr/local目录下下载(解压完后,把安装包删掉)
wget http://nginx.org/download/nginx-1.24.0.tar.gz
解压
tar -zxvf nginx-1.24.0.tar.gz -C /usr/local
进入根目录
cd nginx-1.24.0/
创建安装目录
mkdir -p /usr/local/nginx
检查nginx安装环境(在nginx-1.24.0/内输入下述命令)
./configure --prefix=/usr/local/nginx
编译并安装nginx,会安装到/usr/local/nginx中 (在nginx-1.24.0/内输入下述命令)
make && make install
为了方便看目录,可以下载一个tree
yum install tree
在进入 nginx 目录下的 sbin
目录后,使用以下命令可以查看 nginx 版本
./nginx -v
在启动 Nginx 服务之前,可以先检查一下 conf/nginx.conf
文件配置的是否有错误,进入 nginx
目录下的 sbin
目录后执行如下命令:
./nginx -t
启动:进入 nginx
目录下的 sbin
目录后执行如下命令:
./nginx
记得关闭防火墙:
systemctl stop friewalld
启动后可以查看 nginx 进程
ps -ef | grep nginx
停止:进入 nginx
目录下的 sbin
目录后执行如下命令:
./nginx -s stop
当修改Nginx配置文件后,需要重新加载才能生效,可以使用下面命令重新加载配置文件:
进入 nginx
目录下的 sbin
目录后执行如下命令:
./nginx -s reload
修改 /etc/profile 文件
在 PATH 前加上 nginx 的 sbin 的完整路径,这里是 /usr/local/nginx/sbin: (注意有个冒号)
PATH=/usr/local/nginx/sbin:$PATH
修改完后重新加载
source /etc/profile
改完之后,可以任意位置使用nginx命令
(此功能在dev3分支上:redis缓存、mysql主从复制、swagger)
<dependency>
<groupId>com.github.xiaoymingroupId>
<artifactId>knife4j-spring-boot-starterartifactId>
<version>3.0.2version>
dependency>
在 WebMvcConfig
类上加上两个注解
@EnableSwagger2
@EnableKnife4j
然后在WebMvcConfig类中添加这两个方法
@Bean
public Docket createRestApi() {
// 文档类型
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.gq.reggie.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("瑞吉外卖")
.version("1.0")
.description("瑞吉外卖接口文档")
.build();
}
在 WebMvcConfig
类的 addResourceHandlers
配置静态资源映射
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
最终版:WebMvcConfig
package com.gq.reggie.config;
import com.gq.reggie.common.JacksonObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.List;
@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始进行静态资源映射");
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
/**
* 扩展mvc框架的消息转换器
* @param converters
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
//log.info("扩展消息转换器...");
//创建消息转换器对象
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
//设置对象转换器,底层使用Jackson将Java对象转为json
messageConverter.setObjectMapper(new JacksonObjectMapper());
//将上面的消息转换器对象追加到mvc框架的转换器集合中
//转换器是有优先级顺序的,这里我们把自己定义的消息转换器设置为第一优先级,所以会优先使用我们的转换器来进行相关数据进行转换,如果我们的转换器没有匹配到相应的数据来转换,那么就会去寻找第二个优先级的转换器,以此类推
converters.add(0,messageConverter);
}
@Bean
public Docket createRestApi() {
// 文档类型
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.gq.reggie.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("瑞吉外卖")
.version("1.0")
.description("瑞吉外卖接口文档")
.build();
}
}
在 LoginCheckFilter
类的 doFilter
方法添加放行路径(为了方便)
// knife4j 放行路径
"/doc.html",
"/webjars/**",
"/swagger-resources",
"/v2/api-docs"
在浏览器访问 http://localhost:8080/doc.html ,可以看到接口文档
(以红字
为准)
准备两台机器:
192.168.10.103
: 主从复制的主库,需要的软件:jdk
、mysql8
、nginx
、redis
(如果手动把jar包传入,不需要git maven)
192.168.10.104
:主从复制的从库,需要的软件:mysql8
1、将前端资料打包,传到 nginx 根目录下的 html 目录
2、修改 nginx.conf
server{
listen 80;
server_name localhost;
location / {
root html/dist; # 根目录
index index.html; # 默认首页
}
# 反向代理
location ^~ /api/ {
rewrite ^/api/(.*)$ /$1 break; # rewirte:重写url,将 /api/ 除去
proxy_pass proxy_pass http://192.168.10.103:8080;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html{
root html;
}
}
(建议使用docker,这里这样不推荐)
将打包好的jar包传入到服务器:192.168.10.103
中
传入到:/usr/local/app/目录下,后台运行
nohup java -jar reggie-0.0.1-SNAPSHOT.jar >server.log 2>&1 &