springboot(3)——整合freemarker模板、AOP统一处理、全局异常处理

版权声明:本文出自mqy1023的博客,转载必须注明出处。 https://blog.csdn.net/mqy1023/article/details/79633325

《三》、整合freemarker模板、AOP统一处理、全局异常处理

一、整合freemarker模板引擎

  • 1、引入freemarker依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
  • 2、常用配置
############################################################
#
# freemarker 静态资源配置
#
############################################################
# 设定ftl文件路径
spring.freemarker.template-loader-path=classpath:/templates
# 关闭缓存, 即时刷新, 上线生产环境时需要修改了true
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.check-template-location=true
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=true
spring.freemarker.expose-session-attributes=true
spring.freemarker.request-context-attribute=request
spring.freemarker.suffix=.ftl
  • 3、templates目录下新建xxx.ftl后缀的模板html文件

  • 4、注解@Controller打开模板网页

@RequestMapping("/ftl")
public String showFtl(ModelMap map) {
    return "xxx"; // 对应templates目录下的xxx.ftl模板
}

二、AOP统一处理

AOP指面向切面编程, 比如在很多个请求中加某一点"面"中验证是否登录的切入口(PointCut)
  • 1、引入aop依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
  • 2、新建一个类HttpAspect.java切面类
@Aspect // 切面注解
@Component
public class HttpAspect {
    // 拦截TestController控制器的aspectTest方法
    @Before("execution(public * com.xxx.yyy.controller.TestController.aspectTest(..))")
    public void logBefore() {
        // 每次访问“..../aspect”请求前会打印如下
        System.out.println("logBefore");
    }
    // 拦截TestController控制器中所有方法
    // @Before("execution(public * com.xxx.yyy.controller.TestController.*(..))")
    @After("execution(public * com.xxx.yyy.controller.TestController.aspectTest(..))")
    public void logAfter() {
        // 每次访问“..../aspect”请求后会打印如下
        System.out.println("logAfter");
    }


    // 上面的@Before和@After重复, 可以抽出公用的PointCut切面
    // 上面的代码可替换为如下
    @Pointcut("execution(public * com.xxx.yyy.TestController.aspectTest(..))")
    public void log() {
    }
    @Before("log()")
    public void logBefore() {
        System.out.println("logBefore");
    }
    @After("log()")
    public void logAfter() {
        System.out.println("logAfter");
    }
}
  • 3、TestController控制器中
@GetMapping("/aspect")
@ResponseBody
public String aspectTest() {
    return "aspect test";
}
  • 4、获取http请求头的内容
@Before("log()")
public void doBefore(JoinPoint joinPoint) { //JoinPoint提供对连接点上可用状态和静态信息的反射访问
    ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    //url
    logger.info("url={}",request.getRequestURL());
    //method
    logger.info("method={}",request.getMethod());
    //ip
    logger.info("ip={}",request.getRemoteAddr());
    //类方法
    logger.info("clsss_method={}",joinPoint.getSignature().getDeclaringTypeName()+"."+joinPoint.getSignature().getName());
    //参数
    logger.info("args={}",joinPoint.getArgs());
}
  • 5、AOP中获取方法返回Response内容
@AfterReturning(returning = "obj", pointcut="log()")
public void doAfterReturn(Object obj){
    logger.info("response={}", obj.toString())
}

三、全局异常处理

  • 1、枚举用于统一管理异常的code和message
@Getter
public enum ResultEnum {
    LOGIN_FAIL(-1, "登录失败, 登录信息不正确"),
    LOGOUT_SUCCESS(-2, "登出成功"),
    ;
    private Integer code;
    private String message;

    ResultEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}
  • 2、定义自己的继承RuntimeException的异常类
@Getter
public class B2CException extends RuntimeException {
    private Integer code;
    public B2CException(ResultEnum resultEnum) {
        super(resultEnum.getMessage());
        this.code = resultEnum.getCode();
    }
    public B2CException(Integer code, String message) {
        super(message);
        this.code = code;
    }
}
  • 3、两种请求的捕获异常类:
    • 页面跳转形式
@ControllerAdvice
public class B2CExceptionHandler {
    public static final String IMOOC_ERROR_VIEW = "error";
    // 全局捕获Exception.class异常, 跳转到error.ftl模板
    @ExceptionHandler(value = Exception.class)
    public Object errorHandler(HttpServletRequest reqest,
                               HttpServletResponse response, Exception e) throws Exception {
        e.printStackTrace(); // 打印错误
        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", e);
        mav.addObject("url", reqest.getRequestURL());
        mav.setViewName(IMOOC_ERROR_VIEW);
        return mav;
    }
}
  • ajax形式(捕获自定义B2CException异常)

// 全局捕获B2CExceptionn.class自定义的异常, json数据返回时
@ExceptionHandler(value = B2CException.class)
@ResponseBody
public ResultVO handlerB2CException(B2CException e) {
    return ResultVOUtil.error(e.getCode(), e.getMessage());
}
  • 统一返回异常的形式

    根据请求头判断是否是ajax请求来返回页面还是json数据

    @ControllerAdvice
    public class B2CExceptionHandler {
        public static final String IMOOC_ERROR_VIEW = "error";
    
        @ExceptionHandler(value = Exception.class)
        public Object errorHandler(HttpServletRequest reqest,
                                   HttpServletResponse response, Exception e) throws Exception {
            e.printStackTrace();
            if (isAjax(reqest)) {
                return ResultVOUtil.error(555, e.getMessage());
            } else {
                ModelAndView mav = new ModelAndView();
                mav.addObject("exception", e);
                mav.addObject("url", reqest.getRequestURL());
                mav.setViewName(IMOOC_ERROR_VIEW);
                return mav;
            }
        }
    
        // 判断是否是ajax请求
        private static boolean isAjax(HttpServletRequest httpRequest){
            return  (httpRequest.getHeader("X-Requested-With") != null
                    && "XMLHttpRequest"
                    .equals( httpRequest.getHeader("X-Requested-With").toString()) );
        }
    }
  • 4、使用测试
@GetMapping("/exception")
@ResponseBody
public String exceptionTest() throws Exception {
    throw new B2CException(ResultEnum.LOGIN_FAIL);
//  return "aspect test";
}

可以看到浏览器返回{"code":-1,"msg":"登录失败, 登录信息不正确"}

猜你喜欢

转载自blog.csdn.net/mqy1023/article/details/79633325