海量数据处理商用短链接生成器平台 - 2

第二章 短链平台项目创建+git代码管理+开发分层规范

第1集 短链平台实战-Maven聚合工程创建微服务项目

**简介:Maven聚合工程创建微服务项目实战 **

  • Maven聚合工程拆分

    • dcloud-common
      • 公共依赖包
    • dcloud-app
      • Flink+Kafka实时计算
    • dcloud-account
      • 账号+流量包微服务
    • dcloud-data
      • 数据可视化微服务
    • dcloud-gateway
      • 业务网关
    • dcloud-link
      • 短链微服务
    • dcloud-shop
      • 流量包商品+支付微服务
  • 创建项目(记得删除聚合工程src目录)

  • 添加依赖

  <properties>

        <!--JDK版本,如果是jdk8则这里是 1.8-->
        <java.version>11</java.version>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>


        <spring.boot.version>2.5.5</spring.boot.version>
        <spring.cloud.version>2020.0.4</spring.cloud.version>
        <alibaba.cloud.version>2021.1</alibaba.cloud.version>

        <mybatisplus.boot.starter.version>3.4.0</mybatisplus.boot.starter.version>
        <lombok.version>1.18.16</lombok.version>
        <commons.lang3.version>3.9</commons.lang3.version>
        <commons.codec.version>1.15</commons.codec.version>

        <xxl-job.version>2.3.0</xxl-job.version>

        <aliyun.oss.version>3.10.2</aliyun.oss.version>

        <captcha.version>1.1.0</captcha.version>

        <docker.image.prefix>dcloud</docker.image.prefix>

        <redission.version>3.10.1</redission.version>
        <jwt.version>0.7.0</jwt.version>
        <sharding-jdbc.version>4.1.1</sharding-jdbc.version>
        <!--跳过单元测试-->
        <skipTests>true</skipTests>
        <junit.version>4.12</junit.version>
        <druid.version>1.1.16</druid.version>

    </properties>
    
    
    

    <!--锁定版本-->
    <dependencyManagement>
        <dependencies>
            <!--https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies/2.3.3.RELEASE-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies/Hoxton.SR8-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-alibaba-dependencies/2.2.1.RELEASE-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${alibaba.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>



            <!--mybatis plus和springboot整合-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatisplus.boot.starter.version}</version>
            </dependency>

            <!--https://mvnrepository.com/artifact/org.projectlombok/lombok/1.18.16-->
            <!--scope=provided,说明它只在编译阶段生效,不需要打入包中, Lombok在编译期将带Lombok注解的Java文件正确编译为完整的Class文件-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <!--<scope>provided</scope>-->
            </dependency>



            <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>${commons.lang3.version}</version>
            </dependency>

            <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
            <!--用于加密-->
            <dependency>
                <groupId>commons-codec</groupId>
                <artifactId>commons-codec</artifactId>
                <version>${commons.codec.version}</version>
            </dependency>





            <!--验证码kaptcha依赖包-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>kaptcha-spring-boot-starter</artifactId>
                <version>${captcha.version}</version>
            </dependency>


            <!--阿里云oss-->
            <dependency>
                <groupId>com.aliyun.oss</groupId>
                <artifactId>aliyun-sdk-oss</artifactId>
                <version>${aliyun.oss.version}</version>
            </dependency>



            <!-- JWT相关 -->
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>${jwt.version}</version>
            </dependency>



            <!--分布式锁-->
            <dependency>
                <groupId>org.redisson</groupId>
                <artifactId>redisson</artifactId>
                <version>${redission.version}</version>
            </dependency>



             <!--https://mvnrepository.com/artifact/org.apache.shardingsphere/sharding-jdbc-spring-boot-starter-->
            <dependency>
                <groupId>org.apache.shardingsphere</groupId>
                <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
                <version>${sharding-jdbc.version}</version>
            </dependency>


            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>


            <!-- https://mvnrepository.com/artifact/com.xuxueli/xxl-job-core -->
            <dependency>
                <groupId>com.xuxueli</groupId>
                <artifactId>xxl-job-core</artifactId>
                <version>${xxl-job.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>

    <!-- 代码库 -->
    <repositories>
        <repository>
            <id>maven-ali</id>
            <url>http://maven.aliyun.com/nexus/content/groups/public//</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
                <updatePolicy>always</updatePolicy>
                <checksumPolicy>fail</checksumPolicy>
            </snapshots>
        </repository>
    </repositories>


    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

    <!--module不用添加打包版本信息-->
    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring.boot.version}</version>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>

