SSM框架学习记录-SpringMVC_day02

1.SSM整合

代码参考Springmvc_08_ssm


流程分析

测试

2.统一结果封装

Controller层中会返回不同类型数据给前端(有boolean值、单个对象的Json或集合对象的Json等),如果后台能够返回统一的数据结果,前端在解析时就可按照一种方式进行解析,简化开发。主要思想如下(即创建Result类):

  • 为了封装返回的结果数据:创建结果模型类,封装数据到data属性中(定义为Object类型就可以接收所有类型的数据)
  • 为了封装返回的数据是何种操作及是否操作成功:封装操作结果到code属性中
  • 操作失败后为了封装返回的错误信息:封装特殊消息到msg属性中

代码参考Springmvc_09_result


表现层与前端数据传输协议实现

和前端的传输协议其实就是定义数据以什么形式返回给前端,前端根据返回的结果,先从中获取code ,根据code判断,如果成功则取data属性的值,如果失败则取msg中的值做提示。具体流程如下:

  • 环境准备:和之前类似,不再赘述
  • 结果封装:
  • 使用PostMan测试:看返回的Json数据中三个属性是否符合预期

3.统一异常处理

假设在Service层某个方法执行过程中出现异常,此时返回给前端是500错误页面,前端开发人员无法处理。其实在开发的任何一个位置都有可能出现异常,需要思考以下问题:

  • 各个层级均出现异常,异常处理代码书写在哪一层?不管是Dao层还是啥层,所有的异常全往上抛(即均抛出到表现层进行处理)
  • 异常的种类很多,表现层如何将所有的异常都处理到呢?对异常分类
  • 表现层处理异常,每个方法中单独书写,代码书写量巨大且意义不强,如何解决?AOP

代码参考Springmvc_10_exception


异常处理器的使用
  • 环境准备:和之前类似,不再赘述
  • 创建异常处理器类ProjectExceptionAdvice.java
    • 放置在controller包下确保SpringMvcConfig能够扫描到该类,并且其中的方法可以视为和控制器方法具有一样的处理流程
    • 每个处理异常的方法返回的是Result类型的对象,因为需要返回给前端去解析

项目异常处理方案

为异常的种类有很多,如果每一个异常都对应一个@ExceptionHandler,那需要写许多方法来处理各自的异常,所以在处理异常之前需对异常进行分类:

  • 业务异常(BusinessException):
    • 规范的用户行为产生的异常,如在年龄框输入字符串
    • 不规范的用户行为操作产生的异常,如用户故意传递错误数据
  • 系统异常(SystemException):
    • 项目运行过程中可预计但无法避免的异常,比如数据库或服务器宕机
  • 其他异常(Exception):
    • 编程人员未预期到的异常,如用到的文件不存在

对于上述三种异常,有以下解决流程:

  • 业务异常:
    • 发送对应消息传递给用户,提醒规范操作
  • 系统异常:
    • 发送固定消息传递给用户,比如系统繁忙,请稍后再试
    • 发送特定消息给运维人员,提醒维护
    • 记录日志
  • 其他异常:
    • 发送固定消息传递给用户
    • 发送特定消息给编程人员,提醒维护(比如未做非空校验等)
    • 记录日志

编码思路:

  • 先通过自定义异常,完成BusinessExceptionSystemException的定义
    • 让自定义异常类继承RuntimeException是为了后期在抛出这两个异常的时候,就不用在try-catchthrows
    • 自定义异常类中添加code属性是为了更好的区分异常是来自哪个业务
  • 将其他异常包装成自定义异常类型:使用try-catchthrows皆可
public Book getById(Integer id) {
    // 模拟业务异常,包装成自定义异常
    if (id == 1) {
        throw new BusinessException(Code.BUSINESS_ERR, "请输入正确id!");
    }
    // 模拟系统异常,将可能出现的异常进行包装,转换成自定义异常
    try {
        int i = 1 / 0;
    } catch (Exception e) {
        throw new SystemException(Code.SYSTEM_TIMEOUT_ERR, "服务器访问超时,请重试!", e);
    }
    return bookDao.getById(id);
}

