Spring Boot 优雅实现统一数据返回格式+统一异常处理+统一日志处理

news2024/12/25 13:45:54

        在我们的项目开发中,我们都会对数据返回格式进行统一的处理,这样可以方便前端人员取数据,当然除了正常流程的数据返回格式需要统一以外,我们也需要对异常的情况进行统一的处理,以及项目必备的日志。

1. 统一返回格式

        在项目开发中返回的是json格式的数据,也就是统一json数据返回格式,一般情况下返回数据的基本格式包含是否成功、响应状态码、返回的消息、以及返回的数据。格式如下:

{
  "success": 布尔,      // 是否成功
  "code": 数字,         // 响应状态码
  "message": 字符串,    // 返回的消息
  "data": {}           //  放置响应的数据
}

1.1 添加枚举类

        该类定义了以上统一格式的前三部分:是否成功、响应状态码、返回的消息;可自行根据项目需要进行后续的添加或者删改。

创建一个result包,下面放置ResultCodeEnum枚举类

/**
 * 状态码
 *
 */
public enum ResultCodeEnum {
 
    SUCCESS(true, 20000, "成功"),
 
    UNKNOWN_REASON(false, 20001, "未知错误");
 
    private final Boolean success;
 
    private final Integer code;
 
    private final String message;
 
    ResultCodeEnum(Boolean success, Integer code, String message) {
        this.success = success;
        this.code = code;
        this.message = message;
    }
 
    public Boolean getSuccess() {
        return success;
    }
 
    public Integer getCode() {
        return code;
    }
 
    public String getMessage() {
        return message;
    }
 
    @Override
    public String toString() {
        return "ResultCodeEnum{" + "success=" + success + ", code=" + code + ", message='" + message + '\'' + '}';
    }
}

1.2 添加统一返回格式的类

该类是用来和前端交互的类,定义的就是本文开头所说的格式

在result包下创建一个统一返回格式的类R

/**
 * 统一返回格式类
 *
 */
public class R {
 
    /**
     * 是否成功
     */
    private Boolean success;
 
    /**
     * 状态码
     */
    private Integer code;
 
    /**
     * 返回的消息
     */
    private String message;
 
    /**
     * 放置响应的数据
     */
    private Map<String, Object> data = new HashMap<>();
 
    public R() {}
 
    /** 以下是定义一些常用到的格式,可以看到调用了我们创建的枚举类 */
    
    public static R ok() {
        R r = new R();
        r.setSuccess(ResultCodeEnum.SUCCESS.getSuccess());
        r.setCode(ResultCodeEnum.SUCCESS.getCode());
        r.setMessage(ResultCodeEnum.SUCCESS.getMessage());
        return r;
    }
 
    public static R error() {
        R r = new R();
        r.setSuccess(ResultCodeEnum.UNKNOWN_REASON.getSuccess());
        r.setCode(ResultCodeEnum.UNKNOWN_REASON.getCode());
        r.setMessage(ResultCodeEnum.UNKNOWN_REASON.getMessage());
        return r;
    }
 
    public static R setResult(ResultCodeEnum resultCodeEnum) {
        R r = new R();
        r.setSuccess(resultCodeEnum.getSuccess());
        r.setCode(resultCodeEnum.getCode());
        r.setMessage(resultCodeEnum.getMessage());
        return r;
    }
 
    public R success(Boolean success) {
        this.setSuccess(success);
        return this;
    }
 
    public R message(String message) {
        this.setMessage(message);
        return this;
    }
 
    public R code(Integer code) {
        this.setCode(code);
        return this;
    }
 
    public R data(String key, Object value) {
        this.data.put(key, value);
        return this;
    }
 
    public R data(Map<String, Object> map) {
        this.setData(map);
        return this;
    }
 
    /** 以下是get/set方法,如果项目有集成lombok可以使用@Data注解代替 */
 
    public Boolean getSuccess() {
        return success;
    }
 
    public void setSuccess(Boolean success) {
        this.success = success;
    }
 
    public Integer getCode() {
        return code;
    }
 
    public void setCode(Integer code) {
        this.code = code;
    }
 
    public String getMessage() {
        return message;
    }
 