第2集 Gitee仓库介绍和项目纳入版本管理+ignore文件配置

简介:开源中国Gitee仓库-介绍和项目纳入版本管理+ignore文件配置置

  • Git介绍

    • 是一个版本管理工具, 其作用就是可以让你更好的管理你的程序,比如你原来提交过的内容,以后虽然修改了,但是通过git这个工具,可以把你原来提交的内容重现出来,这样对于你后来才意识到的一些错误的更改,可以进行还原
  • 基于git协议的代码仓库

    • github 全球最大同性交友社区
    • gitee 开源中国
    • gitlab 开源的git仓库平台,阿里等大厂就是基于这个搭建
    • codeup 阿里云上的免费git仓库
  • gitee仓库地址

    • https://gitee.com/
  • 大课项目必须用git吗?

    • 如果是因为不会git,而不用则不行,因为这个是互联网公司必备的
    • 可以看联系客服看小滴课堂 git+gitlab专题视频
  • 本地安装文档

    • https://www.runoob.com/git/git-install-setup.html
    • https://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git
  • 大课项目加入git管理(是公钥设置,不是秘钥设置)

    • 本地生成公钥 ssh-keygen -t rsa -C “794666918@qq.com”
      • 生成公钥文档:https://gitee.com/help/articles/4181
      • 设置公钥文档:https://gitee.com/help/articles/4191#article-header0
    • 进入项目目录
  • 配置gitignore文件

    • 根目录创建文件 .gitignore
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
.DS_Store
.idea
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

在这里插入图片描述

第3集 阿里编码规范里面Manager分层介绍-和开发规范说明

简介:阿里编码规范里面Manager分层介绍-专用名词和POJO实体类约定

  • 开发人员:张三、李四、王五

  • 一定要避免单点故障

    • 一个微服务起码两个人熟悉:一个是主程一个是技术leader ,推荐是团队里面两个开发人员
  • N方库说明

一方库: 本工程内部子项目模块依赖的库(jar 包)二方库: 公司内部发布到中央仓库,可供公司内部其它应用依赖的库(jar包)三方库: 公司之外的开源库(jar 包)
  • POJO实体类
POJO(Plain Ordinary Java Object): 在手册中,POJO 专指只有 setter / getter / toString的简单类,包括DO/DTO/BO/VO等, 禁止命名成xxxPOJO
  • 各个层级约束规范
A) Service/DAO层方法命名规约
	1) 获取单个对象的方法用get做前缀。
	2) 获取多个对象的方法用list做前缀,复数形式结尾如:listObjects。 
	3) 获取统计值的方法用count做前缀。
	4) 插入的方法用save/insert做前缀。
	5) 删除的方法用remove/delete做前缀。
	6) 修改的方法用update做前缀。

B) 领域模型命名规约
  1) 数据对象:xxxDO,xxx即为数据表名。
  2) 一般数据传输对象:xxxDTO,xxx为业务领域相关的名称,项目里面也用VO。 
  3) 展示对象:xxxVO,也就是响应给前端的实体包装类。
  4) 接收前端json对象请求的命名为 XXXRequest
  • Manager分层说明 通用业务处理层,它有如下特征
    • 对第三方平台封装的层,预处理返回结果及转化异常信息
    • 对Service层通用能力的下沉,如缓存方案、中间件通用处理;
    • 与DAO层交互,对多个DAO的组合复用。

