学成在线--7.CMS页面管理开发(异常处理)

文章目录

  • 1.异常处理的问题分析
  • 2.异常处理流程
  • 3.可预知异常处理
    • 1.自定义异常类
    • 2.异常抛出类
    • 3.异常捕获类
    • 4.异常处理测试
      • 1)定义错误代码
      • 2)异常处理测试
  • 4.不可预知异常处理
    • 1.定义异常捕获方法
      • 1)异常抛出测试
      • 2)异常捕获方法

1.异常处理的问题分析

从添加页面的service方法中找问题:
文件位置:com/ xuecheng/ manage_cms/ service/ PageService

//添加页面
public CmsPageResult add(CmsPage cmsPage){
//校验页面是否存在,根据页面名称、站点Id、页面webpath查询
CmsPage cmsPage1=cmsPageRepository.findByPageNameAndSiteIdAndPageWebPath(cmsPage.getPageName(),cmsPage.getSiteId(),cmsPage.getPageWebPath());
if(cmsPage1==null){
cmsPage.setPageId(null);//添加页面主键由spring data 自动生成
cmsPageRepository.save(cmsPage);
//返回结果
CmsPageResult cmsPageResult = new CmsPageResult(CommonCode.SUCCESS,cmsPage);
return cmsPageResult;
} 
return new CmsPageResult(CommonCode.FAIL,null);
}

问题:
1)上边的代码只要操作不成功仅向用户返回“错误代码:11111,失败信息:操作失败”,无法区别具体的错误信
息。
2)service方法在执行过程出现异常在哪捕获?在service中需要都加try/catch,如果在controller也需要添加
try/catch,代码冗余严重且不易维护。

解决方案:
1)在Service方法中的编码顺序是先校验判断,有问题则抛出具体的异常信息,最后执行具体的业务操作,返回成
功信息。
2)在统一异常处理类中去捕获异常,无需controller捕获异常,向用户返回统一规范的响应信息。

代码模板如下:

//添加页面
public CmsPageResult add(CmsPage cmsPage){
//校验cmsPage是否为空
if(cmsPage == null){
//抛出异常,非法请求
//...
}
//根据页面名称查询(页面名称已在mongodb创建了唯一索引)
CmsPage cmsPage1 =cmsPageRepository.findByPageNameAndSiteIdAndPageWebPath(cmsPage.getPageName(),cmsPage.getSiteId(),cmsPage.getPageWebPath());
//校验页面是否存在,已存在则抛出异常
if(cmsPage1 !=null){
//抛出异常,已存在相同的页面名称
//...
} 
cmsPage.setPageId(null);//添加页面主键由spring data 自动生成
CmsPage save = cmsPageRepository.save(cmsPage);
//返回结果
CmsPageResult cmsPageResult = new CmsPageResult(CommonCode.SUCCESS,save);
return cmsPageResult;
}

2.异常处理流程

系统对异常的处理使用统一的异常处理流程:
1、自定义异常类型。
2、自定义错误代码及错误信息。
3、对于可预知的异常由程序员在代码中主动抛出,由SpringMVC统一捕获。
可预知异常是程序员在代码中手动抛出本系统定义的特定异常类型,由于是程序员抛出的异常,通常异常信息比较齐全,程序员在抛出时会指定错误代码及错误信息,获取异常信息也比较方便。
4、对于不可预知的异常(运行时异常)由SpringMVC统一捕获Exception类型的异常。
不可预知异常通常是由于系统出现bug、或一些不要抗拒的错误(比如网络中断、服务器宕机等),异常类型为RuntimeException类型(运行时异常)。
5、可预知的异常及不可预知的运行时异常最终会采用统一的信息格式(错误代码+错误信息)来表示,最终也会随请求响应给客户端。

在这里插入图片描述
1、在controller、service、dao中程序员抛出自定义异常;springMVC框架抛出框架异常类型
2、统一由异常捕获类捕获异常,并进行处理
3、捕获到自定义异常则直接取出错误代码及错误信息,响应给用户。
4、捕获到非自定义异常类型首先从Map中找该异常类型是否对应具体的错误代码,如果有则取出错误代码和错误信息并响应给用户,如果从Map中找不到异常类型所对应的错误代码,则统一为99999错误代码并响应给用户。
5、将错误代码及错误信息以Json格式响应给用户。