    public void setMessage(String message) {
        this.message = message;
    }
 
    public Map<String, Object> getData() {
        return data;
    }
 
    public void setData(Map<String, Object> data) {
        this.data = data;
    }
}

 1.3 测试

/**
 * 测试控制器
 *
 */
@RestController
@RequestMapping("testR")
public class TestController {
 
    @GetMapping("ok")
    public R testOk() {
        Map<String, Object> data = new HashMap<>();
        data.put("name", "李太白");
        return R.ok().data(data);
    }
}

        可以看到格式是正确的,只要我们返回数据的时候使用R这个类返回就行了,不过有一种情况,就是当我们代码中抛出异常之后返回的格式就不是这样子了,下面我演示一下在代码中添加int a = 1/0的语句,肯定导致抛异常的; 

/**
 * 测试控制器
 *
 */
@RestController
@RequestMapping("testR")
public class TestController {
 
    @GetMapping("ok")
    public R testOk() {
        int a = 1/0;
        Map<String, Object> data = new HashMap<>();
        data.put("name", "李太白");
        return R.ok().data(data);
    }
}

        可以发现返回的格式已经不是我们所需要的格式了,这种情况会给前端人员带来不必要的麻烦,所以我们也需要对异常情况进行统一的格式处理; 

2. 统一异常处理

        经过上面的演示,相信你已经明白我们为什么需要进行统一的异常处理了,当然处理统一的异常处理以外我们在开发项目中也会主动的抛出异常,像这种情况我们需要配合自定义异常来完成;

2.1 添加统一异常处理器

创建一个handler包,在该包下面添加GlobalExceptionHandler类

/**
 * 统一异常处理
 * ControllerAdvice注解的含义是当异常抛到controller层时会拦截下来
 */
@ControllerAdvice
public class GlobalExceptionHandler {
 
    /**
     * 使用ExceptionHandler注解声明处理Exception异常
     *
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public R exception(Exception e) {
        // 控制台打印异常
        e.printStackTrace();
        // 返回错误格式信息
        return R.error();
    }
 
}

2.2 测试统一异常处理

        可以看到现在出现异常之后返回的格式已经是我们所需要的格式了,如果我们想让这个错误信息更加明确,我们可以通过添加自定义异常来实现。

2.3 添加自定义异常类

新建exception包,在该包下添加自定义异常类

/**
 * 测试自定义异常类
 * 需要继承运行时异常RuntimeException
 */
public class TestException extends RuntimeException {
    private Integer code;
 
    public TestException(ResultCodeEnum resultCodeEnum) {
        // 调用父类的方法添加信息
        super(resultCodeEnum.getMessage());
        this.code = resultCodeEnum.getCode();
    }
 
    public Integer getCode() {
        return code;
    }
}

 2.4 在统一异常处理类GlobalExceptionHandler中添加一个自定义异常的处理

/**
 * 统一异常处理
 * ControllerAdvice注解的含义是当异常抛到controller层时会拦截下来
 */
@ControllerAdvice
public class GlobalExceptionHandler {
 
    /**
     * 使用ExceptionHandler注解声明处理Exception异常
     *
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public R exception(Exception e) {
        // 控制台打印异常
        e.printStackTrace();
        // 返回错误格式信息
        return R.error();
    }
 
    /**
     * 使用ExceptionHandler注解声明处理TestException异常
     *
     */
    @ResponseBody
    @ExceptionHandler(TestException.class)
    public R exception(TestException e) {
        // 控制台打印异常
        e.printStackTrace();
        // 返回错误格式信息
        return R.error().message(e.getMessage()).code(e.getCode());
    }
 
}

 2.5 测试自定义异常

在枚举类中添加一个状态信息

TEST_NUMBER(false, 500, "计算错误");
/**
 * 测试控制器
 *
 */
@RestController
@RequestMapping("testR")
public class TestController {
 
