zoukankan      html  css  js  c++  java
  • springboot使用小tip

    1.springboot2.0.x和springboot2.1.x使用不同点:

     springboot2.1.x版本的时候,写数据库驱动和数据库路径时候是不一样的

    spring.datasource.driver-class-name= com.mysql.cj.jdbc.Driver

    spring.datasource.url=jdbc:mysql://localhost:3306/chixue_web?characterEncoding=utf-8&serverTimezone=Asia/Shanghai

    2.springboot1.x和springboot2.x的区别:

      springboot1.x底层使用spring4.x

      springboot2.x底层使用spring5.x(有强大的注解)

    3.分布式id生成策略:

    (1)mysql数据库自动增长

    (2)redis的原子操作

    (3)mp自带增长策略,使用snowflake算法

    4.mybatis-plus自动填充时间

    在字段上面加上注解@TableField(fill=FillField.INSERT) 添加时,@TableField(fill=FillField.UPDATE)修改时候,时间跟着修改

    必备条件:创建类MyMetaObjectHandler实现类MetaObjectHandler,重写insertFill和updateFill方法,具体写法:this.setFieldValByName("createTime",new Date(),metaObject);

    5.springboot依赖管理

    1)我们在创建springboot项目时候会发现每个新建的springboot项目都有一个父依赖

     <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.4.0.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
     </parent>

    2)每个springboot-web项目都有web依赖

     <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
     </dependency>

    3)总结

    1. 首先springboot的核心就是starter模块核心依赖和autoconfiguration自动配置
    starter:每个spring框架都有与之对应的starter,如springmvc有spring-boot-starter-web,spring-boot-starter-web 内置web容
    器tomcat等
    autoconfiguration:自动化配置为springboot项目简化了繁琐的配置文件;核心就是通过@SpringBootApplication继承了
    @SpringbootConfiguration和@EnableAutoConfiguration还有@ComponentScan这三个注解;可以通过
    spring-boot-autoconfiguration-1.2.*.RELEASE.jar里面的spring-configuration-metadata.json看到所有当前
    starter(框架)下面所有定义的配置属性。
    2. spring-boot-starter-parent是一个springboot项目的父工程,它定义了很多当前项目的规范,比如:
    a:定义了Java编译版本为 1.8.
    b:使用UTF-8格式编码。
    c:继承自spring-boot-dependencies,这个里面定义了依赖的版本,也是因为继承了这个依赖,我们在写依赖时才不需要写版本号。
    d:执行打包操作的配置。
    e:自动化的资源过滤。
    f: 自动化的插件配置。
    g:针对 application.properties 和application.yml 的资源过滤,包括通过profile定义不同的环境配置文件,application-dev.properties 和application-pro.properties.
    3. 所以一般的maven父pom工程可能会继承spring-boot-dependencies

            <dependencyManagement>
                   <dependencies>
                       <dependency>
                           <groupId>org.springframework.boot</groupId>
                           <artifactId>spring-boot-dependencies</artifactId>
                           <version>2.1.4.RELEASE</version>
                           <type>pom</type>
                           <scope>import</scope>
                       </dependency>
                   </dependencies>
               </dependencyManagement>

    这样虽然以来的版本号问题解决了,但是唯独parent依赖解决的那些打包插件配置,编译的jdk版本,文件编码格式等等这些配置,在没有parent的时候,都需要自己再去配置。这就是parent依赖的重要作用。

    6.springboot整合定时任务

    1.在启动类添加注解@EnableScheduling

    2.创建定时任务类

    在这个类里面使用表达式设置什么时候去执行

    corn表达式

    @Component
    public class ScheduledTask {
    
        /**
         * 每隔五秒去执行这个方法
         */
        @Scheduled(cron = "0/5 * * * * ?")
        public void task1() {
            System.out.println("task1执行了");
        }
    }

    在线生成corn 表达式工具 https://www.pppet.net/

    7.springboot异常处理

    7.1 全局异常处理

    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        @ExceptionHandler(Exception.class)
        @ResponseBody
        public Result error(Exception e){
            e.printStackTrace();
            return Result.fail();
        }
    }

    7.2 自定义异常

        @ExceptionHandler(HospitalException.class)
        @ResponseBody
        public Result error(HospitalException e){
            e.printStackTrace();
            return Result.fail();
        }

    @Data
    public class HospitalException extends RuntimeException{
    
        @ApiModelProperty(value = "异常状态码")
        private Integer code;
    
        /**
         * 通过状态码和错误消息创建异常对象
         * @param message
         * @param code
         */
        public HospitalException(Integer code,String message) {
            super(message);
            this.code = code;
        }
    
        /**
         * 接收枚举类型对象
         * @param resultCodeEnum
         */
        public HospitalException(ResultCodeEnum resultCodeEnum) {
            super(resultCodeEnum.getMessage());
            this.code = resultCodeEnum.getCode();
        }
    
        @Override
        public String toString() {
            return "HospitalException{" +
                    "code=" + code +
                    ", message=" + this.getMessage() +
                    '}';
        }
    
    }

    8.统一返回格式

    全局统一返回结果类

    package com.gh.result;
    
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    
    /**
     * 全局统一返回结果类
     */
    @Data
    @ApiModel(value = "全局统一返回结果")
    public class Result<T> {
    
        @ApiModelProperty(value = "返回码")
        private Integer code;
    
        @ApiModelProperty(value = "返回消息")
        private String message;
    
        @ApiModelProperty(value = "返回数据")
        private T data;
    
        public Result(){}
    
        protected static <T> Result<T> build(T data) {
            Result<T> result = new Result<T>();
            if (data != null)
                result.setData(data);
            return result;
        }
    
        public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
            Result<T> result = build(body);
            result.setCode(resultCodeEnum.getCode());
            result.setMessage(resultCodeEnum.getMessage());
            return result;
        }
    
        public static <T> Result<T> build(Integer code, String message) {
            Result<T> result = build(null);
            result.setCode(code);
            result.setMessage(message);
            return result;
        }
    
        public static<T> Result<T> ok(){
            return Result.ok(null);
        }
    
        /**
         * 操作成功
         * @param data
         * @param <T>
         * @return
         */
        public static<T> Result<T> ok(T data){
            Result<T> result = build(data);
            return build(data, ResultCodeEnum.SUCCESS);
        }
    
        public static<T> Result<T> fail(){
            return Result.fail(null);
        }
    
        /**
         * 操作失败
         * @param data
         * @param <T>
         * @return
         */
        public static<T> Result<T> fail(T data){
            Result<T> result = build(data);
            return build(data, ResultCodeEnum.FAIL);
        }
    
        public Result<T> message(String msg){
            this.setMessage(msg);
            return this;
        }
    
        public Result<T> code(Integer code){
            this.setCode(code);
            return this;
        }
    
        public boolean isOk() {
            if(this.getCode().intValue() == ResultCodeEnum.SUCCESS.getCode().intValue()) {
                return true;
            }
            return false;
        }
    }
    View Code

    枚举类型

    package com.gh.result;
    
    import lombok.Getter;
    
    /**
     * 统一返回结果状态信息类
     */
    @Getter
    public enum ResultCodeEnum {
    
        SUCCESS(200,"成功"),
        FAIL(201, "失败"),
        PARAM_ERROR( 202, "参数不正确"),
        SERVICE_ERROR(203, "服务异常"),
        DATA_ERROR(204, "数据异常"),
        DATA_UPDATE_ERROR(205, "数据版本异常"),
    
        LOGIN_AUTH(208, "未登陆"),
        PERMISSION(209, "没有权限"),
    
        CODE_ERROR(210, "验证码错误"),
    //    LOGIN_MOBLE_ERROR(211, "账号不正确"),
        LOGIN_DISABLED_ERROR(212, "改用户已被禁用"),
        REGISTER_MOBLE_ERROR(213, "手机号已被使用"),
        LOGIN_AURH(214, "需要登录"),
        LOGIN_ACL(215, "没有权限"),
    
        URL_ENCODE_ERROR( 216, "URL编码失败"),
        ILLEGAL_CALLBACK_REQUEST_ERROR( 217, "非法回调请求"),
        FETCH_ACCESSTOKEN_FAILD( 218, "获取accessToken失败"),
        FETCH_USERINFO_ERROR( 219, "获取用户信息失败"),
        //LOGIN_ERROR( 23005, "登录失败"),
    
        PAY_RUN(220, "支付中"),
        CANCEL_ORDER_FAIL(225, "取消订单失败"),
        CANCEL_ORDER_NO(225, "不能取消预约"),
    
        HOSCODE_EXIST(230, "医院编号已经存在"),
        NUMBER_NO(240, "可预约号不足"),
        TIME_NO(250, "当前时间不可以预约"),
    
        SIGN_ERROR(300, "签名错误"),
        HOSPITAL_OPEN(310, "医院未开通,暂时不能访问"),
        HOSPITAL_LOCK(320, "医院被锁定,暂时不能访问"),
        ;
    
        private Integer code;
        private String message;
    
        private ResultCodeEnum(Integer code, String message) {
            this.code = code;
            this.message = message;
        }
    }
    View Code

    9.springboot统一日志输出

    在resources目录下新建logback-spring.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration  scan="true" scanPeriod="10 seconds">
        <!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
        <!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
        <!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
        <!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
    
        <contextName>logback</contextName>
        <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
        <property name="log.path" value="F://Android" />
    
        <!-- 彩色日志 -->
        <!-- 配置格式变量:CONSOLE_LOG_PATTERN 彩色日志格式 -->
        <!-- magenta:洋红 -->
        <!-- boldMagenta:粗红-->
        <!-- cyan:青色 -->
        <!-- white:白色 -->
        <!-- magenta:洋红 -->
        <property name="CONSOLE_LOG_PATTERN"
                  value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/>
    
    
        <!--输出到控制台-->
        <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
            <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
            <!-- 例如:如果此处配置了INFO级别,则后面其他位置即使配置了DEBUG级别的日志,也不会被输出 -->
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>INFO</level>
            </filter>
            <encoder>
                <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
                <!-- 设置字符集 -->
                <charset>UTF-8</charset>
            </encoder>
        </appender>
    
    
        <!--输出到文件-->
    
        <!-- 时间滚动输出 level为 INFO 日志 -->
        <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!-- 正在记录的日志文件的路径及文件名 -->
            <file>${log.path}/log_info.log</file>
            <!--日志文件输出格式-->
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
                <charset>UTF-8</charset>
            </encoder>
            <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <!-- 每天日志归档路径以及格式 -->
                <fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>100MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
                <!--日志文件保留天数-->
                <maxHistory>15</maxHistory>
            </rollingPolicy>
            <!-- 此日志文件只记录info级别的 -->
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>INFO</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
        </appender>
    
        <!-- 时间滚动输出 level为 WARN 日志 -->
        <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!-- 正在记录的日志文件的路径及文件名 -->
            <file>${log.path}/log_warn.log</file>
            <!--日志文件输出格式-->
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
                <charset>UTF-8</charset> <!-- 此处设置字符集 -->
            </encoder>
            <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>100MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
                <!--日志文件保留天数-->
                <maxHistory>15</maxHistory>
            </rollingPolicy>
            <!-- 此日志文件只记录warn级别的 -->
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>warn</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
        </appender>
    
    
        <!-- 时间滚动输出 level为 ERROR 日志 -->
        <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <!-- 正在记录的日志文件的路径及文件名 -->
            <file>${log.path}/log_error.log</file>
            <!--日志文件输出格式-->
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
                <charset>UTF-8</charset> <!-- 此处设置字符集 -->
            </encoder>
            <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>100MB</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
                <!--日志文件保留天数-->
                <maxHistory>15</maxHistory>
            </rollingPolicy>
            <!-- 此日志文件只记录ERROR级别的 -->
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>ERROR</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
        </appender>
    
        <!--
            <logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。
            <logger>仅有一个name属性,
            一个可选的level和一个可选的addtivity属性。
            name:用来指定受此logger约束的某一个包或者具体的某一个类。
            level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
                  如果未设置此属性,那么当前logger将会继承上级的级别。
        -->
        <!--
            使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
            第一种把<root level="INFO">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
            第二种就是单独给mapper下目录配置DEBUG模式,代码如下,这样配置sql语句会打印,其他还是正常DEBUG级别:
         -->
        <!--开发环境:打印控制台-->
        <springProfile name="dev">
            <!--可以输出项目中的debug日志,包括mybatis的sql日志-->
            <logger name="jw.hospital" level="INFO" />
    
            <!--
                root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
                level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,默认是DEBUG
                可以包含零个或多个appender元素。
            -->
            <root level="INFO">
                <appender-ref ref="CONSOLE" />
                <appender-ref ref="INFO_FILE" />
                <appender-ref ref="WARN_FILE" />
                <appender-ref ref="ERROR_FILE" />
            </root>
        </springProfile>
    
    
        <!--生产环境:输出到文件-->
        <springProfile name="pro">
    
            <root level="INFO">
                <appender-ref ref="CONSOLE" />
                <appender-ref ref="DEBUG_FILE" />
                <appender-ref ref="INFO_FILE" />
                <appender-ref ref="ERROR_FILE" />
                <appender-ref ref="WARN_FILE" />
            </root>
        </springProfile>
    
    </configuration>
    View Code

    一点点学习,一丝丝进步。不懈怠,才不会被时代所淘汰!

  • 相关阅读:
    笨办法学习python之hashmap
    python实现三级菜单源代码
    ql的python学习之路-day3
    ql的python学习之路-day2
    Spring的数据库开发
    Spring学习之Aspectj开发实现AOP
    spring学习之依赖注入DI与控制反转IOC
    spring学习之第一个spring程序
    spring学习之spring入门
    Java线程(一)——创建线程的两种方法
  • 原文地址:https://www.cnblogs.com/fqh2020/p/14575329.html
Copyright © 2011-2022 走看看