4.前后台协议联调

主要是前端代码的编写

代码参考Springmvc_11_page


5.拦截器

代码参考Springmvc_12_interceptor


拦截器概念

在介绍拦截器(Interceptor)前先大致了解下浏览器发送请求后整个流程:

  • 浏览器发送一个请求会先到Web服务器(即Tomcat)
  • Tomcat服务器接收到请求以后,会去判断请求的是静态资源还是动态资源
  • 静态资源会直接到Tomcat的项目部署目录下去直接访问
  • 动态资源需要交给项目的后台代码进行处理
  • 在找到具体的方法前,可配置一/多个过滤器,按照顺序进行执行
  • 然后进入到到中央处理器(SpringMVC中的内容),SpringMVC会根据配置的规则进行拦截
  • 满足规则则进行处理,找到其对应的Controller类中的方法进行执行,完成后返回结果
  • 不满足规则则不进行处理

在这里插入图片描述

如果此时需要在每个Controller中的方法执行的前后添加业务,该如何实现?使用拦截器即可,它是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行(可以理解为增强方法),主要作用如下:

  • 在指定的方法调用前后执行预先设定的代码
  • 阻止原始方法的执行

拦截器和过滤器之间的区别是什么?

  • 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
  • 拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强

在这里插入图片描述


入门案例
  • 环境准备:和之前类似,不再赘述

  • 拦截器开发:

    • 创建拦截器类ProjectInterceptor.java(因为是给表示层使用,所以放在controller包下)
    • 配置拦截器类:
      • 未简化版则需要创建SpringMvcSupport.java,并且SpringMVCSpringMvcSupport.java所在包进行扫描
      • 简化版就不需要创建SpringMvcSupport.java(也就不需要额外扫描包),可直接在SpringMvcSupport.java中进行配置

    在这里插入图片描述


拦截器参数
  • 前置处理方法preHandle:该方法中可通过返回值来决定是否要进行放行,所以使用率较高
// request:请求对象,可以获取请求数据中的内容
// response:响应对象
// handler:被调用的处理器对象,本质上是一个方法对象,对反射中的Method对象进行了再包装,意味着可获取方法的相关信息
public boolean preHandle(HttpServletRequest request, 
                         HttpServletResponse response, 
                         Object handler) throws Exception {
    String contentType = request.getHeader("Content-Type");
    HandlerMethod hm = (HandlerMethod) handler;
    String name = hm.getMethod().getName();
    System.out.println("preHandle..." + contentType);
    System.out.println("preHandle..." + name);
    return true;
}
  • 后置处理方法postHandle
// modelAndView:如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息并进行调整(现在都返回json数据,该参数使用率不高)
public void postHandle(HttpServletRequest request,
                       HttpServletResponse response, 
                       Object handler, 
                       ModelAndView modelAndView) throws Exception {
    System.out.println("postHandle...");
}
  • 完成处理方法afterCompletion
// ex:如果处理器执行过程中出现异常对象,可以针对异常情况进行单独处理(现在已有全局异常处理器类,该参数的使用率不高)
public void afterCompletion(HttpServletRequest request, 
                            HttpServletResponse response, 
                            Object handler, 
                            Exception ex) throws Exception {
    System.out.println("afterCompletion...");
}

拦截器链配置

在项目中如果有多个拦截器,它们的执行顺序是什么?拦截器执行的顺序和配置顺序有关

  • 当配置多个拦截器时,形成拦截器链
  • 拦截器链的运行顺序参照拦截器添加顺序为准
  • 当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
  • 当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作

在这里插入图片描述


参考


https://www.bilibili.com/video/BV1Fi4y1S7ix?p=59-74

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值