    @GetMapping("ok")
    public R testOk() {
    try{

        int a = 1/0;
    }catch{
        throw new TestException(ResultCodeEnum.TEST_NUMBER);    
    }
        Map<String, Object> data = new HashMap<>();
        data.put("name", "李太白");
        return R.ok().data(data);
    }
}

3. 统一日志处理 

为了更方便我们进行错误的调式,一般会在项目中集成日志。

3.1 添加日志配置文件

在resources下添加日志的配置,文件名必须是logback-spring.xml

以下配置一般不需要修改,要改的话也只是修改日志的输出目录

<property name="log.path" value="D:/javaWeb/log" />

value就是日志的输出位置

<?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="D:/javaWeb/log" />
 
    <!--控制台日志格式:彩色日志-->
    <!-- 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)"/>
 
    <!--文件日志格式-->
    <property name="FILE_LOG_PATTERN"
              value="%date{yyyy-MM-dd HH:mm:ss} |%-5level |%thread |%file:%line |%logger |%msg%n" />
 
    <!--编码-->
    <property name="ENCODING"
              value="UTF-8" />
 
    <!--输出到控制台-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <!--日志级别-->
            <level>DEBUG</level>
        </filter>
        <encoder>
            <!--日志格式-->
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!--日志字符集-->
            <charset>${ENCODING}</charset>
        </encoder>
    </appender>
 
    <!--输出到文件-->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--日志过滤器:此日志文件只记录INFO级别的-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_info.log</file>
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
            <charset>${ENCODING}</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>500MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
    </appender>
 
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 日志过滤器:此日志文件只记录WARN级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_warn.log</file>
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
            <charset>${ENCODING}</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>
    </appender>
 
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 日志过滤器:此日志文件只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_error.log</file>
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
            <charset>${ENCODING}</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>
    </appender>
 
    <!--开发环境-->
    <springProfile name="dev">
        <!--可以灵活设置此处,从而控制日志的输出-->
        <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="ERROR">
            <appender-ref ref="ERROR_FILE" />
        </root>
    </springProfile>
 
</configuration>

3.2 添加application.properties配置

配置文件需要设置下环境,需要跟日志配置文件中的<springProfile name="dev">对应上,不然不生效

# 设置环境
spring.profiles.active=dev

3.3 修改GlobalExceptionHandler类

/**
 * 统一异常处理
 * ControllerAdvice注解的含义是当异常抛到controller层时会拦截下来
 */
@ControllerAdvice
public class GlobalExceptionHandler {
 
    /**
     * 打印日志 
     * 如果项目有集成lombok可使用@Slf4j注解代替
     */
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
 
    /**
     * 使用ExceptionHandler注解声明处理Exception异常
     *
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public R exception(Exception e) {
        // 控制台打印异常
        log.error(e.getMessage());
        // 返回错误格式信息
        return R.error();
    }
 
    /**
     * 使用ExceptionHandler注解声明处理TestException异常
     *
     */
    @ResponseBody
    @ExceptionHandler(TestException.class)
    public R exception(TestException e) {
        // 控制台打印异常
        log.error(e.getMessage());
        // 返回错误格式信息
        return R.error().message(e.getMessage()).code(e.getCode());
    }
 
}

3.4 测试效果

日志生效了,而且在我们的D盘javaWeb目录下也有对应的日志文件了

 我们可以进一步的完善下,将日志堆栈信息输出到文件

3.5 定义工具类

 新建utils包,在该包下添加ExceptionUtils类

/**
 * 日志堆栈信息输出到文件工具类
 *
 */
