首页 > 其他分享 >瑞吉外卖项目记录

瑞吉外卖项目记录

时间:2022-10-16 21:56:29浏览次数:55  
标签:jackson 记录 nginx 瑞吉 master 外卖 import com class

通过过滤器实现用户状态检测

功能描述:

用户访问首页时,若为未登录状态,则跳转到登录页面

功能实现:

  1. 创建 LoginCheckFilter 类,添加 @WebFilter注解,将该类声明为过滤器
//filterName 表示过滤器的名称;urlPatterns 表示拦截的请求路径
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
  1. 在 SpringBootApplication 上使用@ServletComponentScan 注解后,Servlet、Filter、Listener 可以直接通过@WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。
@SpringBootApplication
@ServletComponentScan
  1. 通过spring 的路径匹配器来对请求进行筛选
//spring中的路径匹配器
AntPathMatcher PATH_MATCHER = new AntPathMatcher();

异常处理

使用@ControllerAdvice 注解可以给Controller控制器添加统一的操作或处理,结合@ExceptionHandler注解,就可以实现统一的异常处理

注:一定要打印异常信息

@ControllerAdvice(annotations = {Controller.class, RestController.class})
@ResponseBody //用于回传数据
@Slf4j
public class GlobalExceptionHandle {
	//统一处理sql异常
    @ExceptionHandler(SQLException.class)
    public R<String> sqlExceptionHandle(SQLException e) {
        //打印异常信息
        log.error(e.getMessage());
        return R.error("数据操作异常");
    }
}

MybatisPlus雪花算法生成的 id 字段精度缺失问题

mybatis plus默认使用雪花算法生成 long 型的主键 id,而JavaScript在处理数字时,超过16位的数字会自动进行四舍五入,这将导致在获取前端的 id 字段时会丢失精度

解决方案:

springMvc在底层是使用消息转换器来实现 Java对象与 json格式的数据的相互转换

所以可以自定义一个消息转换器,让其在处理 long 型的数据时 将其转为字符串类型进行传输,然后再将自定义的消息处理器添加到springMvc的转换器集合中即可

1. 自定义消息处理器类:

package com.waimai.commom;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;

/**
 * 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
 * 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
 * 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
 */
public class JacksonObjectMapper extends ObjectMapper {

    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    public JacksonObjectMapper() {
        super();
        //收到未知属性时不报异常
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);

        //反序列化时,属性不存在的兼容处理
        this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);


        SimpleModule simpleModule = new SimpleModule()
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))

                .addSerializer(BigInteger.class, ToStringSerializer.instance)
                .addSerializer(Long.class, ToStringSerializer.instance)
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));

        //注册功能模块 例如,可以添加自定义序列化器和反序列化器
        this.registerModule(simpleModule);
    }
}

2. 在springMvc的配置类中,将自定义消息处理器添加到spring mvc的转换集合中

/**
 * 扩展spring mvc的消息转换器
 * @param converters
 */
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    //创建消息对象转换器
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    //设置对象转换器,使用Jackson将Java对象转为json(自定义的对象映射器)
    converter.setObjectMapper(new JacksonObjectMapper());
    //将消息转换器添加到spring mvc的转换集合中(设置自定义的转换器下标,实现优先调用)
    converters.add(0,converter);
}

Mybatis Plus公共字段自动填充

在数据库不同的表中,可能会存在一些相同的字段,这时可以使用mybatis plus的公共字段自动填充功能来简化开发

操作步骤:

  1. 在实体类中,为表中公共字段所对应的属性添加@TableField 注解,将其标识为公共字段
//fill 表示自动填充的策略
//fill = FieldFill.INSERT 执行insert操作时进行填充
//fill = FieldFill.INSERT_UPDATE 执行insert或updat操作时进行填充
//fill = FieldFill.UPDATE 执行updat操作时进行填充
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
  1. 创建一个类,实现 MetaObjectHandler 接口,当公共字段执行insert或update操作时,该类的方法会被自动调用
