> 文章列表 > 谷粒学院开发(三):统一日志、异常及前端准备工作

谷粒学院开发(三):统一日志、异常及前端准备工作

谷粒学院开发(三):统一日志、异常及前端准备工作

特定异常处理

@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)  // 指定出现什么异常会被处理@ResponseBody  // 为了能够返回数据public R error(Exception e) {e.printStackTrace();return R.error().message("执行了全局异常处理");}// 特定异常处理@ExceptionHandler(ArithmeticException.class)  // 指定出现什么异常会被处理@ResponseBody  // 为了能够返回数据public R error(ArithmeticException e) {e.printStackTrace();return R.error().message("执行了ArithmeticException异常处理");}
}

自定义异常处理

  1. 创建自定义异常类继承RuntimeException,写异常属性

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class GuliException extends RuntimeException{@ApiModelProperty("异常状态码")private Integer code;@ApiModelProperty("异常信息")private String msg;
    }
    
  2. 添加异常处理方法

    @ExceptionHandler(GuliException.class)  // 指定出现什么异常会被处理
    @ResponseBody  // 为了能够返回数据
    public R error(GuliException e) {e.printStackTrace();return R.error().code(e.getCode()).message(e.getMsg());
    }
    
  3. 在需要抛出异常的地方抛出

    try {int i = 10/0;
    } catch(Exception e) {throw new GuliException(20001, "自定义异常");
    }
    

统一日志处理

日志级别

在springboot配置文件中配置

# 设置日志级别, ERROR, WARN, INFO, DEBUG, ALL, 越靠后显示内容越多
logging.level.root=INFO

把日志输出到文件中

使用Logback工具

  1. 把之前在properties文件里面添加的所有日志相关的内容全部删掉

    # 设置日志级别, ERROR, WARN, INFO, DEBUG, ALL, 越靠后显示内容越多
    #logging.level.root=INFO
    # mybatis日志
    #mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
    
  2. 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="D:/guli_1010/edu" /><!-- 彩色日志 --><!-- 配置格式变量: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="com.liuscoding.edu.mapper" level="DEBUG" additivity="false"/><!--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>
    

