项目心得--网约车

news2024/11/6 3:17:07

一、RESTFUL

Post:新增

Put:全量修改

Patch:修改某个值

Delete: 删除

Get:查询

删除接口也可以用POST请求

url注意:

url中不要带有敏感词(用户id等)

url中的名词用复数形式

url设计:

api.xxx.com/courses

二、状态码和提示信息

code:状态码

message:success等

消息:真正的消息体

这样做可以省去解析消息体拿到状态码

三、分页

  1. /api/courses?page=1&size=10

  1. /api/courses?max_id=100&min_id=90

第一种缺点:不适合频繁有插入的情况(第一页的数据,可能在看第二页的时候被挤到第二页了,看到了重复数据)

第二种缺点:不合适看指定的页数(得要看了前一页之后,才能知道下一页的max_id和min_id)

四、接口设计工具

APIFOX

五、dependencies和dependencyManager

dependencyManager在父项目中只声明依赖,并不实现引用;子项目需要显示声明依赖;有利于版本统一,父项目声明后,子项目中可以不写版本号

dependencies:在父项目中写了依赖后,子项目自动继承父项目的依赖,可以直接使用

创建项目:

groupId:公司名

artifactId:项目名

六、创建项目

  1. 验证项目

项目创建完成,可以通过package打包的方式,验证项目是否创建完成

  1. 父项目中packaging为pom

<packaging>pom</packaging>

3.创建子项目

new module

创建完子项目,父项目的pom文件中会多:

<modules>
 <module>子项目名 </module>
<modules>

4. relativePath

relativePath用于找父项目的pom文件位置,默认就是../pom.xml

<relativePath>../pom.xml<relativePath>

5. 子项目调用

同一个父项目中的各个子项目,如果需要相互调用,可以在父项目中加对应的项目依赖,也可以在调用的项目中添加依赖

七、nacos

nacos只是一个应用服务,下载了以后,直接启动运行

nacos启动时,路径带中文会报错

windows上可以使用启动脚本来启动nacos,把启动命令放在bat文件中,双击bat文件就可以启动了

把服务注册到nacos中

  1. 在服务中添加nacos依赖

  1. 添加配置

  1. 在启动类中添加注解

@EnableDiscoveryClient

八、链式调用@Accessors

实体类上可以加@Accessors(chain=true)注解

用于链式调用,set完一个属性后可以直接再设置另一个属性,会返回对象本身

user.setName("").setAge();

九、springboot、spring cloud、spring cloud alibaba版本统一问题

spring cloud alibaba中有说明版本统一问题,可以通过dependcyManager在管理整个项目的版本

https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

在父项目中注明spring cloud alibab的版本号

十、openFeign

子项目之间调用可以使用openFegin

  1. 添加openFeign的依赖

       <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
  1. 启动类需要添加注解

@EnableFeignClients

  1. 使用openFegin需要引用loadBalance依赖

使用openFeign进行远程调用

使用feign进行服务调用会出现的问题:

GET请求中,如果参数放在body中,使用@RequestBody进行参数传递,GET请求会被转成POST请求。

解决方式一:需要修改成路径参数 @PathVariable

解决方式二:添加依赖

        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>

十一、mysql8的数据库连接

需要写时区serverTimezone=GMT%2B8

十二、JWT

用于生成解析token

JWT:Json Web Token

官网:https://jwt.io/

第一部分和第二部分都可以被解析出来,所以token里面不要放很重要的信息

第三部分中有一个256位的密码,可以增加密码的安全性