3.可预知异常处理

1.自定义异常类

文件位置:com/ xuecheng/ framework/ exception/ CustomException

package com.xuecheng.framework.exception;import com.xuecheng.framework.model.response.ResultCode;/*** 自定义异常类型**/
public class CustomException extends RuntimeException {//错误代码ResultCode resultCode;public CustomException(ResultCode resultCode){this.resultCode = resultCode;}public ResultCode getResultCode(){return resultCode;}}

2.异常抛出类

文件位置:com/ xuecheng/ framework/ exception/ ExceptionCast

package com.xuecheng.framework.exception;
import com.xuecheng.framework.model.response.ResultCode;
public class ExceptionCast {
//使用此静态方法抛出自定义异常
public static void cast(ResultCode resultCode){
throw new CustomException(resultCode);
}
}

3.异常捕获类

使用 @ControllerAdvice和@ExceptionHandler注解来捕获指定类型的异常

文件位置:com/ xuecheng/ framework/ exception/ ExceptionCatch

package com.xuecheng.framework.exception;import com.google.common.collect.ImmutableMap;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.model.response.ResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;/*** 统一异常捕获类**/
@ControllerAdvice//控制器增强
public class ExceptionCatch {private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionCatch.class);//捕获CustomException此类异常@ExceptionHandler(CustomException.class)@ResponseBodypublic ResponseResult customException(CustomException customException){//记录日志LOGGER.error("catch exception:{}",customException.getMessage());ResultCode resultCode = customException.getResultCode();return new ResponseResult(resultCode);}}

4.异常处理测试

1)定义错误代码

每个业务操作的异常使用异常代码去标识

文件位置:com/ xuecheng/ framework/ domain/ cms/ response / CmsCode

package com.xuecheng.framework.domain.cms.response;import com.xuecheng.framework.model.response.ResultCode;
import lombok.ToString;@ToString
public enum CmsCode implements ResultCode {CMS_ADDPAGE_EXISTSNAME(false,24001,"页面名称已存在!"),CMS_GENERATEHTML_DATAURLISNULL(false,24002,"从页面信息中找不到获取数据的url!"),CMS_GENERATEHTML_DATAISNULL(false,24003,"根据页面的数据url获取不到数据!"),CMS_GENERATEHTML_TEMPLATEISNULL(false,24004,"页面模板为空!"),CMS_GENERATEHTML_HTMLISNULL(false,24005,"生成的静态html为空!"),CMS_GENERATEHTML_SAVEHTMLERROR(false,24005,"保存静态html出错!"),CMS_COURSE_PERVIEWISNULL(false,24007,"预览页面为空!");//操作代码boolean success;//操作代码int code;//提示信息String message;private CmsCode(boolean success, int code, String message){this.success = success;this.code = code;this.message = message;}@Overridepublic boolean success() {return success;}@Overridepublic int code() {return code;}@Overridepublic String message() {return message;}
}

其中继承的接口ResultCode如下:

package com.xuecheng.framework.model.response;/*** Created by mrt on 2018/3/5.* 10000-- 通用错误代码* 22000-- 媒资错误代码* 23000-- 用户中心错误代码* 24000-- cms错误代码* 25000-- 文件系统*/
public interface ResultCode {//操作是否成功,true为成功,false操作失败boolean success();//操作代码int code();//提示信息String message();}

2)异常处理测试

1.抛出异常
在controller、service、 dao中都可以抛出异常。
修改PageService的add方法,添加抛出异常的代码

文件位置:com/ xuecheng/ manage_cms/ service/ PageService

/校验页面是否存在,根据页面名称、站点Id、页面webpath查询
CmsPage cmsPage1 =cmsPageRepository.findByPageNameAndSiteIdAndPageWebPath(cmsPage.getPageName(),cmsPage.getSiteId(), cmsPage.getPageWebPath());
if(cmsPage1 !=null){
//校验页面是否存在,已存在则抛出异常
ExceptionCast.cast(CmsCode.CMS_ADDPAGE_EXISTS);
}

