SSM框架学习记录-SpringMVC_day02

news2024/11/26 3:46:36

1.SSM整合

代码参考Springmvc_08_ssm


流程分析

  • 添加依赖:pom.xml
  • 编写配置类:
    • Spring的配置类SpringConfig.java
    • SpringMVC的配置类SpringMvcConfig.java
    • Web项目的入口配置类ServletConfig.java
    • MyBatis的配置类MyBatisConfig.java
    • 第三方数据源的配置类JdbcConfig.java
  • 创建数据库表:tbl_book.sql
  • 根据数据库表创建对应的模型类:Book.java
  • 通过Dao层完成数据库表的增删改查:BookDao.java
  • 编写Service层:BookServiceImpl.java和BookService.java
  • bookDaoService中注入的会提示一个红线提示,因为BookDao是一个接口,没有实现类,最终注入的是代理对象,该代理对象需要等Web服务器启动并完成IOC容器的创建才会生成,但是可以正常运行
  • 编写Controller层:BookController.java

测试

  • Service层进行测试:BookServiceTest.java
  • 使用PostManController中接口进行测试

2.统一结果封装

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

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

代码参考Springmvc_09_result


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

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

  • 环境准备:和之前类似,不再赘述
  • 结果封装:
    • 创建Result.java
    • 定义返回码Code.java
    • 修改Controller类的返回值为Result
  • 使用PostMan测试:看返回的Json数据中三个属性是否符合预期

3.统一异常处理

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

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

代码参考Springmvc_10_exception


异常处理器的使用

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

项目异常处理方案

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

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

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

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

编码思路:

  • 先通过自定义异常,完成BusinessException和SystemException的定义
    • 让自定义异常类继承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);
}
  • 在异常处理器类ProjectExceptionAdvice.java中对不同的异常进行处理

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/114156.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp动态切换显示不同内容组件

需求描述 通过点击注册或是登录按钮切换不同的组件.默认显示登陆界面,登录字样加粗显示,登录页面显示手机号密码登录.点击注册切换到注册页面,注册字样加粗显示,页面显示手机号和验证码以及注册按钮.对应页面显示如下: 实现代码: <template><view class"conte…

pytorch实战(五)——时间序列多步预测的五种方法介绍

当需要根据已有的时间序列数据&#xff0c;预测未来多个时刻的状态时&#xff0c;被称之为时间序列多步预测。 时间序列多步预测有五种策略&#xff0c;分别为&#xff1a; 1、直接多步预测&#xff08;Direct Multi-step Forecast&#xff09; 2、递归多步预测&#xff08;Rec…

Redis5.0+——主从复制

说明 主机数据更新后根据配置和策略&#xff0c;自动同步到备机的master/slave机制&#xff0c;Master以写为主&#xff0c;Slave以读为主&#xff08;一主一从&#xff0c;一主多从&#xff09; 能实现目的 读写分离&#xff0c;性能拓展容灾区快速恢复&#xff08;当一个从…

【软件测试】资深测试的总结,接口测试中的最常见的几个错误......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 为了彻底进行API接口…

入门力扣自学笔记221 C++ (题目编号:1739)

1739. 放置盒子 题目&#xff1a; 有一个立方体房间&#xff0c;其长度、宽度和高度都等于 n 个单位。请你在房间里放置 n 个盒子&#xff0c;每个盒子都是一个单位边长的立方体。放置规则如下&#xff1a; 你可以把盒子放在地板上的任何地方。 如果盒子 x 需要放置在盒子 y…

工作流运行

工作流运行 定义内涵 工作流运行是工作流模板的依次执行&#xff0c;在工作流运行时&#xff0c;用户可以随时取消或查看正在 运行的任务。由于工作流运行的模板的不同&#xff0c;运行过程中可能会产生不同的新资源&#xff0c;如数据 处理类型的工作流会产生新的数据集&…

DJ15 8086 中断程序设计

目录 一、8086/8088 中断系统 1. 8086/8088 中断源类型 2. 中断向量表 3. CPU 中断类型码的获取方法 二、8259A 的引线及内部结构 1. 外部引线 2. 内部结构 3. 与系统总线的连接方式 4. 级联连接方式 5. 中断触发方式 三、8259A 的工作过程 四、8259A 的工作方式 …

K. The Robot(思维 + 看数据范围)

Problem - 1468K - Codeforces 有一个机器人在一个格子场上&#xff0c;这个格子场在各个方向都是无尽的。最初&#xff0c;机器人位于坐标为(0,0)的单元中。他将执行由一串大写拉丁字母 "L"、"R"、"D"、"U "描述的命令。当一个命令被…