项目中引入JWT

  1. 添加依赖

  1. 生成token

    // 生成token
    public static String generatorToken(String phone , String identity , String tokenType) {
        Map<String,String> map = new HashMap<>();
        map.put(JWT_KEY_PHONE,phone);
        map.put(JWT_KEY_IDENTITY, identity);
        map.put(JWT_TOKEN_TYPE, tokenType);
        // 防止每次生成的token一样。
        map.put(JWT_TOKEN_TIME, Calendar.getInstance().getTime().toString());

        JWTCreator.Builder builder = JWT.create();
        // 整合map
        map.forEach(
            (k,v) -> {
                builder.withClaim(k,v);
            }
        );
        // 整合过期时间
//        builder.withExpiresAt(date);

        // 生成 token
        String sign = builder.sign(Algorithm.HMAC256(SIGN));

        return sign;
    }
  1. 解析token

 // 解析token
    public static TokenResult parseToken(String token){
        DecodedJWT verify = JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
        String phone = verify.getClaim(JWT_KEY_PHONE).asString();
        String identity = verify.getClaim(JWT_KEY_IDENTITY).asString();

        TokenResult tokenResult = new TokenResult();
        tokenResult.setPhone(phone);
        tokenResult.setIdentity(identity);
        return tokenResult;

    }

十三、添加拦截器

  1. 实现HandlerInterceptor

  1. 重写preHandle方法

public class JwtInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        boolean result = true;
        String resutltString = "";

        String token = request.getHeader("Authorization");
        // 解析token
        TokenResult tokenResult = JwtUtils.checkToken(token);

        if (tokenResult == null){
            resutltString = "access token invalid";
            result = false;
        }else{
            // 拼接key
            String phone = tokenResult.getPhone();
            String identity = tokenResult.getIdentity();

            String tokenKey = RedisPrefixUtils.generatorTokenKey(phone,identity, TokenConstants.ACCESS_TOKEN_TYPE);
            // 从redis中取出token
            String tokenRedis = stringRedisTemplate.opsForValue().get(tokenKey);
            if ((StringUtils.isBlank(tokenRedis))  || (!token.trim().equals(tokenRedis.trim()))){
                resutltString = "access token invalid";
                result = false;
            }
        }

        if (!result){
            PrintWriter out = response.getWriter();
            out.print(JSONObject.fromObject(ResponseResult.fail(resutltString)).toString());
        }

        return result;
    }
}
  1. 把拦截器注入到spring容器中

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Bean
    public JwtInterceptor jwtInterceptor(){
        return new JwtInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor())
                // 拦截的路径
                .addPathPatterns("/**")
                // 不拦截的路径
                .excludePathPatterns("/noauth")
                .excludePathPatterns("/verification-code")
                .excludePathPatterns("/verification-code-check")
                ;
    }
}

拦截器是在bean实例化前初始化的,所以拦截器中使用bean需要在拦截器配置类中手动注入要使用的bean

十四、token

token失效

  1. 可以通过token本身设置过期时间

  1. 也可以通过存储在redis中设置过期时间

双token

accessToken、refreshToken

accessToken是正常的访问token,refreshToken是刷新token,refreshToken的过期时间一般要比accessToken长。当accessToken快要过期了,但是用户正在访问,此时突然过期,对用户体验很不友好。此时,使用refreshToken访问,来更新accessToken和refreshToken。提高用户体验

可以在浏览器中安装JSON-handle插件,这样浏览器中的数据会展示成json格式

十五、读取yml中配置的参数

  1. @Value

2. 配置文件

@Data
@Configuration
@ConfigurationProperties(prefix = "xxx.xxx.xxx")
public class ApiAuthProperties {

    private String url;

    private String checkToken;

}

十六、Ribbon

Ribbon用法:

  1. 在启动类中添加RestTemplate

  1. 通过RestTemplate进行远程调用

openFeign和Ribbon的区别

openFeign内置了Ribbon,调用的是服务注册中心(Nacos)的服务

Ribbon可以调用第三方接口,需要手动调用

url中的参数是复杂json,包含数组,对象

需要对一些符号进行编码:[ ] " : ,

使用ribbon进行接口调用时,url需要使用URI.create(url)