2、启动工程,扫描到异常捕获的类ExceptionCatch

文件位置:com/ xuecheng/ manage_cms/ ManageCmsApplication

在springBoot的启动类中添加

@ComponentScan(basePackages="com.xuecheng.framework")//扫描common工程下的类

3、前端展示异常信息

服务端响应信息如下:
在这里插入图片描述
前端页面提取异常处理
文件位置:src/ module/ cms/ page/ page_add.vue

      addSubmit:function(){this.$refs['pageForm'].validate((valid) => {if (valid) {//表单校验成功//确认提示this.$confirm('您确认提交吗?', '提示', { }).then(() => {//调用page_add方法请求服务端的新增页面接口cmsApi.page_add(this.pageForm).then(res=>{//解析服务端响应内容if(res.success){/*this.$message({message: '提交成功',type: 'success'})*/this.$message.success("提交成功")//将表单清空this.$refs['pageForm'].resetFields();}else if(res.message){this.$message.error(res.message)}else{this.$message.error("提交失败")}});})}});},

4.不可预知异常处理

1.定义异常捕获方法

1)异常抛出测试

使用postman测试添加页面,不输入cmsPost信息,提交,报错信息如下:

org.springframework.http.converter.HttpMessageNotReadableException
此异常是springMVC在进行参数转换时报的错误。

具体的响应的信息为:

{
"timestamp": 1528712906727,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "Required request body is missing: public
com.xuecheng.framework.domain.cms.response.CmsPageResult
com.xuecheng.manage_cms.web.controller.CmsPageController.add(com.xuecheng.framework.domain.cms.C
msPage)",
"path": "/cms/page/add"
}

上边的响应信息在客户端是无法解析的。

2)异常捕获方法

针对上边的问题其解决方案是:
1、我们在map中配置HttpMessageNotReadableException和错误代码。
2、在异常捕获类中对Exception异常进行捕获,并从map中获取异常类型对应的错误代码,如果存在错误代码则返
回此错误,否则统一返回99999错误。
具体的开发实现如下:
1、在通用错误代码类CommCode中配置非法参数异常
文件位置:com/xuecheng/framework/model/response/CommonCode

INVALID_PARAM(false,10003,"非法参数!")

2.在异常捕获类中添加对Exception异常的捕获,并配置 HttpMessageNotReadableException 为非法参数异常

文件位置:com/ xuecheng/ framework/ exception/ ExceptionCatch

package com.xuecheng.framework.exception;import com.google.common.collect.ImmutableMap;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.model.response.ResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;/*** 统一异常捕获类* @author Administrator* @version 1.0* @create 2018-09-14 17:32**/
@ControllerAdvice//控制器增强
public class ExceptionCatch {private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionCatch.class);//定义map,配置异常类型所对应的错误代码private static ImmutableMap<Class<? extends Throwable>,ResultCode> EXCEPTIONS;//定义map的builder对象,去构建ImmutableMapprotected static ImmutableMap.Builder<Class<? extends Throwable>,ResultCode> builder = ImmutableMap.builder();//捕获CustomException此类异常@ExceptionHandler(CustomException.class)@ResponseBodypublic ResponseResult customException(CustomException customException){//记录日志LOGGER.error("catch exception:{}",customException.getMessage());ResultCode resultCode = customException.getResultCode();return new ResponseResult(resultCode);}//捕获Exception此类异常@ExceptionHandler(Exception.class)@ResponseBodypublic ResponseResult exception(Exception exception){//记录日志LOGGER.error("catch exception:{}",exception.getMessage());if(EXCEPTIONS == null){EXCEPTIONS = builder.build();//EXCEPTIONS构建成功}//从EXCEPTIONS中找异常类型所对应的错误代码,如果找到了将错误代码响应给用户,如果找不到给用户响应99999异常ResultCode resultCode = EXCEPTIONS.get(exception.getClass());if(resultCode !=null){return new ResponseResult(resultCode);}else{//返回99999异常return new ResponseResult(CommonCode.SERVER_ERROR);}}static {//定义异常类型所对应的错误代码builder.put(HttpMessageNotReadableException.class,CommonCode.INVALID_PARAM);}
}

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

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

相关文章

Django(6)

为什么不用_set related_name和related_query_name的区别related_name将成为相关对象的属性&#xff0c;允许您使用外键对模型进行“倒退”。例如&#xff0c;如果ModelA有像下面这样的字段&#xff0c;那么model_b ForeignKeyField(ModelB, related_namemodel_as)这将使您能够…

P5 RV1126编码测试Demo

目录 前言 01 测试Demo大致流程图 02 代码分析 2.1 VI设备初始化 2.2 使能通道 —— RK_MPI_VI_EnableChn 2.3 VI 和 VENC绑定 2.4 创建 编码线程 前言 从本章开始我们将要学习嵌入式音视频的学习了 &#xff0c;使用的瑞芯微的开发板 &#x1f3ac; 个人主页&#xff1a…

MP算法和OMP算法及其思想

主要介绍MP(Matching Pursuits)算法和OMP(Orthogonal Matching Pursuit)算法[1]&#xff0c;这两个算法虽然在90年代初就提出来了&#xff0c;但作为经典的算法&#xff0c;国内文献(可能有我没有搜索到)都仅描述了算法步骤和简单的应用&#xff0c;并未对其进行详尽的分析&…

SpringMVC详细示例实战教程

一、SpringMVC基础入门&#xff0c;创建一个HelloWorld程序 1.首先&#xff0c;导入SpringMVC需要的jar包。 2.添加Web.xml配置文件中关于SpringMVC的配置 123456789101112131415<!--configure the setting of springmvcDispatcherServlet and configure the mapping-->&…

学成在线--8.Freemarker入门教程

文章目录1.FreeMarker介绍1&#xff09;常用的java模板引擎还有哪些&#xff1f;2&#xff09;freemarker是一个用Java开发的模板引擎3&#xff09;模板数据模型输出2.FreeMarker快速入门1&#xff09;创建测试工程2&#xff09;配置文件3&#xff09;创建模型类4&#xff09;创…

if...elif...else...fi和case...esac的脚本条件判断式

注意1&#xff1a; if 表达式和case 表达式的区别及什么时候使用哪个要有明确的区分&#xff1f; 『 if .... then .... fi 』对于变量的判断是以『比对』的方式来分辨的&#xff0c; 如果符合状态就进行某些行为&#xff0c;并且透过较多层次 (就是elif ) 的方式来进行多个变量…

安卓自定义View进阶-分类与流程

自定义View绘制流程函数调用链(简化版) 一.自定义View分类 我将自定义View分为了两类(sloop个人分类法&#xff0c;非官方)&#xff1a; 1.自定义ViewGroup 自定义ViewGroup一般是利用现有的组件根据特定的布局方式来组成新的组件&#xff0c;大多继承自ViewGroup或各种Layout&…

【笔试记录】2021/3/13美团

2021/3/13美团笔试 1.旋转二维数组 m, n map(int, input().split()) a [] for _ in range(m):a.append(list(map(int, input().split()))) for j in range(n):for k in range(m):print(a[k][j], end )print(end\n)输入输出 2.找出输入字符串中的所有数字 s input() n …

学成在线--9.页面静态化

文章目录一.页面静态化流程二.数据模型1.轮播图DataUrl接口1&#xff09;需求分析2&#xff09;接口定义3&#xff09;Dao4&#xff09;Service5&#xff09;Controller6&#xff09;测试2.远程请求接口1&#xff09;添加依赖2&#xff09;配置RestTemplate3&#xff09;测试Re…

数据库MySQL/mariadb知识点——日志记录(2)二进制日志

二进制日志 记录已提交事务导致数据改变或潜在导致数据改变的SQL语句&#xff0c;通过“重放”日志文件中的事件来生成数据副本&#xff0c;不依赖存储引擎类型。 开启二进制日志&#xff0c;默认是关闭的&#xff0c;二进制日志和数据分开存放 开启记录二进制文件的功能&#…

【面试记录】Python常见面试200题及答案总结

Python常见面试200题及答案总结 /待完善/ 1. 列出5个常用python标准库&#xff1f; os&#xff1a;提供了不少与操作系统相关联的函数&#xff0c;提供了一种可移植的使用操作系统功能的方法。使用os模块中提供的接口&#xff0c;可实现跨平台访问。但是&#xff0c;并不是所…

Linux负载均衡软件LVS之一(概念篇)

2019独角兽企业重金招聘Python工程师标准>>> 一、 LVS简介 LVS是Linux Virtual Server的简称&#xff0c;也就是Linux虚拟服务器, 是一个由章文嵩博士发起的自由软件项目&#xff0c;它的官方站点是www.linuxvirtualserver.org。现在LVS已经是 Linux标准内核的一部分…

学成在线--10.页面预览

文章目录一.需求分析二. 搭建环境1.在cms服务中集成freemarker&#xff1a;2.在application.yml配置freemarker三.Service四.Controller五.页面预览测试-- 配置Nginx代理六.页面预览测试-- 添加“页面预览”链接一.需求分析 页面在发布前增加页面预览的步骤&#xff0c;方便用…

【代码刷题】排序算法总结(python实现)

排序算法总结&#xff08;Python实现&#xff09;算法介绍算法分类相关概念1. 冒泡排序&#xff08;Bubble Sort&#xff09;1.1 思想1.2 python实现1.3 复杂度1.4 稳定性2. 快速排序&#xff08;Quick Sort&#xff09;2.1 思想&#xff08;伪代码&#xff09;2.2 python实现2…

学成在线--11.RabbitMQ快速入门

文章目录一.RabbitMQ简介二.相关知识1.AMQP2.JMS是什么 &#xff1f;三.RabbitMQ的工作原理四.Hello World1.创建Maven工程2.生产者3.消费者五.总结一.RabbitMQ简介 MQ全称为Message Queue&#xff0c;即消息队列&#xff0c; RabbitMQ是由erlang语言开发&#xff0c;基于AMQP…

maven工程建立和SSM(springMVC+spring+mybatis)整合

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1.环境&#xff1a; maven 版本&#xff1a;3.5.1 ecelipse mars.2 JDK : jdk1.8.0_45 tomcat : apache-tomcat-8.0.0-RC1 2. 建…

Java——网络编程(实现基于命令行的多人聊天室)

2019独角兽企业重金招聘Python工程师标准>>> 目录&#xff1a; 1.ISO和TCP/IP分层模型 2.IP协议 3.TCP/UDP协议 4.基于TCP的网络编程 5.基于UDP的网络编程 6.基于TCP的多线程的聊天室的实现 1.ISO和TCP/IP分层模型&#xff1a; OSI分层模型&#xff08;Open System …

一网打尽中文编码转换---6种编码30个方向的转换

一网打尽中文编码转换——6种编码30个方向的转换 1.问题提出 在学编程序时&#xff0c;曾经有人问过“你可以编一个记事本程序吗?”当时很不屑一顾&#xff0c;但是随着学习MFC的深入&#xff0c;了解到记事本程序也并非易事&#xff0c;难点就是四种编码之间的转换。 对于编…

十万服务器秒级管控 腾讯云如何将AIOps用于日常管理?

AIOps&#xff0c;是指基于算法的 IT运维&#xff08;Algorithmic IT Operations&#xff09;&#xff0c;由 Gartner定义的新类别&#xff0c;源自业界之前所说的 ITOA&#xff08;IT Operations and Analytics&#xff09;。我们已经到达了这样的一个时代&#xff0c;数据科学…

ssm(springMVC + spring+MyBatis) 小例

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 整体环境参见本人另一文&#xff1a;http://blog.csdn.net/jiangyu1013/article/details/51983360 此工程访问入口为index.jsp页面. 工…