在这里插入图片描述

  • 更多开发规范,可以参考阿里巴巴编码手册(资料里面有 第6章第3集资料里面)
    • 有兴趣也可以安装IDEA编码扫描插件,不过前期可以先不用开启,会影响电脑卡顿和强迫症

第4集 dcloud-common通用模块配置使用实战和新版改动

简介:短链平台dcloud-common通用模块配置使用实战

  • pom文件配置
    <dependencies>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--项目中添加 spring-boot-starter-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


        <!--数据库连接-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--mybatis plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>


        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>


        <!--redis客户端-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>



        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

        <!--用于加密-->
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </dependency>

        <!-- JWT相关 -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
        </dependency>


        <!--redisson分布式锁-->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
        </dependency>

<!--Hoxton.M2版本之后不再使用Ribbon而是使用spring-cloud-loadbalancer,所以不引入spring-cloud-loadbalancer会报错,所以加入spring-cloud-loadbalancer依赖 并且在nacos中排除ribbon依赖,不然loadbalancer无效 -->

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>


        <!--配置中心, 留坑,后续用的时候再讲-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>


        <!--Feign远程调用-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>


        <!--限流依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>



        <!--限流持久化到nacos-->

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>



        <!--Springboot项目整合spring-kafka依赖包配置-->
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
        </dependency>



        <!--引入AMQP-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>


        <!--spring cache依赖包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>


        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
        </dependency>


        <!-- https://mvnrepository.com/artifact/com.xuxueli/xxl-job-core -->
        <!--分布式调度-->
        <dependency>
            <groupId>com.xuxueli</groupId>
            <artifactId>xxl-job-core</artifactId>
        </dependency>


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>

    </dependencies>

第5集 统一接口响应协议-响应工具类封装

简介:统一接口响应协议和响应工具类封装

  • 统一业务状态码 BizCodeEnum开发
    • 状态码定义约束,共6位数,前三位代表服务,后3位代表接口
    • 比如 商品服务210
/**
 * 
 *
 * @Description 状态码定义约束,共6位数,前三位代表服务,后3位代表接口
 *  比如 商品服务210,购物车是220、用户服务230,403代表权限
 *
 **/
public enum BizCodeEnum {


    /**
     * 短链分组
     */
    GROUP_REPEAT(23001,"分组名重复"),
    GROUP_OPER_FAIL(23503,"分组名操作失败"),
    GROUP_NOT_EXIST(23404,"分组不存在"),



    /**
     *验证码
     */
    CODE_TO_ERROR(240001,"接收号码不合规"),
    CODE_LIMITED(240002,"验证码发送过快"),
    CODE_ERROR(240003,"验证码错误"),
    CODE_CAPTCHA_ERROR(240101,"图形验证码错误"),



    /**
     * 账号
     */
    ACCOUNT_REPEAT(250001,"账号已经存在"),
    ACCOUNT_UNREGISTER(250002,"账号不存在"),
    ACCOUNT_PWD_ERROR(250003,"账号或者密码错误"),
    ACCOUNT_UNLOGIN(250004,"账号未登录"),


    /**
     * 短链
     */
    SHORT_LINK_NOT_EXIST(260404,"短链不存在"),


    /**
     * 订单
     */
    ORDER_CONFIRM_PRICE_FAIL(280002,"创建订单-验价失败"),
    ORDER_CONFIRM_REPEAT(280008,"订单恶意-重复提交"),
    ORDER_CONFIRM_TOKEN_EQUAL_FAIL(280009,"订单令牌缺少"),
    ORDER_CONFIRM_NOT_EXIST(280010,"订单不存在"),

    /**
     * 支付
     */
    PAY_ORDER_FAIL(300001,"创建支付订单失败"),
    PAY_ORDER_CALLBACK_SIGN_FAIL(300002,"支付订单回调验证签失败"),
    PAY_ORDER_CALLBACK_NOT_SUCCESS(300003,"支付宝回调更新订单失败"),
    PAY_ORDER_NOT_EXIST(300005,"订单不存在"),
    PAY_ORDER_STATE_ERROR(300006,"订单状态不正常"),
    PAY_ORDER_PAY_TIMEOUT(300007,"订单支付超时"),