十七、根据数据库表生成对应实体类

  1. 引入jar包

  1. 编写自动生成工具类

FastAutoGenerator.create("jdbc:mysql://localhost:3306/service-driver-user?characterEncoding=utf-8&serverTimezone=GMT%2B8",
                "root","root")
                .globalConfig(builder -> {
                    builder.author("作者名").fileOverride().outputDir("导出文件路径");
                })
                .packageConfig(builder -> {
                    builder.parent("com.mashibing.serviceDriverUser").pathInfo(Collections.singletonMap(OutputFile.mapperXml,
                            "xxx\\service-driver-user\\src\\main\\java\\com\\mashibing\\serviceDriverUser\\mapper"));
                })
                .strategyConfig(builder -> {
                    builder.addInclude("driver_user_work_status");

                })
                .templateEngine(new FreemarkerTemplateEngine())
                .execute();

加sql相关的日志

logging:
  level:
    com:
      baomidou:
        mybatisplus: debug
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

十八、请求参数

@RequestParam

写在params中的参数,接收时使用@RequestParam

@RequestBody

在body中的,接收时使用@RequestBody

@PathVariable

在路径中的,接收时使用@PathVariable

Header

header中的参数,接收时使用HttpServletRequest,httpServletRequest.getHeader("xxx");

十九、日期

实体类的中Date不推荐,推荐使用LocalDate

时间转成时间戳:

localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli()

使用@JsonFormat注解,需要以下依赖

二十、请求错误码

4开头的是客户端的错误

5开头的是服务端的错误

400:参数有误,比如说日期格式有误

401:权限有误

404:地址有误

二十一、idea运行xml中的sql注意事项

勾选bulid project automatically

按住clt+shift+A,选择Register,勾选compiler.xxx

二十二、把mapper文件放在resource下,需要配置

二十三、数字与字符串

json格式中的字符串使用getLong获取,可能会导致精度丢失

可以getString后,通过Long.parseLong转换

小数用double存储,还是用字符串存储

如果小数用于计算,用double

如果不用于计算,只用于展示,可以用字符串

二十四、设置提交忽略目录

在项目的跟目录下找到.gitignore文件

写项目名/子项目名/target/,这样可以忽略target下所有文件

二十五、并发测试

工具:Jmeter

https://jmeter.apache.org/

需要配置环境变量JMETER_HOME

设置需要的参数

二十六、并发问题

  1. 单节点可以使用synchronized加锁

synchronized锁long类型的数据,可以使用:

synchronized(( longNum + "").intern())

当调用intern()方法时,如果常量池中已经有这个字符串(根据equals判断),则直接返回

如果常量池中没有,把这个字符串添加进常量池并返回

但是synchronized是jvm级别的,解决不了集群之间的并发问题

2. 集群可以使用redisson

RLock lock = redissonClient.getLock(lockKey);
lock.lock(); // 加锁
lock.unlock(); // 解锁

一个项目启动多次(测试集群部署)

  1. 添加多个端口号

  1. 复制两个项目启动

二十七、修改项目名

  1. rename

  1. 修改包名

  1. 修改pom文件

二十八、其他

数据库名可以与服务名保持一致

JSONObject中是否有某个字段,可以用has

复制对象属性:

可以使用BeanUtils.copyProperties(src, dest);

微服务开发时,如果切换网络,可能会导致服务间调用不通了

前后端数据交互,可以使用:SseEmitter

路径中的下划线_和中划线-的区别:

搜索引擎关于爬虫的优化,建议在路径中使用中划线-

计算机通过外网被访问,需要提供一个外网的ip地址,可以使用花生壳产生一个外网ip

接入支付宝支付参考:https://opendocs.alipay.com/common/02ncur

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/398108.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分形(Fractal)及分形维数(Fractal dimension)

