谷粒学院项目第三天
今日任务:
统一异常处理:全局异常处理、特定异常处理、自定义异常处理
统一日志处理:Logback
前端知识:安装vscode
统一异常处理
全局异常处理
创建异常处理类
在异常处理类里添加全局异常的处理方法
@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异常处理……");
}
自定义异常处理
创建自定义异常类
创建com.jiabei.servicebase.exceptionhandler.GuliException类
@AllArgsConstructor
@NoArgsConstructor
@Data
public class GuliException extends RuntimeException{
private Integer code;//状态码
private String message;//异常信息
}
在异常处理类里添加自定义异常的处理方法
@ExceptionHandler(GuliException.class)//指定处理什么类型的异常
@ResponseBody
public R error(GuliException e){
e.printStackTrace();
return R.error().message("执行了GuliException的异常处理……");
}
swagger测试结果
统一日志处理
日志:就是控制台输出的项目执行信息
日志级别
OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL
默认是INFO,后面的包含前面的:INFO包含WARN、ERROR、FATAL、OFF
设置日志级别
在application.properties中添加
#设置日志级别
logging.level.root=WARN
Logback日志工具
logback可以把日志输出在控制台的同时,也输出到文件中
删除application.properties里的日志配置
#删除以下内容
#设置日志级别
logging.level.root=WARN
#mysql日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
在service_edu模块中的resource目录下创建logback-spring.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:每10s看一下配置文件是否被修改了,默认单位是ms。scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<contextName>logback</contextName>
<!-- name:变量名,value:变量值。通过“${}”使用变量。 -->
<property name="log.path" value="D:/log/guli_log/edu" />
<!-- 彩色日志 -->
<!-- 配置格式变量:CONSOLE_LOG_PATTERN 彩色日志格式 -->
<!-- magenta:洋红 boldMagenta:粗红 cyan:青色 white:白色 -->
<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>
<!--输出到文件-->
<!-- 时间滚动输出 日志级别为 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.guli" 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>
修改日志文件输出路径为自己的目录:
<property name="log.path" value="D:/log/guli_log/edu" />
启动项目
此时,日志文件将被创建在相应目录
我们发现只有info有内容,错误信息和警告信息没有输出
在异常处理类上加上@Slf4j注解
在异常处理方法上写上
这时,e.getMessage()将被写入error.log
前端
前端:通过ajax调用后端接口,得到数据,将数据显示出来
VSCode的下载和插件的安装:手把手教你VSCode的下载和插件安装
搭建项目
在本地创建一个空文件夹(vs1010)
用vscode打开vs1010
将文件夹保存为工作区
vscode中打开项目就是双击.code-workspaces文件
创建目录和html文件,进行测试
原先是将html页面放到Tomcat上,通过ip和端口号进行访问
现在,我们可以利用插件Live Server,通过ip和端口号进行访问,无需部署到tomcat上
es6
ECMAScript是浏览器脚本语言的一套标准,JavaScript是这个标准的一种实现
es5:ECMAScript5
es6:ECMAScript6
es5对比es6:es5浏览器兼容性更好,es6代码更简洁
变量特点
创建文件夹es6demo,创建文件01.html
<script>
{
var a=10 //js方式定义变量
let b=10 //es6方式定义变量
}
console.log(a) //10
console.log(b) //b is not defined 说明es6方式定义变量有局部作用域
</script>
js方式和es6方式在变量上的区别:
1、js变量的作用范围是全局,es6是局部
2、js变量能重复声明,es6只能声明一次
数组解构
<script>
let a=10,b=20,c=30
console.log(a,b,c)
let [x,y,z]=[10,20,30] //数组解构:x=10,y=20,z=30
console.log(x,y,z)
</script>
对象解构
<script>
let user={"name":"lucy","age":20}
let name1=user.name //传统赋值
let age1=user.age
let {name,age}=user //对象解构:name=user.name age=user.age
</script>
模板字符串
<script>
//``实现换行、空格的输出
let str1=`hello,
vscode`
console.log(str1)
//``里能通过${}获取变量值
let name="Mike"
let age=20
let str2=`name=${name},age=${age+1}`
console.log(str2) //name=Mike,age=21
//``里能通过${}调用方法
function f1(){
return "hello f1"
}
let str3=`${f1()}`
console.log(str3) //hello f1
</script>
声明对象
<script>
const name="lucy" //const是定义常量的关键字
const age=20
const p1={name:name,age:age} //name=${name},age=${age}
console.log(p1)
const p2={name,age} //name=${name},age=${age}
console.log(p2)
</script>
方法简写
<script>
//js方式
const p1={
sayHi:function(){
console.log("Hi")
}
}
p1.sayHi()
//es6方式
const p2={
sayHi(){
console.log("Hi")
}
}
p2.sayHi()
</script>
对象扩展运算符
对象拓展运算符:...
用于将一个对象赋值给另一个对象
<script>
//复制对象
let p1={name:"lucy",age:20}
let p2={name:p1.name,age:p1.age} //传统方式
let p3={...p1} //对象拓展运算符
//合并对象
let p4={name:"lucy"}
let p5={age:20}
let p6={...p4,...p5} //将p4 p5合并为p6
console.log(p6)
</script>
箭头函数
箭头函数:=>
用来简化方法
<script>
//传统方式创建方法
let f1=function(m){
return m
}
//箭头函数创建方法
let f2=m=>m //参数=>返回值
let f3=(a,b)=>a+b
console.log (f1(1)) //1
console.log (f2(2)) //2
console.log (f3(1,2)) //3
</script>
Vue
vue是用于构建用户界面的渐进式框架
入门案例
创建文件夹vuedemo,在里面创建测试文件
!+ enter:快速生成 html 框架
和JQuery一样,使用之前先引入vue的js文件
在本地将vue.min.js复制到项目中
在项目中引入vue.min.js
vue代码的固定结构
测试
运行结果
抽取代码片段
就是设置一个快捷方式能快速生成vue骨架
替换为以下内容
{
"vue html": {
"scope": "html",
"prefix": "vuehtml",
"body": [
"<!DOCTYPE html>",
"<html lang=\"en\">",
"",
"<head>",
" <meta charset=\"UTF-8\">",
" <meta name=\"viewport\" content=\"width=device-width, initialscale=1.0\">",
" <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">",
" <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>",
],
"description": "my vue template in html"
}
}
保存
以后,就能vue+enter快速生成骨架啦
vue指令
vue中的指令都是以 v- 开头
v-bind变量单向绑定
<body>
<div id="app">
<!-- v-bind:单向绑定 -->
<h1 v-bind:title="message">
{{content}}
</h1>
<!-- 简写方式 -->
<h1 :title="message">
{{content}}
</h1>
</div>
<script src="vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
content:'我是内容',
message:'页面加载于'+new Date().toLocaleString()
}
})
</script>
</body>
v-model变量双向绑定
单向绑定时,value值不会改变变量值
双向绑定时,value值会改变变量值
<body>
<div id="app">
<input type="text" v-bind:value="message"></input>
<input type="text" v-model:value="message"></input>
<h1>{{message}}</h1>
</div>
<script src="vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
message:"good morning"
}
})
</script>
</body>
v-on事件绑定
<body>
<div id="app">
<button v-on:click="greet()">打招呼</button>
<!--简写-->
<button @click="greet()">打招呼</button>
</div>
<script src="vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
},
methods:{
greet(){
console.log("good morning")
}
}
})
</script>
</body>
修饰符
修饰符:阻止默认行为的发生
<body>
<div id="app">
<form action="save" v-on:submit.prevent="f1()">
<input type="text" id="name" v-model:value="user.name"></input>
<button type="submit">保存</button>
</form>
</div>
<script src="vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
user:{}
},
methods:{
f1(){
if(this.user.name){
console.log("提交成功")
}else{
console.log("请输入用户名")
}
}
}
})
</script>
</body>
v-if条件判断
<body>
<div id="app">
<form action="save" v-on:submit.prevent="f1()">
<input type="text" id="name" v-model:value="user.name"></input>
<button type="submit">保存</button>
</form>
</div>
<script src="vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
user:{}
},
methods:{
f1(){
if(this.user.name){
console.log("提交成功")
}else{
console.log("请输入用户名")
}
}
}
})
</script>
</body>
v-for循环
<body>
<div id="app">
<p v-for="n in 10">{{n}}</p>
<p v-for="(n,index) in 10">{{n}}——{{index}}</p>
<hr/>
<table>
<tr v-for="user in users">
<td>{{user.name}}</td>
<td>{{user.age}}</td>
</tr>
</table>
</div>
<script src="vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
users:[
{name:"lucy",age:20},
{name:"lily",age:22},
{name:"mike",age:23}
]
}
})
</script>
</body>
组件
组件:将代码抽取成模板,提高代码的复用性
局部组件:只能在当前页面使用
<body>
<div id="app">
<Navbar></Navbar> <!--组件可以扩展html标签-->
</div>
<script src="vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
},
//组件
components:{
'Navbar':{
template:'<ul><li>spring</li><li>summer</li></ul>'
}
}
})
</script>
</body>
全局组件
创建一个文件夹,用来放组件的js文件
编写组件
调用组件
<body>
<div id="app">
<Navbar></Navbar> <!--调用组件-->
</div>
<script src="vue.min.js"></script>
<script src="components/Navbar.js"></script> <!--先引入组件-->
<script>
new Vue({
el: '#app',
data: {
}
})
</script>
</body>
vue对象的生命周期
<body>
<div id="app">
<h1>hello</h1>
</div>
<script src="vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
},
created(){
debugger
console.log("created()在页面渲染之前执行")
},
mounted(){
debugger
console.log("mounted()在页面渲染之后执行")
},
})
</script>
</body>
vue路由
路由就是将选项和页面绑定在一起,点击不同的选项会跳转到不同的页面
将vue-router.min.js拷贝到项目所在目录
使用之前需要先引入
<script src="vue.min.js"></script>
<script src="vue-router.min.js"></script>