    /**
     * 流控操作
     */
    CONTROL_FLOW(500101,"限流控制"),
    CONTROL_DEGRADE(500201,"降级控制"),
    CONTROL_AUTH(500301,"认证控制"),


    /**
     * 流量包操作
     */
    TRAFFIC_FREE_NOT_EXIST(600101,"免费流量包不存在,联系客服"),

    TRAFFIC_REDUCE_FAIL(600102,"流量不足,扣减失败"),

    TRAFFIC_EXCEPTION(600103,"流量包数据异常,用户无流量包"),


    /**
     * 通用操作码
     */

    OPS_REPEAT(110001,"重复操作"),
    OPS_NETWORK_ADDRESS_ERROR(110002,"网络地址错误"),


    /**
     * 文件相关
     */
    FILE_UPLOAD_USER_IMG_FAIL(700101,"用户头像文件上传失败");

    @Getter
    private String message;

    @Getter
    private int code;

    private BizCodeEnum(int code, String message){
        this.code = code;
        this.message = message;
    }
}

  • 接口统一协议 JsonData工具类开发
@Data
@AllArgsConstructor
@NoArgsConstructor
public class JsonData {

    /**
     * 状态码 0 表示成功
     */

    private Integer code;
    /**
     * 数据
     */
    private Object data;
    /**
     * 描述
     */
    private String msg;


    /**
     *  获取远程调用数据
     *  注意事项:
     *      支持多单词下划线专驼峰(序列化和反序列化)
     *
     *
     * @param typeReference
     * @param <T>
     * @return
     */
    public <T> T getData(TypeReference<T> typeReference){
        return JSON.parseObject(JSON.toJSONString(data),typeReference);
    }

    /**
     * 成功,不传入数据
     * @return
     */
    public static JsonData buildSuccess() {
        return new JsonData(0, null, null);
    }

    /**
     *  成功,传入数据
     * @param data
     * @return
     */
    public static JsonData buildSuccess(Object data) {
        return new JsonData(0, data, null);
    }

    /**
     * 失败,传入描述信息
     * @param msg
     * @return
     */
    public static JsonData buildError(String msg) {
        return new JsonData(-1, null, msg);
    }



    /**
     * 自定义状态码和错误信息
     * @param code
     * @param msg
     * @return
     */
    public static JsonData buildCodeAndMsg(int code, String msg) {
        return new JsonData(code, null, msg);
    }

    /**
     * 传入枚举,返回信息
     * @param codeEnum
     * @return
     */
    public static JsonData buildResult(BizCodeEnum codeEnum){
        return JsonData.buildCodeAndMsg(codeEnum.getCode(),codeEnum.getMessage());
    }
}

第6集 微服务自定义全局异常+处理器handler开发

简介:自定义全局异常+处理器开发

  • 自定义全局异常
/**
 * 全局异常处理
 */
@Data
public class BizException extends RuntimeException {

    private Integer code;
    private String msg;

    public BizException(Integer code, String message) {
        super(message);
        this.code = code;
        this.msg = message;
    }

    public BizException(BizCodeEnum bizCodeEnum) {
        super(bizCodeEnum.getMsg());
        this.code = bizCodeEnum.getCode();
        this.msg = bizCodeEnum.getMsg();
    }

}
  • 自定义异常处理器
@ControllerAdvice
@Slf4j
public class ExceptionHandle {

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public JsonData handle(Exception e) {

        if (e instanceof BizException) {
            BizException bizException = (BizException) e;
            log.info("[业务异常]{}", e);
            return JsonData.buildError(bizException.getMsg(), bizException.getCode());

        } else {
            log.info("[系统异常]{}", e);
            return JsonData.buildError("全局异常,未知错误");
        }

    }
}

第7集 common通用工具和时间格式化工具类