文章目录1. 分形介绍2. 分形的定义3. 分形维数介绍4. 历史5. 缩放的作用&#xff08;Role of scaling&#xff09;6. D 不是唯一描述符7. 分形表面结构8. 例子8.8 Hausdorff dimension8.8.1 直观概念8.8.2 正式定义8.8.2.1 Hausdorff dimension8.8.2.2 Hausdorff content8.8.3 …

C++ 实现一个反射类

代码环境为VScode CMake GCC 8.1.0 首先&#xff0c;如何才能做到给我一个名字我就能拿到这个对象的这个值&#xff0c;也是比较难的一个地方&#xff0c;方法如下 #define OFFSET(className,fieldName) (size_t)&(((className*)0)->fieldName)这个能够得到该成员变…

数据结构3——线性表2:线性表的顺序结构

顺序结构的基本理解 定义&#xff1a; 把逻辑上相邻的数据元素存储在物理上相邻&#xff08;占用一片连续的存储单元&#xff0c;中间不能空出来&#xff09;的存储单元的存储结构 存储位置计算&#xff1a; LOC(a(i1))LOC(a(i))lLOC(a(i1))LOC(a(i))l LOC(a(i1))LOC(a(i))l L…

【pyqt】win10下使用pycharm安装并配置pyqt环境,并用其进行界面绘制

目录1.PyQt简介2.PyQt安装2.PyQt中界面绘制工具集在pycharm中的配置2.主程序引入生成的界面类1.PyQt简介 PyQt是一个基于Python语言的开源图形用户界面&#xff08;GUI&#xff09;框架&#xff0c;它是Qt跨平台应用程序框架的Python绑定&#xff0c;可以用于创建各种不同类型…

js 拷贝

一、浅拷贝 对数据拷贝的时候只拷贝一层&#xff0c;深层次的只拷贝了地址 1. &#xff08;1&#xff09;对于数组类型&#xff0c;可以使用slice(start, end)方法&#xff0c;返回一个新的数组。 var arr1 arr.slice(0); &#xff08;备注&#xff1a;slice 方法一直复制到…

(Fabric 超级账本学习【2】)Fabric2.4环境下部署自己编写的链码

&#xff08;Fabric 超级账本学习【2】&#xff09;Fabric2.4环境下部署自己编写的链码 1、前提是搭建好了Fabric 2.4&#xff08;Fabric2.x&#xff09;版本的区块链网络&#xff0c;并在以此环境下部署自己编写的链码&#xff0c;如下图先进入 test-network 文件夹目录下 2、…

23年PMP考试,应试技巧二十五条(含资料)

1.一定要认真阅读答案的全部四个选项。 千万不要看到某个选项是正确的&#xff0c;就不看其他选项&#xff0c;因为可能还有更正确的选项。PMP考的是选项的相对正确程度&#xff0c;而不是绝对正确程度&#xff0c;这与英语水平考试截然不同。可能四个选项都是正确或错误的&am…

Linux进程间通信详解(最全)

进程间的五种通信方式介绍 进程间通信&#xff08;IPC&#xff0c;InterProcess Communication&#xff09;是指在不同进程之间传播或交换信息。IPC的方式通常有管道&#xff08;包括无名管道和命名管道&#xff09;、消息队列、信号量、共享内存、Socket&#xff08;套接字&a…

项目实战典型案例20——内存长期占用导致系统慢

内存长期占用导致系统慢一&#xff1a;背景介绍出现的问题二&#xff1a;思路&方案下面是对于这三个原因的解决方案1.服务启动时分配的堆内存过小2. 具有大量大对象被创建&#xff0c;并且没有及时被GC回收或者由于具有引用GC无法回收3.当GC之后&#xff0c;虽然会清理堆内…

再获认可!腾讯安全NDR获Forrester权威推荐

近日&#xff0c;国际权威研究机构Forrester发布最新研究报告《The Network Analysis And Visibility Landscape, Q1 2023》&#xff08;以下简称“NAV报告”&#xff09;&#xff0c;从网络分析和可视化&#xff08;NAV&#xff09;厂商规模、产品功能、市场占有率及重点案例等…