将异常信息输出到文件中

  1. 在异常处理类加上注解 @Slf4j

    @ControllerAdvice
    @Slf4j
    public class GlobalExceptionHandler {
    
  2. 在具体执行异常处理函数里面输出日志

    @ExceptionHandler(GuliException.class)  // 指定出现什么异常会被处理
    @ResponseBody  // 为了能够返回数据
    public R error(GuliException e) {log.error(e.getMsg());  // 这里是输出日志的e.printStackTrace();return R.error().code(e.getCode()).message(e.getMsg());
    }
    

前端技术

VSCode安装下面的插件

谷粒学院开发(三):统一日志、异常及前端准备工作

创建工作区

前端代码卸载工作区里

  1. 在本地创建空文件夹
  2. 使用vscode大概空文件夹
  3. 选择 文件=>将工作区另存为 把这个工作区保存到刚刚的空文件夹里面

Vue

Vue入门案例

  1. 创建html页面,vscode 中使用 ! 可以快速生成

  2. 引入vue的js文件,类似于jquery

    <script src="vue.min.js"></script>
    
  3. 在html页面创建div标签,添加id属性

    <div id="app"></div>
    
  4. 编写vue代码,固定的结构

    <script>// 创建一个vue对象new Vue({el: '#app',  // 绑定vue作用的范围data: {  // 定义页面中显示的模型数据message: 'Hello Vue!'}})
    </script>
    
  5. 使用插值表达式
    获取data里面定义的值 {{名称}}
    谷粒学院开发(三):统一日志、异常及前端准备工作

抽取代码片段

抽取页面基本结构,方便之后的工程使用

{"vue htm": {"scope": "html","prefix": "vuehtml","body": ["<!DOCTYPE html>","<html lang=\\"en\\">","","<head>","    <meta charset=\\"UTF-8\\">","    <meta http-equiv=\\"X-UA-Compatible\\" content=\\"IE=edge\\">","    <meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1.0\\">","    <title>Document</title>","</head>","","<body>","    <div id=\\"app\\">","","    </div>","    <script src=\\"vue.min.js\\"></script>","    <script>","        new Vue({","            el: '#app',","            data: {","                $1","            }","        })","    </script>","</body>","</html>"]}
}

axios

  1. 不是vue里面的一部分,但是经常和vue一起使用,用来实现ajax操作。

  2. 使用axios应用场景
    谷粒学院开发(三):统一日志、异常及前端准备工作

  3. axios的使用

    • 创建html页面,引入js文件,包含两个js文件:vue和axios

      <script src="vue.min.js"></script>
      <script src="axios.min.js"></script>
      
    • 编写axios代码

      1. 构造json文件,用于后面请求数据
        谷粒学院开发(三):统一日志、异常及前端准备工作

      2. 发送ajax请求文件,得到数据在页面显示

        new Vue({el: '#app',data: {  // 定义变量和初始值userList: []  // 定义变量,空数组},created() {  // 页面渲染之前执行// 调用定义的方法this.getUserList()},methods: {  // 编写具体的方法// 创建方法,查询所有用户数据getUserList() {// 使用axios发送ajax请求// axios.提交方式("请求接口路径").then(箭头函数).catch(箭头函数)axios.get("data.json").then(response => {  // response就是请求后返回的数据console.log('*'+response)})  // 请求成功执行then方法.catch(error => {})  // 请求失败执行catch方法}}
        })
        
new Vue({el: '#app',data: {  // 定义变量和初始值userList: []  // 定义变量,空数组},created() {  // 页面渲染之前执行// 调用定义的方法this.getUserList()},methods: {  // 编写具体的方法// 创建方法,查询所有用户数据getUserList() {// 使用axios发送ajax请求// axios.提交方式("请求接口路径").then(箭头函数).catch(箭头函数)axios.get("data.json").then(response => {  // response就是请求后返回的数据// console.log(response)// console.log(response.data.data.items)this.userList = response.data.data.items})  // 请求成功执行then方法.catch(error => {})  // 请求失败执行catch方法}}
})
<!-- 把userList里的数据进行显示 -->
<table border="1"><tr v-for="(user,index) in userList"><td>{{index}}</td><td>{{user.name}}</td><td>{{user.age}}</td></tr>
</table>

element-ui

饿了么出品的基于Vue.js的后台组件

https://element.eleme.cn/#/zh-CN/

Node.js

  1. 什么是Node.js
    不需要浏览器,直接使用nodejs运行JavaScript代码

  2. 模拟服务器效果,比如tomcat

    const http = require('http');http.createServer(function (request, response) {// 发送HTTP头部// HTTP 状态值200 : OK// 内容类型: text/plainresponse.writeHead(200, {'Content-Type':'text/plain'});response.end('Hello Server');
    }).listen(8888);console.log('Server running at http://127.0.0.1:8888/');
    
  3. 使用nodejs执行JavaScript代码

    console.log("hello nodejs")
    

使用node命令执行js文件即可。

npm

后端中,maven用来构建项目,管理jar依赖,联网下载依赖
相当于前端的maven,管理前端js依赖,联网下载js依赖,比如jquery

演示npm具体操作

  1. npm项目初始化
    使用命令 npm init
    项目初始化之后会生成一个文件 package.json 类似于后端的 pom.xml

  2. npm下载js依赖
    使用命令 npm install 依赖名称
    设置成淘宝的镜像

    # 配置镜像地址
    npm config set registry https://registry.npm.taobao.org# 查看npm配置信息
    npm config list
    

babel

转码器,把es6代码转换成es5代码,提高代码的浏览器兼容性。

安装babel工具

npm install --global babel-cli

创建es6代码

let input = [1, 2, 3]
// 将数组的每个元素 +1
input = input.map(item => item + 1)
console.log(input)

配置.babelrc

是Babel的配置文件,存放在项目的根目录下,用来设置转码规则和插件,基本格式如下

{"presets": ["es2015"],"plugins": []
}

安装es2015转码器

npm install --save-dev babel-preset-es2015

使用命令转码

  • 根据文件转码
babel 源文件路径 -o 目标文件路径
  • 根据文件夹转码
babel 源文件夹 -d 目标文件夹

转换过来的js文件与源文件同名

模块化

是什么

  • 开发后端接口的时候,开发controller service mapper,controller注入service,service注入mapper
    后端中类与类之间的调用称为后端模块化操作
  • 前端模块化,在前端中,js与js之间的调用称为模块化

es5实现模块化

01.js

// 创建方法const sum = function(a,b){return parseInt(a) + parseInt(b)
}
const subtract = function(a,b){return parseInt(a) - parseInt(b)
}// 设置哪些方法可以被其他js调用
module.exports = {sum: sum,subtract: subtract
}

02.js

// 调用01.js方法const m = require('./01.js')const res1 = m.sum(1, 2);
const res2 = m.subtract(2, 1);console.log(res1)
console.log(res2)

es6实现模块化

如果es6的模块化不能在nodejs中运行,则需要使用babel转换成es5之后才能运行

01.js

// 定义方法,设置哪些方法可以被其他js调用export function getList() {console.log('获取数据列表');
}export function save() {console.log('保存')
}// 简化: 可以输出多个函数
// 使用这个之后,上面的函数无法输出
export default {test() {console.log('test')},test2() {console.log('test2')},getList() {console.log('获取数据列表');},save() {console.log('保存')}
}

02.js

// 引入01.js,调用01.js的方法import { getList, save } from "./01.js";getList()
save()

02.js写法2

import m from './01.js'm.test();
m.getList();

webpack

前端资源加载/打包工具。可以根据依赖关系将多种js、css、less文件转换成一个静态文件,减少页面请求。

谷粒学院开发(三):统一日志、异常及前端准备工作

  1. 安装webpack工具

    npm install -g webpack webpack-cli
    
  2. 初始化项目

    npm init -y
    
  3. 新建一个文件夹,创建三个js文件

    // common.js
    exports.info = function (str) {document.write(str)  // 浏览器中输出
    }
    
    // utils.js
    exports.add = function (a, b) {return a + b
    }
    
    // main.js
    const common = require('./common.js')
    const utils = require('./utils.js')common.info('hello common' + utils.add(1, 2))
    
  4. 创建webpack配置文件,配置打包信息
    谷粒学院开发(三):统一日志、异常及前端准备工作

    const path = require("path"); //Node.js内置模块 
    module.exports = {entry: './src/main.js', //配置入口文件 output: {path: path.resolve(__dirname, './dist'), //输出路径,__dirname:当前文件所在路 filename: 'bundle.js' //输出文件}
    }
    
  5. 使用命令执行打包工作

    webpack  # 有黄色警告
    webpack --mode=development  # 没有警告, 可以设置production或development
    

打包css

  1. 创建css文件,写样式内容

    body {background-color: red;
    }
    
  2. 在main.js中引入css文件

    // 引入css文件
    require('./style.css')
    
  3. 安装style-loader 和 css-loader
    webpack本身只能处理JavaScript模块,如果要处理其他类型的文件,就需要使用loader进行转换

    npm install --save-dev style-loader css-loader
    
  4. 修改webpack.config.js

    const path = require("path"); //Node.js内置模块 
    module.exports = {entry: './src/main.js', //配置入口文件 output: {path: path.resolve(__dirname, './dist'), //输出路径,__dirname:当前文件所在路 filename: 'bundle.js' //输出文件},module: {rules: [{test: /\\.css$/,  // 打包规则应用到.css结尾的文件上use: ['style-loader','css-loader']}]}
    }
    

搭建项目前端页面环境

选取一个模版(框架)进行环境搭建,这里选取vue-admin-template

  1. 解压压缩文件到工作区
  2. 通过vscode终端打开解压的文件夹,进行依赖安装
    通过配置文件加载依赖,使用命令npm install ,报错的话可以加上 --legacy-peer-deps 参数
  3. 启动下载好的项目
    命令 npm run dev

前端页面环境说明

  1. 前端框架入口
    谷粒学院开发(三):统一日志、异常及前端准备工作

  2. 前端页面环境使用框架(模版),主要基于两种技术实现出来
    vue-admin-template模版 = vue + element-ui

  3. build目录
    放项目构件的脚本文件

  4. config目录
    index.js中把useEslint: true,值改为false
    接口的地址在另外两个js文件中修改,这两个文件分别对应 npm run devnpm run prod
    谷粒学院开发(三):统一日志、异常及前端准备工作

  5. src目录
    谷粒学院开发(三):统一日志、异常及前端准备工作