简介:common通用工具和时间格式化工具类讲解

  • 时间格式化工具类封装
public class TimeUtil {

    /**
     * 默认日期格式
     */
    private static final String DEFAULT_PATTERN = "yyyy-MM-dd HH:mm:ss";

    /**
     * 默认日期格式
     */
    private static final DateTimeFormatter DEFAULT_DATE_TIME_FORMATTER  = DateTimeFormatter.ofPattern(DEFAULT_PATTERN);

    private static final  ZoneId DEFAULT_ZONE_ID = ZoneId.systemDefault();


    /**
     * LocalDateTime 转 字符串,指定日期格式
     * @param time
     * @param pattern
     * @return
     */
    public static String format(LocalDateTime localDateTime,String pattern){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        String timeStr = formatter.format(localDateTime.atZone(DEFAULT_ZONE_ID));
        return timeStr;
    }


    /**
     * Date 转 字符串, 指定日期格式
     * @param time
     * @param pattern
     * @return
     */
    public static String format(Date time,String pattern){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        String timeStr = formatter.format(time.toInstant().atZone(DEFAULT_ZONE_ID));
        return timeStr;
    }

    /**
     *  Date 转 字符串,默认日期格式
     * @param time
     * @return
     */
    public static String format(Date time){

        String timeStr = DEFAULT_DATE_TIME_FORMATTER.format(time.toInstant().atZone(DEFAULT_ZONE_ID));
        return timeStr;
    }

    /**
     * timestamp 转 字符串,默认日期格式
     *
     * @param time
     * @return
     */
    public static String format(long timestamp) {
        String timeStr = DEFAULT_DATE_TIME_FORMATTER.format(new Date(timestamp).toInstant().atZone(DEFAULT_ZONE_ID));
        return timeStr;
    }


    /**
     * 字符串 转 Date
     *
     * @param time
     * @return
     */
    public static Date strToDate(String time) {
        LocalDateTime localDateTime = LocalDateTime.parse(time, DEFAULT_DATE_TIME_FORMATTER);
        return Date.from(localDateTime.atZone(DEFAULT_ZONE_ID).toInstant());

    }


    /**
     * 获取当天剩余的秒数,用于流量包过期配置
     * @param currentDate
     * @return
     */
    public static Integer getRemainSecondsOneDay(Date currentDate) {
        LocalDateTime midnight = LocalDateTime.ofInstant(currentDate.toInstant(),
                ZoneId.systemDefault()).plusDays(1).withHour(0).withMinute(0)
                .withSecond(0).withNano(0);
        LocalDateTime currentDateTime = LocalDateTime.ofInstant(currentDate.toInstant(),
                ZoneId.systemDefault());
        long seconds = ChronoUnit.SECONDS.between(currentDateTime, midnight);
        return (int) seconds;
    }
}
  • Json序列化工具类封装
public class JsonUtil {

    private static final ObjectMapper mapper = new ObjectMapper();

    static {

        //设置可用单引号
        mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);