//将该类标识为 bean
@Component
public class CommonMetaHandle implements MetaObjectHandler {
    /**
     * 执行insert操作时,为公共字段进行赋值
     * @param metaObject 元数据
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        //设置创建时间和操作时间
        metaObject.setValue("createTime",LocalDateTime.now());
        metaObject.setValue("updateTime",LocalDateTime.now());
        //设置操作人信息
        metaObject.setValue("createUser",1L);
        metaObject.setValue("updateUser",1L);
    }

    /**
     * 执行update操作时,为公共字段进行赋值
     * @param metaObject 元数据
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        //设置操作时间和操作人信息
        metaObject.setValue("updateTime",LocalDateTime.now());
        metaObject.setValue("updateUser", 1L);
    }
}

Mysql主从复制

mysql主从复制是一个异步复制过程,底层是基于mysql数据库自带的二进制日志功能。就是一台或多台MySQL数据库(slave,从库)从另一台数据库(master,主库)进行日志复制,然后再解析日志并应用到自身,最终实现从库数据与主库数据保持一致

mysql复制步骤

  • master将改变记录到二进制日志(binary log)
  • slave将master的日志拷贝到它的中继日志(relay log)
  • slave重复中继日志中的事件,将改变应用到自身

配置-主库master:

  1. 修改Mysql的配置文件 my.cnf,追加如下内容
[mysqld]
log-bin=mysql-bin # 启用二进制日志
server-id=100 # 服务器唯一id
  1. 重启mysql服务: systemctl restart mysqld
  2. 执行sql,创建一个用户(用户名:xiaoming,密码:123456)并给用户授权,slave必须通过master授权才能通过该用户复制中继日志
GRANT REPLICATION SLAVE ON *.* to 'xiaoming'@'%' identfied by '123456';
  1. 执行sql:show master status;

配置-从库slave:

  1. 修改Mysql的配置文件 my.cnf,追加如下内容
server-id=101 # 服务器唯一id
  1. 重启MySQL服务
  2. 执行sql
change master to master_host='192.168.75.128',master_user='xiaoming',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=433;
  1. 执行show slave status进行验证

使用 Sharding-JDBC实现读写分离

将数据库拆分为主库和从库,主库负责处理事务性的增删改操作,从库负责处理查询操作,这样能够有效避免由于数据更新造成的行锁,使得整个系统的查询性能能够得到极大的改善

步骤:

  1. 创建MySQL主从复制环境

  2. 导入maven坐标

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.0.0-RC1</version>
</dependency>
  1. 在springboot配置文件中配置读写分离规则
spring:
  application:
    name: reggie_take_out

  shardingsphere:
    datasource:
      names:
        master,slave

      # 主数据源
      master:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
        username: root
        password: 123456

      # 从数据源
      slave:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
        username: root
        password: 123456

    masterslave:
      # 读写分离配置 轮循
      load-balance-algorithm-type: round_robin
      # 主数据源mc
      master-data-source-name: master
      # 从数据源名称列表,多个使用逗号分隔
      slave-data-source-names: slave
      # 最终的数据源名称
      name: dataSource

    props:
      sql:
        show: true #开启sql显示
  main:
    allow-bean-definition-overriding: true # 开启bean定义覆盖
  1. 由于Sharding-JDBC 需要配置数据源,而druid 数据库连接池也会创建一个数据源对象,所以会造成bean 冲突,可以在配置文件中开启 bean定义覆盖

Nginx

neginx 命令

查看版本信息:

  • ./nginx -v:在nginx 安装目录的 sbin目录下执行

检查配置文件的正确性:

  • ./nginx -t:检查 conf/nginx.conf 文件配置是否有错误

启动和停止:

  • ./nginx:启动nginx 服务(默认是80端口)
  • ./nginx -s stop:停止nginx 服务

nginx 服务启动后默认有两个进程 master 和 worker,可修改配置文件来启动多个 worker 进程

重新加载配置文件:

  • ./nginx -s reload:修改配置文件后需要重新加载才能生效

nginx配置文件结构

整体结构:分为三部分

  • 全局块:和nginx 运行相关的全局配置
  • events块:和网络连接相关的配置
  • http块:代理、缓存、日志记录、虚拟主机配置
    • http全局块
    • server块
      • server全局块
      • location块

注意:http块中可以配置多个server块每个server块中也可以配置多个location块

nginx 具体应用

反向代理

代理模式介绍

  • 正向代理:正向代理一般是在客户端设置代理服务器,通过代理服务器转发请求,最终访问到目标服务器(梯子)
  • 反向代理:反向代理服务器位于用户与目标服务器之间,与正向代理的区别就是,服务器是设置在服务端(例如某个项目有多个服务,就可以使用反向代理来实现对请求的统一管理)

配置反向代理:

server{
	listen 端口号;
	server_name 服务名称;
	location /{
		porxy_pass url #将请求转发到指定服务
	}
}

负载均衡

  • 应用集群:将同一应用部署到多台服务器上,组成应用集群,接收负载均衡器分发的请求
  • 负载均衡器:将用户请求根据对应的负载均衡算法分发到应用集群中的一台服务器进行处理

负载均衡策略:

  • 轮询:默认配置
  • 权重:权重数字越大,分发机率越大
  • ip_hash:根据访问ip进行分发,可以保证同一个ip请求的都是同一个服务器
  • least_conn:依据最少连接方式,分发到当前连接数最少的服务器
  • url_hash:根据url进行分发,相同的url会请求到固定的服务器
  • fair:根据响应时间,分发到响应时间短的服务器

Swagger 生成接口文档

使用swagger 只需按照它的规范去定义接口及接口相关信息,再通过swagger衍生出的工具就可以生成各种格式的接口文档,以及在线接口调试页面

但是直接使用 swagger 比较繁琐,可以使用 knife4j (底层使用的还是swagger)更便于操作

使用步骤:

  1. 导入坐标

  2. 在springboot启动类加上注解

@EnableSwagger2
@EnableKnife4j
  1. 导入knife4j 相关配置类

  2. 启动项目后,访问 doc.html

swagger 常用注解

  • @Api:用在类上,表示对类的说明
  • @ApiModel:用在类上,通常是实体类,表示返回响应数据的信息
  • @ApiModelPropety:用在属性上,描述响应类的属性
  • @ApiOperation:用在请求的方法上,描述方法的作用
  • @ApiImplicitParams:用在请求的方法上,表示一组参数的说明
  • @ApiImplicitParam:用在@ApiImplicitParams注解中,描述某个参数的信息

标签:jackson,记录,nginx,瑞吉,master,外卖,import,com,class
From: https://www.cnblogs.com/xxgxs/p/16797321.html

相关文章

  • 【博学谷学习记录】超强总结,用心分享|Java基础分享-数据结构(栈、队列)
    目录 1.栈1.1.栈简介1.2.栈的常见应用常见应用场景1.2.1.实现浏览器的回退和前进功能1.2.2.检查符号是否成对出现1.2.3.反转字符串将字符串中的每个字符先入......
  • 【博学谷学习记录】超强总结,用心分享 。网络编程、日志技术、枚举、类加载器、反射。
    网络编程、日志技术、枚举、类加载器、反射。一、三要素1.IP地址:设备在网络中的地址,是唯一的标识(包含ipv4和ipv6,ipv4计算方法是点号计算,ipv6是冒号计算)......
  • 第三次会议记录
    设计数据库并绘制数据库ER图   ......
  • 网络层首部记录着超多信息
    网络层位于运输层和数据链路层之间,存在着IP、ARP、ICMP协议,以包的形式传递数据。网络层数据包(IP数据包,Packet)由首部、数据两部分组成。版本(Version)---占4个二进......
  • 虚拟机随笔记录
    这里记录一些安装虚拟机时碰到的一些问题,因为每次装都会遇到所以索性就记录下来。虚拟机安装ip地址查询不到参考centos7怎么查看ip地址_疯狂Programmer的博客-CSDN博......
  • 趣题记录
    趣题记录为啥是趣题记录?之前试过很多次按时间顺序编年体的做题记录,但是都因为在机房做题不方便更新、有些题没有什么意义等原因导致越攒越多,最后就咕掉了,因此决定试一试......
  • Linux学习记录(六):SSH
    使用场景:VSCode通过SSH访问远程服务器通过SSH连接远程服务器:sshuser@hostname(SSH默认端口为22),然后提示需要输入登录密码参考:https://code.visualstudio.com/docs/rem......
  • 2021 CCPC 威海站 VP记录(题解)
    2021CCPC威海站VP记录(题解)题目顺序为vp时开题顺序:A-Goodbye,Ziyin!签到,连边数小于等于2的可以作为二叉树根,若有大于4的直接输出0。code:voidsolve(){ int......
  • 疫情到往记录
    <%@pagelanguage="java"contentType="text/html;charset=UTF-8"pageEncoding="UTF-8"%><!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN"......
  • 挖土机杯 CSP-J 组模拟赛 R2 记录
    题外话:我以为10:00开始的......没有足够时间搞,不过题目总体而言难度不大,虽然但是也没赛时AC两题。T1比较简单的送分题,就是分数的加减及约分而已,最后来个特判0和整除。至于......