public class ExceptionUtils {
    public static String getMessage(Exception e) {
        StringWriter sw = null;
        PrintWriter pw = null;
        try {
            sw = new StringWriter();
            pw = new PrintWriter(sw);
            // 将出错的栈信息输出到printWriter中
            e.printStackTrace(pw);
            pw.flush();
            sw.flush();
        } finally {
            if (sw != null) {
                try {
                    sw.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (pw != null) {
                pw.close();
            }
        }
        return sw.toString();
    }
}

3.6 再修改GlobalExceptionHandler类

/**
 * 统一异常处理
 * ControllerAdvice注解的含义是当异常抛到controller层时会拦截下来
 */
@ControllerAdvice
public class GlobalExceptionHandler {
 
    /**
     * 打印日志 如果项目有集成lombok可使用@Slf4j注解代替
     */
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
 
    /**
     * 使用ExceptionHandler注解声明处理Exception异常
     *
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public R exception(Exception e) {
        // 控制台打印异常  借助工具类将错误堆栈输出到文件
        log.error(ExceptionUtils.getMessage(e));
        // 返回错误格式信息
        return R.error();
    }
 
    /**
     * 使用ExceptionHandler注解声明处理TestException异常
     *
     */
    @ResponseBody
    @ExceptionHandler(TestException.class)
    public R exception(TestException e) {
        // 控制台打印异常   借助工具类将错误堆栈输出到文件
        log.error(ExceptionUtils.getMessage(e));
        // 返回错误格式信息
        return R.error().message(e.getMessage()).code(e.getCode());
    }
 
}

以上是根据一位博主的文章编写的,现在找不到那篇文章了,还请见谅。

这篇文章就到这里了,下次见!

🥇原创不易,还希望各位大佬支持一下!

👍点赞,你的认可是我创作的动力 !

🌟收藏,你的青睐是我努力的方向!

✏️评论,你的意见是我进步的财富!

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

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

相关文章

【小沐学GIS】基于C++绘制三维太阳系SolarSystem(OpenGL、glfw、glut)

&#x1f37a;三维数字地球系列相关文章如下&#x1f37a;&#xff1a;1【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;OpenGL、glfw、glut&#xff09;第一期2【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;OpenGL、glfw、glut&#xff09;第二期3【小沐学GIS】…

深度学习基础之数据操作

深度学习中最常用的数据是张量&#xff0c;对张量进行操作是进行深度学习的基础。以下是对张量进行的一些操作&#xff1a; 首先我们需要先导入相关的张量库torch。 元素构造&#xff08;初始化&#xff09; 使用arange创造一个行向量&#xff0c;也就是0轴&#xff08;0维&a…

LabVIEW 2023下载安装教程,附安装包和工具,免费使用,无套路获取

前言 LabVIEW是一种程序开发环境&#xff0c;提供一种图形化编程方法&#xff0c;可可视化应用程序的各个方面&#xff0c;包括硬件配置、测量数据和调试&#xff0c;同时可以通过FPGA数学和分析选板中的NI浮点库链接访问浮点运算功能库&#xff0c;LabVIEW软件是NI设计平台的…

西圣H1头戴式耳机发布,不止音质惊艳,更有舒适听音体验

近日&#xff0c;深耕智能声学领域多年的 xisem西圣品牌‏‏发布——‏西圣H1头戴式主动降噪蓝牙耳机正式迎来首销。从各个方面来看&#xff0c;这款头戴式耳机展现出了极具颠覆性的创新&#xff0c;不仅在音质和降噪性能上表现出色&#xff0c;更重要的是采用了更加轻巧的佩戴…

使用记事本修复DBC文件问题V3.0

要麻了&#xff0c;竟然写到3.0了。 有个信号解析不出来&#xff0c;同一条报文的其他信号可以正确解析&#xff0c;打开DBC检查&#xff0c;位置长度都是正确的&#xff0c;死活解析不出来。 打开记事本 发现他居然在信号后面加了个回车&#xff0c;就产生了上面这种诡异的情…

js实现九九乘法表

效果图 代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body><script type"text/javascript">// 输出乘法口诀表// document.write () 空格 " " 换行…

微电网优化MATLAB:火鹰优化算法(Fire Hawk Optimizer,FHO)求解微电网优化(提供MATLAB代码)

一、火鹰优化算法FHO 火鹰优化算法&#xff08;Fire Hawk Optimizer&#xff0c;FHO&#xff09;由Mahdi Azizi等人于2022年提出&#xff0c;该算法性能高效&#xff0c;思路新颖。 单目标优化&#xff1a;火鹰优化算法&#xff08;Fire Hawk Optimizer&#xff0c;FHO&#…

QKCP容器平台安装qkcp paas deployment

22年底23年初做的容器云平台的项目&#xff0c;该份是当初实施部署真实生产环境的手册&#xff0c;关键ip和端口已经更改&#xff0c;现贴来给大伙参阅。 x公司qkcp容器平台安装部署手册 目录 x公司qkcp容器平台安装部署手册 1 集群基础环境 3 1.1. 集群规划信息 3 1.2. 标准…

Eclipses安装教程

一、下载开发工具包 1、开发工具包JDK 下载地址链接&#xff1a;https://www.oracle.com/cn/java/technologies/downloads/ 下载教程&#xff1a; 1&#xff09;点击链接&#xff0c;可以跳转到页面 2&#xff09;下滑页面&#xff0c;找到开发工具包 3&#xff09; 记住下载之…

数据库管理Navicat Premium 15

Navicat Premium 15是一款强大的数据库管理和开发工具&#xff0c;支持多种数据库类型&#xff0c;包括MySQL、MariaDB、SQL Server、SQLite、Oracle和PostgreSQL等。它提供了数据可视化、高效的操作、数据同步与备份等功能&#xff0c;以及用户友好的界面。Navicat Premium 15…

【数据库原理】(37)Web与数据库

随着网络的高速发展和网络服务的日趋完善&#xff0c;网络上的信息量呈几何级数增长。为了有效地组织、存储、管理和使用网上的信息&#xff0c;数据库技术被广泛地应用于网络领域。特别是在Internet上&#xff0c;已建立了数以万计的网站&#xff0c;其中大中型网站的后台大多…

2.4 网络层01

2.4 网络层01 2.4.1 网络层概述 网络层的主要任务是实现网络互连&#xff0c;进而实现数据包在各网络之间的传输。 异构网络内部的计算机要想实现通信是不需要实现网络互联的&#xff0c;异构网络之间要想实现通信就必须实现网络互连。 路由器工作在五层协议体系结构的网络…

Android:JNI实战,加载三方库、编译C/C++

一.概述 Android Jni机制让开发者可以在Java端调用到C/C&#xff0c;也是Android应用开发需要掌握的一项重要的基础技能。 计划分两篇博文讲述Jni实战开发。 本篇主要从项目架构上剖析一个Android App如何通过Jni机制加载三方库和C/C文件。 二.Native C Android Studio可…

python一元线性回归sklearn

# -*- coding: utf-8 -*-from sklearn.linear_model import LinearRegression import numpy as np import matplotlib.pyplot as plt# 载入数据 data np.genfromtxt(一元线性回归.csv, delimiter,) x_data data[:,0] y_data data[:,1] plt.scatter(x_data,y_data) plt.show(…

如何本地安装Python Flask并结合内网穿透实现远程开发

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

03--数据库连接池

1、数据库连接池 1.1 JDBC数据库连接池的必要性 在使用开发基于数据库的web程序时&#xff0c;传统的模式基本是按以下步骤&#xff1a; 在主程序&#xff08;如servlet、beans&#xff09;中建立数据库连接进行sql操作断开数据库连接 这种模式开发&#xff0c;存在的问题:…

外贸自建站如何建立?海洋建站的操作指南?

外贸自建站的建站流程什么&#xff1f;做跨境怎么搭建外贸网站&#xff1f; 外贸自建站成为企业开拓国际市场、提升品牌形象的重要途径。然而&#xff0c;对于许多企业而言&#xff0c;如何高效地进行外贸自建站仍然是一个挑战。海洋建站将带您一步步探讨外贸自建站的关键步骤…

Ubuntu重设root的密码

重设root的密码 未重设密码之前&#xff0c;Ubuntu 中默认的 root 密码是随机的&#xff0c;即每次开机都会有一个新的root 密码&#xff0c;所以此时的 root 用户密码并不确定&#xff1b; 重设root 密码&#xff0c;使用安装时创建的用户登录后sudo su切换至root用户&#…

JAVASE进阶(设计模式、设计原则)(更新中...)

目录 一、注解 内置注解&#xff1a;JAVA中已经定义好的注解。 元注解&#xff1a;修饰注解的注解。 自定义注解。 二、克隆 JAVA中对clone的实现&#xff1f; 浅克隆 深克隆 那么该如何做到深克隆呢&#xff1f; 三、常用设计模式 1、创建型模式 单例模式 工厂模式 工…

【数据结构与算法】之字符串系列-20240122

这里写目录标题 一、383. 赎金信二、387. 字符串中的第一个唯一字符三、389. 找不同四、392. 判断子序列五、409. 最长回文串 一、383. 赎金信 简单 给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 magazine 里面的字符构成。 如果…