        //序列化的时候序列对象的所有属性
        mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);

        //反序列化的时候如果多了其他属性,不抛出异常
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        //如果是空对象的时候,不抛异常
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

        //取消时间的转化格式,默认是时间戳,可以取消,同时需要设置要表现的时间格式
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    }



    /**
     * 对象转为Json字符串
     * @param data
     * @return
     */
    public static String obj2Json(Object obj) {
        String jsonStr = null;
        try {
            jsonStr = mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return jsonStr;
    }
    /**
     * json字符串转为对象
     * @param str
     * @param valueType
     * @return
     */
    public static <T> T json2Obj(String jsonStr, Class<T> beanType) {
        T obj = null;
        try {
            obj = mapper.readValue(jsonStr, beanType);
        } catch (Exception e){
            e.printStackTrace();
        }
        return obj;
    }


    /**
     * json数据转换成pojo对象list
     * @param jsonData
     * @param beanType
     * @return
     */
    public static <T> List<T> json2List(String jsonData, Class<T> beanType) {
        JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, beanType);
        try {
            List<T> list = mapper.readValue(jsonData, javaType);
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 对象转为byte数组
     * @param data
     * @return
     */
    public static byte[] obj2Bytes(Object obj) {
        byte[] byteArr = null;
        try {
            byteArr = mapper.writeValueAsBytes(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return byteArr;
    }



    /**
     * byte数组转为对象
     * @param byteArr
     * @param valueType
     * @return
     */
    public static <T> T bytes2Obj(byte[] byteArr, Class<T> beanType) {
        T obj = null;
        try {
            obj = mapper.readValue(byteArr, beanType);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }

}
  • common工具大集合
@Slf4j
public class CommonUtil {

    /**
     * 获取ip
     *
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = null;
        try {
            ipAddress = request.getHeader("x-forwarded-for");
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                if (ipAddress.equals("127.0.0.1")) {
                    // 根据网卡取本机配置的IP
                    InetAddress inet = null;
                    try {
                        inet = InetAddress.getLocalHost();
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                    ipAddress = inet.getHostAddress();
                }
            }
            // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
            if (ipAddress != null && ipAddress.length() > 15) {
                // "***.***.***.***".length()
                // = 15
                if (ipAddress.indexOf(",") > 0) {
                    ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
                }
            }
        } catch (Exception e) {
            ipAddress = "";
        }
        return ipAddress;
    }


    /**
     * 获取全部请求头
     * @param request
     * @return
     */
    public static Map<String, String> getAllRequestHeader(HttpServletRequest request){
        Enumeration<String> headerNames = request.getHeaderNames();
        Map<String, String> map = new HashMap<>();
        while (headerNames.hasMoreElements()) {
            String key = (String)headerNames.nextElement();
            //根据名称获取请求头的值
            String value = request.getHeader(key);
            map.put(key,value);
        }

        return map;
    }


    /**
     * MD5加密
     *
     * @param data
     * @return
     */
    public static String MD5(String data) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] array = md.digest(data.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
            }

            return sb.toString().toUpperCase();
        } catch (Exception exception) {
        }
        return null;

    }


    /**
     * 获取验证码随机数
     *
     * @param length
     * @return
     */
    public static String getRandomCode(int length) {

        String sources = "0123456789";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int j = 0; j < length; j++) {
            sb.append(sources.charAt(random.nextInt(9)));
        }
        return sb.toString();
    }


    /**
     * 获取当前时间戳
     *
     * @return
     */
    public static long getCurrentTimestamp() {
        return System.currentTimeMillis();
    }


    /**
     * 生成uuid
     *
     * @return
     */
    public static String generateUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
    }

    /**
     * 获取随机长度的串
     *
     * @param length
     * @return
     */
    private static final String ALL_CHAR_NUM = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    public static String getStringNumRandom(int length) {
        //生成随机数字和字母,
        Random random = new Random();
        StringBuilder saltString = new StringBuilder(length);
        for (int i = 1; i <= length; ++i) {
            saltString.append(ALL_CHAR_NUM.charAt(random.nextInt(ALL_CHAR_NUM.length())));
        }
        return saltString.toString();
    }


    /**
     * 响应json数据给前端
     *
     * @param response
     * @param obj
     */
    public static void sendJsonMessage(HttpServletResponse response, Object obj) {

        response.setContentType("application/json; charset=utf-8");

        try (PrintWriter writer = response.getWriter()) {
            writer.print(JsonUtil.obj2Json(obj));
            response.flushBuffer();

        } catch (IOException e) {
            log.warn("响应json数据给前端异常:{}",e);
        }


    }

}

c String generateUUID() {
return UUID.randomUUID().toString().replaceAll(“-”, “”).substring(0, 32);
}

/**
 * 获取随机长度的串
 *
 * @param length
 * @return
 */
private static final String ALL_CHAR_NUM = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

