谷粒学院项目笔记3——统一异常处理、统一日志处理、前端技术

本文介绍了一种统一处理异常和日志的方法,包括全局异常处理、特定异常处理和自定义异常处理,并详细讲解了如何使用Logback进行日志管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

谷粒学院项目第三天

今日任务:

统一异常处理:全局异常处理、特定异常处理、自定义异常处理

统一日志处理: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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值