手写SpringMVC之前后置操作HandlerAdviserResolver&全局异常处理HnadlerGlobalExceptionResolver&数据库模块

HandlerAdviserResolver:前后置操作

设计思路:

  1. HandlerAdviserResolver抽象类有四个方法

    其中前面两个方法交给web项目中去重写,后面两个方法由框架调用

    public abstract String beforeAdviser(String requestData);
    
    public abstract String afterAdviser(String responseData);
    
    public String before(String requestData) {
        return beforeAdviser(requestData);
    }
    
    public String after(String responseData) {
        return afterAdviser(responseData);
    }
    
  2. web项目继承HandlerAdviserResolver抽象类并实现两个抽象方法

    其本质目的是将前后置操作的业务逻辑交给web项目去实现,而不是在框架中实现

    ps:在框架传递前端数据到参数中时,需要对前端数据进行解密,就需要解密的代码逻辑

    public class Adviser extends HandlerAdviserResolver {
    
        private static final int SHIFT = 4; // 固定偏移量
    
        @Override
        public String beforeAdviser(String requestData) {
            System.out.println("解密:" + requestData);
            return requestData;
        }
    
        @Override
        public String afterAdviser(String responseData) {
            System.out.println("加密:" + responseData);
            return responseData;
        }
    }
    
  3. 通过DispatcherServlet调度器的init方法去判断配置类上是否带有@EnableAdviser注解,对HandlerAdviserResolver对象进行初始化

    @Configuration("cn.cnmd.controller")@EnableAdviser("cn.cnmd.adviser.Adviser")//前后置操作
    public class AppConfig {}
    
    
    //DispatcherServlet
    
    @Override
    public void init() throws ServletException {
    
        ServletContext servletContext = this.getServletContext();
        String config = servletContext.getInitParameter("config");
        //拿到了配置类的class对象
        Class<?> configClass = getConfiguration(config);
    
        //初始化前后置处理器
        initAdviserResolver(configClass);
    
    }
    
  4. DispatcherServlet调度器通过判断方法参数上是否有@BeforeAdviser和@AfterAdviser在传递参数前进行解密、发送数据前进行加密

    jsonStr = handlerAdviserResolver.before(jsonStr);//解密
    
    jsonStr = handlerAdviserResolver.after(jsonStr);//加密
    

理解图(个人)

前后置操作

HandlerGlobalExceptionResolver:全局异常处理器

设计思路

大致思路与HandlerAdviserResolver一致

  1. HandlerGlobalExceptionResolver有两个方法,一个交给web项目的HandlerException去实现具体处理异常的代码逻辑,另一个交由DispatcherServlet调度器去调用
  2. web项目的HandlerException去继承HandlerGlobalExceptionResolver并重写handlerGlobalException方法,实现具体处理异常的代码逻辑
  3. 通过DispatcherServlet调度器的init方法去判断配置类上是否带有@EnableGlobalException注解,对HandlerGlobalExceptionResolver对象进行初始化
  4. DispatcherServlet调度器调用另一个方法,间接调用了web项目中重写的handlerGlobalException方法去处理异常

理解图(个人)

image-20240628171437723

dbutil模块:对数据库的操作

分包

  • base包:

    • ResultSetHandler:对结果集操作的顶级接口

      public interface ResultSetHandler<T> {
          public T handler(ResultSet rs) throws SQLException;
      }
      
    • RowProsecessor:行处理器的接口

      public interface RowProcessor <T>{
          public T toArray(ResultSet rs) throws SQLException;
      }
      
      
  • core包:

    • QueryRunner类:包含了对数据库的query操作和update操作(类似于我以前写的DBUtil利用反射操作数据库)
  • handler包:

    • BeanListHandler(ResultSet):处理结果集为List集合,ps:多个用户的全部信息

      public class BeanListHandler<T> implements ResultSetHandler<List<T>> {
      
          private Class<T> beanClass;
      
          public BeanListHandler(Class<T> beanClass) {
              this.beanClass = beanClass;
          }
      
          @Override
          public List<T> handler(ResultSet resultSet) throws SQLException {
      
              List<T> list;
      
              try {
                  list = new ArrayList<>();
                  ResultSetMetaData metaData = resultSet.getMetaData();
      
                  int columnCount = metaData.getColumnCount();
      
                  while (resultSet.next()) {
      
                      T t = beanClass.newInstance();
      
                      for (int i = 1; i <= columnCount; i++) {
                          String columnName = metaData.getColumnName(i);
                          Object columnVal = resultSet.getObject(columnName);
                          BeanUtils.setProperty(t, columnName, columnVal);
                      }
                      list.add(t);
                  }
              } catch (InvocationTargetException | IllegalAccessException | InstantiationException e) {
                  throw new RuntimeException(e);
              }
              return list;
          }
      }
      
    • BeanHandler(ResultSet):处理结果为单条数据,ps:单个用户的全部信息

      public class BeanHandler<T> implements ResultSetHandler<T> {
      
          private Class<T> beanClass;
      
          public BeanHandler(Class<T> beanClass) {
              this.beanClass = beanClass;
          }
      
          @Override
          public T handler(ResultSet resultSet) throws SQLException {
      
              ResultSetMetaData metaData = resultSet.getMetaData();
      
              int columnCount = metaData.getColumnCount();
      
              try {
                  if (resultSet.next()) {
      
                      T t = beanClass.newInstance();
      
                      for (int i = 1; i <= columnCount; i++) {
                          String columnName = metaData.getColumnName(i);
                          Object columnVal = resultSet.getObject(columnName);
                          BeanUtils.setProperty(t, columnName, columnVal);
                      }
                      return t;
                  }
              } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
                  throw new RuntimeException(e);
              }
      
              return null;
          }
      }
      
    • ArrayHandler(ResultSet):处理结果集为数据,ps:多个用户的用户名信息

      ArrayHandler主要就依赖于RowProcessor行处理器,虽然我觉得简直多此一举

      public class ArrayHandler<T> implements ResultSetHandler<T[]> {
      
          private RowProcessor<T> rowProcessor;
      
          public ArrayHandler(RowProcessor<T> rowProcessor) {
              this.rowProcessor = rowProcessor;
          }
      
          @Override
          public T[] handler(ResultSet resultSet) throws SQLException {
              return rowProcessor.toArray(resultSet);
          }
      }
      
  • processor包

    • RowProcessor类:行处理器,处理一行数据

      //将查询的数据添加到list集合中,再将list集合转化为数据返回
      public class RowProcessor<T> implements cn.cnmd.shop.dbutil.base.RowProcessor<T[]> {
      
          private Class<T> arrClass;
      
          public RowProcessor(Class<T> arrClass) {
              this.arrClass = arrClass;
          }
      
          @Override
          public T[] toArray(ResultSet resultSet) throws SQLException {
      
              List<T> list = new ArrayList<>();
      
              while (resultSet.next()) {
      
                  T t = (T) resultSet.getObject(1);
                  list.add(t);
              }
      
              T[] ts = (T[]) Array.newInstance(arrClass, list.size());
      
              for (int i = 0; i < list.size(); i++) {
                  ts[i] = list.get(i);
              }
      
              return ts;
          }
      }
      
      

理解图(个人)

image-20240628181011275

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拖把湛屎,戳谁谁死

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值