public static String getStringNumRandom(int length) {
    //生成随机数字和字母,
    Random random = new Random();
    StringBuilder saltString = new StringBuilder(length);
    for (int i = 1; i <= length; ++i) {
        saltString.append(ALL_CHAR_NUM.charAt(random.nextInt(ALL_CHAR_NUM.length())));
    }
    return saltString.toString();
}


/**
 * 响应json数据给前端
 *
 * @param response
 * @param obj
 */
public static void sendJsonMessage(HttpServletResponse response, Object obj) {

    response.setContentType("application/json; charset=utf-8");

    try (PrintWriter writer = response.getWriter()) {
        writer.print(JsonUtil.obj2Json(obj));
        response.flushBuffer();

    } catch (IOException e) {
        log.warn("响应json数据给前端异常:{}",e);
    }


}

}




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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

程序报错无法打开源文件stdafx.h

在运行代码时&#xff0c;代码中头文件突然报错程序无法打开源文件stdafx.h include “stdafx.h”,编译器就说无法打开源文件&#xff0c;直接上干货解决方法是&#xff1a; 1.打开项目 ->项目属性&#xff08;最后一个&#xff09;-> C/C ->常规&#xff0c; 2在附…

【MySQL】——数据定义

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

第二十二回 横海郡柴进留宾 景阳冈武松打虎-大模型ChatGLM2-6B新手速通

柴进说这人叫武松&#xff0c;排名老二。宋江说江湖上听说过武二郎的名字&#xff0c;幸会幸会&#xff0c;就拉着武松的手&#xff0c;一起喝酒吃饭。 武松是家喻户晓的打虎英雄&#xff0c;现在最流行的是大模型&#xff01; 大模型ChatGLM2-6B新手速通&#xff01; 人工智能…

成都爱尔林江院长解读儿童青少年为什么一定要进行医学验光配镜

根据国家卫健委数据显示&#xff1a;我国青少年儿童总体近视率为52.7%、高度近视人口超3000万。近视学生中,有10%为高度近视,且占比随年级升高而增长。 近视孩子之多&#xff0c;孩子视力发展备受关注。戴镜进行近视防控十分必要&#xff0c;且眼镜不可随意验配&#xff01; 成…

超越体量:TinyLlama用1.1B参数实现大模型级性能

引言 随着人工智能技术的快速发展&#xff0c;大型语言模型&#xff08;LLM&#xff09;在全球范围内受到瞩目。但与此同时&#xff0c;另一类模型正在逐渐崭露头角&#xff1a;参数规模较小的语言模型。这类模型在计算资源受限的环境下显示出巨大潜力&#xff0c;特别是在智能…

SpringbootV2.6整合Knife4j 3.0.3 问题记录

参考 https://juejin.cn/post/7249173717749940284 近期由于升级到springboot2.6X&#xff0c;所以服务端很多组件都需要重新导入以及解决依赖问题。 下面就是一个很经典的问题了&#xff0c; springboot2.6与knife4j的整合。 版本对应 springboot2.6与knife4j 3.0.3 坑 …

STM32外部中断(红外传感器与旋转编码器计数案例)

文章目录 一、介绍部分简介中断系统中断执行流程STM32中断NVIC基本结构NVIC优先级分组外部中断外部中断简介外部中断基本结构外部中断的流程AFIOEXTI框图 相关外设介绍旋转编码器介绍硬件电路对射式红外传感器 二、代码实现对射式红外传感器计次连接电路封装红外传感器与中断函…

JDK17中的密封类sealed和permits使用指南:什么是Java中的sealed和permits?

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

【工作周志】240129-240204

本周学习了AXI相关的内容 AMBA &#xff08;Advanced Microcontroller Bus Architecture&#xff09; AXI &#xff08;Advanced eXtensible Interface&#xff09; ARM公司提出&#xff0c;AMBA3.0协议中重要组成部分&#xff0c;是一种面向高性能、高带宽、低延迟的片内总线…

docker入门教程之将应用程序容器化

