1.全局异常
全局异常功能是为了防止404页面不美观,外行人也有可能看不懂,因此我们需要返回一个大部分人都能接受的页面来替换。
1.首先床架哪一个MyException类继承RuntimeException类
package cn.sc.exception;
public class MyException extends RuntimeException{
private Integer code;
private String msg;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public MyException(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
}
2.创建一个MyExceptioConfig类
package cn.sc.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
@ControllerAdvice
public class MyExceptionConfig {
//处理异常的两种方法
//1.返回一个对象
@ExceptionHandler(Exception.class)
@ResponseBody
public Object handlerExceptionMessage(Exception e){
if(e instanceof MyException){
MyException myException = (MyException) e;
return "这是一个自定义的异常";
}else{
return "其他异常";
}
}
//可以跳转页面
@ExceptionHandler(Exception.class)
public Object handlerExceptionMessage(Exception e, HttpServletRequest request){
String addr = request.getRequestURL().toString();
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("error.html");
return modelAndView;
}
}
3.创建一个error.html页面(创建路径如图)
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
我是错误信息页
<tr>
<th th:text="#{msg}">Name</th>
</tr>
</body>
</html>
4.然后在UserController中写一个异常(1/0,0不能为除数,所以肯定异常)
package cn.sc.Controller;
import cn.sc.anync.AnyncDemo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@RestController
public class UserController {
@Resource
private AnyncDemo anyncDemo;
@RequestMapping("exe")
public String Exception(){
System.out.println(1/0);
return null;
}
}
}
5.运行结果为(这里出现了乱码,后期我们会在项目中解决)
2.拦截器
拦截器用来拦截方法,例如当你查看购物车时,你必须先登录才能查看,这时候用拦截器来拦截查看购物车就显得格外重要。
1.首先创建一个LoginInterceptor类让它实现 HandlerInterceptor接口
package cn.sc.interceptor;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class LoginInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("服务器正在拦截");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
//只有在preHandle返回为true时 才会使用
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
2然后创建一个LoginInterceptorConfig类实现WebMvcConfigurer接口,添加并注册拦截器
package cn.sc.interceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
@Configuration
//如果当前配作为配置类
public class LoginInterceptorConfig implements WebMvcConfigurer{
@Bean
//将当前方法的返回值作为一个bean对象
LoginInterceptor getLoginInterceptor(){
return new LoginInterceptor();
}
//添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getLoginInterceptor())
.addPathPatterns("/test1")
.excludePathPatterns("/exe");
WebMvcConfigurer.super.addInterceptors(registry);//注册拦截器
}
}
3在UserController中创建方法
package cn.sc.Controller;
import cn.sc.anync.AnyncDemo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@RestController
public class UserController {
@Resource
private AnyncDemo anyncDemo;
@RequestMapping("test1")
public String test1(){
return "测试1";
}
@RequestMapping("test2")
public String test2(){
return "测试2";
}
@RequestMapping("exe")
public String Exception(){
System.out.println(1/0);
return null;
}
}
4运行结果
1当访问test1时则会拦截
2挡访问exe时则会放行
3.定时器
定时器功能在平常都能遇到,例如 淘宝、京东获取分钟交易额,定时维护代码等。
1首先创建一个类为TaskDemo
package cn.sc.task;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
/*
* 定时器类 cron="* * * * * * *"
* 秒 分钟 小时 天 月 当前周的某一天
*/
@Component
public class TaskDemo {
//任务调度
@Scheduled(cron = "*/5 * * * * *")
public void task1(){
//定时两秒执行当前交易额
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
System.out.println(sdf.format(new Date())+"交易量:"+Math.random()*10000+"元");
}
}
2.在启动类中开启定时器
3.执行结果为
4.同步和异步任务
在很多功能中,我们都会使用到异步,springboot的异步原理和ajax的异步相似,下面我们来了解同步和异步的区别
1.先创建一个类为AnyncDemo
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import java.util.concurrent.Future;
@Component
//开启异步
@Async
public class AnyncDemo {
public void task1(){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务1完成");
}
public void task2(){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务2完成");
}
//异步任务有返回值
public Future<Boolean> task4(){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务4完成");
return new AsyncResult<>(true);
}
}
2.在启动类里开启异步
3编写一个启动类UserController
package cn.sc.Controller;
import cn.sc.anync.AnyncDemo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@RestController
public class UserController {
@Resource
private AnyncDemo anyncDemo;
//调用同步方法
@RequestMapping("task1")
public String task1() throws ExecutionException, InterruptedException {
//拿到当前的毫秒值
long start = System.currentTimeMillis();
anyncDemo.task1();
anyncDemo.task2();
Future<Boolean> booleanFuture = anyncDemo.task4();
Boolean boolean1 = booleanFuture.get();
System.out.println(boolean1);
long end = System.currentTimeMillis();
return "执行时间:"+(end-start)+"毫秒";
}
}
4运行结果为
5当关闭异步时,则花费的时间更长,假设有无数项目,每个项目都会有一定的开启时间,若未开启异步这回影响到用户的体验