使用凸优化来调整基于毫米波的无线通信参数(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 随着通信产业尤其是个人移动通信的高速发展&#xff0c;无线电频谱的低端频率已趋饱和&#xff0c;即使是采用高斯滤波最小频移…

CentOS7安装runc

CentOS7安装runc前言一、runc简介二、安装runc1.安装 libseccomp-dev2.获取runc源代码2.1先创建 $GOPATH/src/github.com 目录2.2go get下载源代码2.3checkout最新的代码2.4编译并安装runc2.5查看runc版本总结前言 本文记录CentOS7安装runc的过程。 一、runc简介 RunC 是一个…

UWB定位算法介绍

典型的无线定位方法主要有四种: 1.基于信号到达时间(TOA)&#xff1b; 2.基于信号到达时间差(TDOA)&#xff1b; 3.基于信号到达角度(AOA) 4.基于接信号强度(RSSI) 各自有着不同的优势和应用范围。 定位时一分为两步&#xff0c;第一步:测量时间、角度、信号强度; 第二步…

FFmpeg基础: YUV像素格式介绍和使用

文章目录YUV像素格式YUV采样YUV格式分类YUV存储模式FFmpeg读取YUV数据YUV和RGB转换YUV像素格式 在图片中我们一般都是通过RGB(红-绿-蓝)格式来表示一个像素点。而在视频当中为了兼容黑白和彩色视频我们通过YUV来表示一个像素点&#xff0c;YUV中Y表示像素点的灰度(也就是亮度分…

【nowcoder】笔试强训Day6

目录 一、单选题 二、多选题 三、编程题 3.1不要二 3.2 把字符串转成整数 一、单选题 1.下面哪段程序能够正确的实现了GBK编码字节流到UTF-8编码字节流的转换&#xff1a; A dstString.frombytes(src,”GBK”).getbytes(“UTF-8”) B dstnew String (src,”GBK”).getb…

计算机视觉与图形学-神经渲染专题-非刚体NeRF

《Fast Non-Rigid Radiance Fields from Monocularized Data》链接&#xff1a;https://graphics.tu-bs.de/publications/kappel2022fast摘要单目动态场景下的 3D 重建和新颖视图合成最近受到越来越多的关注。现有工作在合成给定和前向拍摄的真实世界数据下可以合成较好的结果&…

iPhone如何恢复丢失/消失的通讯录联系人,试试这6 种恢复方案

“在我更新 iOS 后&#xff0c;数百个联系人从我的 iPhone 上消失了。我试图从 iCloud 恢复我的联系人存档。我所看到的只是“没有可用的档案”。请来人帮忙&#xff01;” 每当发布新的 iOS 版本时&#xff0c;许多 iPhone 用户都会争先恐后地开始更新。然而&#xff0c;他们…

【Python学习记录】matplotlib绘图基本配置

✨ 博客主页&#xff1a;小小马车夫的主页 ✨ 所属专栏&#xff1a;Python学习记录 文章目录前言1、设置颜色2、设置每个点marker3、设置标题、X轴、Y轴文字4、设置刻度5、同一图中画多条线、绘制图例6、设置图层顺序7、多个图的设置subplot8、保存图片总结前言 matplotlib是p…

python中文编码json中文输出问题

python2.x版本的字符编码有时让人很头疼&#xff0c;遇到问题&#xff0c;网上方法可以解决错误&#xff0c;但对原理还是一知半解&#xff0c;本文主要介绍 python 中字符串处理的原理&#xff0c;附带解决 json 文件输出时&#xff0c;显示中文而非 unicode 问题。首先简要介…

人机交互-广州DACAI触摸屏开发中遇到的一些(屏幕和编程)问题

目录 背景 一、屏幕相关 1、厂家给的指令集资料可能有错误&#xff0c;请以软件VisualTFT中的指令助手为准。 2、屏幕程序下载方式 3、SD卡文件格式问题 4、画面id的问题 巨坑&#xff01;&#xff01;&#xff01; 5、子画面变暗的问题 6、 VisualTFT自带的键盘问题 …

【openGauss】一键编译openGauss3.1+dolphin,体验新增的mysql兼容特性

前言 前两天写了一篇openGauss3.1关于mysql的相关特性&#xff0c;但由于openGauss官网提供下载的版本还是9月30号第一次发布的版本&#xff0c;很多特性都还没合入&#xff0c;所以不少爱好者不能轻易体验到。 虽然openGauss已经提供了“一键式编译脚本”,但是还是得做一些前…

Linux系统下的常用文件目录指令

文件目录指令 pwd (Print Working Directory):显示当前工作目录的绝对路泾 ls (list) 基本语法:ls[选项][目录或是文件]常用选项 -a:显示当前目录所有的文件和目录&#xff0c;包括隐藏的。 -l:以列表的方式显示信息 cd (change directory) :切换到指定目录 基本语法:cd参数理…