LeetCode刷题——回溯法

文章目录[中等]全排列[中等]全排列 II[中等]组合总和[中等]组合总和 II[中等]复原 IP 地址[中等]括号生成[中等]子集[中等]单词搜索[中等]组合[中等]全排列 原题链接题解 class Solution { public:vector<vector<int>> ans;vector<int> num;int flag[10];v…

三天吃透消息队列面试八股文

本文已经收录到Github仓库&#xff0c;该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点&#xff0c;欢迎star~ Github地址&#xff1a;https://github.com/…

OSPF路由协议总结

OSPF路由协议总结一 OSPF协议的三个工作步骤二 5中OSPF协议报文三 4种网络类型&#xff0c;邻居和邻接3.1 P2P3.2 P2MP3.3 Broadcase3.4 NBMA&#xff08;非广播多路访问&#xff09;四 OSPF协议的度量方式五 LS&#xff08;链路状态&#xff09; LSA&#xff08;链路状态通告&…

JMU软件20 大数据技术复习(只写了对比18提纲的变动部分)

原博主 博客主页&#xff1a;https://xiaojujiang.blog.csdn.net/ 原博客链接&#xff1a;https://blog.csdn.net/qq_43058685/article/details/117883940 本复习提纲只适用于JMU软件工程大数据课程&#xff08;ckm授课&#xff09; 具体内容参考老师提纲的考纲&#xff0c;18和…

使用Tensorflow完成一个简单的手写数字识别

Tensorflow中文手册 介绍TensorFlow_w3cschool 模型结构图&#xff1a; 首先明确模型的输入及输出&#xff08;先不考虑batch&#xff09; 输入&#xff1a;一张手写数字图&#xff08;28x28x1像素矩阵&#xff09; 1是通道数 输出&#xff1a;预测的数字&#xff08;1x10的one…

100种思维模型之信息传递思维模型-028

人与人之间存有 认知偏差和理解偏差 &#xff0c;信息在传递过程中会 衰减、失真以及再加工 &#xff01; 信息传递思维模型 &#xff0c;一个有助于 提高信息传递质量 的思维模型。下面从三个方面进行介绍&#xff0c; 何谓信息传递思维模型、信息传递思模型生活中的运…

JVM系统优化实践(9):G1垃圾回收器

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e;在JDK8及其之前&#xff0c;一直用的都是ParNewCMS的组合&#xff1a;ParNew负责年轻代的垃圾回收&#xff0c;而由CMS负责老年代的垃圾回收&#xff0c;但会产生…

脑机接口科普0016——独立BCI与非独立BCI

本文禁止转载&#xff01;&#xff01;&#xff01;&#xff01; 所谓的“独立BCI”与“非独立BCI”仅仅是BCI系统中的一个术语。本章主要是介绍一下这两个术语。 这两个术语是由Wolpaw在2002年提出来的。 独立BCI是指不依赖于中枢神经系统的的输出。 非独立BCI是指那种依赖…

工作5年了,你竟然还不会应用优雅停机?

事情是这样的&#xff0c;小明是一个工作五年的老程序员&#xff0c;半秃着的头已经彰显了他深不可测的技术实力。 这一天&#xff0c;小明收到了领导给过来的一个需求。 领导对小明说&#xff1a;“小明啊&#xff0c;你工作五年了&#xff0c;这个需求我交给你一个人负责很是…

开源写作平台WriteFreely(基础篇)

什么是 WriteFreely ? WriteFreely 是一个专为作家打造的干净、极简主义的出版平台。可以用来创建一个博客&#xff0c;在您的组织内分享知识&#xff0c;或者围绕共同的写作行为建立一个社区。 这里值得一提的是&#xff0c; WriteFreely 支持 ActivityPub 协议&#xff0c;这…