将应用程序容器化 在本指南的其余部分中&#xff0c;您将使用在 Node.js 上运行的简单待办事项列表管理器。如果您不熟悉 Node.js&#xff0c;请不要担心。本指南不需要任何 JavaScript 经验。 先决条件 您已安装最新版本的 Docker Desktop。您已经安装了 Git 客户端。您可以…

手把手教你开发Python桌面应用-PyQt6图书管理系统-图书类别添加模块UI设计实现

锋哥原创的PyQt6图书管理系统视频教程&#xff1a; PyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~_哔哩哔哩_bilibiliPyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~共计24条视频&…

【React】react组件传参、redux状态管理

【React】react组件传参、redux状态管理 一、props&#xff1a;父组件向子组件传参1、将普通的参数作为props传递2、将jsx作为props传递&#xff08;组件插槽&#xff09;&#xff08;1&#xff09;基础功能示例&#xff08;2&#xff09;进阶示例 二、自定义事件&#xff1a;子…

【前端必备】深入详解Vue2/Vue3 diff算法实现思路

在做diff算法之前有个基本逻辑要明白&#xff0c;Vue的diff算法是同层比较&#xff0c;不会跨层比较&#xff0c;时间复杂度为O(N)。 主要使用首尾比较法&#xff08;头-头&#xff0c;头-尾&#xff0c;尾-头&#xff0c;尾-尾&#xff09;。Vue2与Vue3的diff算法主要区别是处…

Mysql运维篇(四) MySQL常用命令

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人。如有侵权&#xff0c;请留言&#xff0c;我及时删除&#xff01; 一、MySQL命令速查表 https://www.cnblogs.com/pyng/p/15560059.html Mysql DBA运维命令大全 - 墨…

【大厂AI课学习笔记】1.4 算法的进步(4)关于李飞飞团队的ImageNet

第一个图像数据库是ImageNet&#xff0c;由斯坦福大学的计算机科学家李飞飞推出。ImageNet是一个大型的可视化数据库&#xff0c;旨在推动计算机视觉领域的研究。这个数据库包含了数以百万计的手工标记的图像&#xff0c;涵盖了数千个不同的类别。 基于ImageNet数据库&#xf…

OpenSSL:configure: error: OpenSSL library not found解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

JavaWeb01-JDBC、Druid连接池

目录 一、JDBC 1.概述 2.本质 3.好处 4.使用步骤 5.JDBC_API &#xff08;1&#xff09;DriverManager&#xff08;驱动管理类&#xff09; &#xff08;2&#xff09;Connection&#xff08;数据库连接对象&#xff09; &#xff08;3&#xff09;Statement &#xf…

2024-02-01 Unity Shader 开发入门4 —— ShaderLab 语法

文章目录 1 材质和 Shader1.1 Unity Shader 和 Shader 的区别1.2 Unity 中的材质和 Shader1.3 创建材质1.4 创建 Shader 2 ShaderLab 的基本结构2.1 什么是 ShaderLab2.2 ShaderLab 的基本结构 3 Shader 名称4 Shader 属性4.1 Shader 属性的作用4.2 Shader 属性的基本语法4.3 数…

C++初阶:适合新手的手撕string类(模拟实现string类)

上次讲了常用的接口&#xff1a;C初阶&#xff1a;初识STL、String类接口详细讲解&#xff08;万字解析&#xff09; 今天就来进行模拟实现啦 文章目录 1.基本结构与文件规划2.构造函数&#xff08;constructor)2.1构造函数2.1.1无参有参分开2.1.2利用缺省参数合起来 2.2拷贝构…

基于YOLOv8算法的照片角度分类项目实践

目录 一、任务概述二、YOLOv8算法简介2.1 算法改进2.2 算法特点2.3 网络结构2.4 性能比较 三、工程实践3.1 安装算法框架库ultralytics3.2 库存照片预处理3.2.1 提取所有图片3.2.2 去除冗余的相同照片3.2.3 去除无车辆照片3.2.4 随机提取指定数量的图片 3.3 照片朝向分类3.3.1 …