当前位置: 首页 > news >正文

佛山市南海区交通建设网站珠海建站公司

佛山市南海区交通建设网站,珠海建站公司,做网站个体户执照,优化方案系列丛书文章目录 1#xff0c;SSM整合1.1 流程分析1.2 整合配置步骤1#xff1a;创建Maven的web项目步骤2:添加依赖步骤3:创建项目包结构步骤4:创建SpringConfig配置类步骤5:创建JdbcConfig配置类步骤6:创建MybatisConfig配置类步骤7:创建jdbc.properties步骤8:创建SpringMVC配置类步… 文章目录 1SSM整合1.1 流程分析1.2 整合配置步骤1创建Maven的web项目步骤2:添加依赖步骤3:创建项目包结构步骤4:创建SpringConfig配置类步骤5:创建JdbcConfig配置类步骤6:创建MybatisConfig配置类步骤7:创建jdbc.properties步骤8:创建SpringMVC配置类步骤9:创建Web项目入口配置类 1.3 功能模块开发步骤1:创建数据库及表步骤2:编写模型类步骤3:编写Dao接口步骤4:编写Service接口和实现类步骤5:编写Contorller类 1.4 单元测试步骤1:新建测试类步骤2:注入Service类步骤3:编写测试方法 1.5 PostMan测试新增修改删除查询单个查询所有 2统一结果封装2.1 表现层与前端数据传输协议定义2.2 表现层与前端数据传输协议实现2.2.1 环境准备2.2.2 结果封装步骤1:创建Result类步骤2:定义返回码Code类步骤3:修改Controller类的返回值步骤4:启动服务测试 3统一异常处理3.1 问题描述3.2 异常处理器的使用3.2.1 环境准备3.2.2 使用步骤步骤1:创建异常处理器类步骤2:让程序抛出异常步骤3:运行程序测试异常处理器类返回结果给前端 知识点1RestControllerAdvice知识点2ExceptionHandler 3.3 项目异常处理方案3.3.1 异常分类3.3.2 异常解决方案3.3.3 异常解决方案的具体实现步骤1:自定义异常类步骤2:将其他异常包成自定义异常步骤3:处理器类中处理自定义异常步骤4:运行程序 4前后台协议联调4.1 环境准备4.2 列表功能4.3 添加功能4.4 添加功能状态处理4.5 修改功能4.6 删除功能 内容 完成SSM的整合开发能够理解并实现统一结果封装与统一异常处理能够完成前后台功能整合开发 1SSM整合 前面我们已经把Mybatis、Spring和SpringMVC三个框架进行了学习今天主要的内容就是把这三个框架整合在一起完成我们的业务功能开发具体如何来整合我们一步步来学习。 1.1 流程分析 (1) 创建工程 创建一个Maven的web工程pom.xml添加SSM需要的依赖jar包编写Web项目的入口配置类实现AbstractAnnotationConfigDispatcherServletInitializer重写以下方法 getRootConfigClasses() 返回Spring的配置类-需要SpringConfig配置类getServletConfigClasses() 返回SpringMVC的配置类-需要SpringMvcConfig配置类getServletMappings() : 设置SpringMVC请求拦截路径规则getServletFilters() 设置过滤器解决POST请求中文乱码问题 (2)SSM整合[重点是各个配置的编写] SpringConfig 标识该类为配置类 Configuration扫描Service所在的包 ComponentScan在Service层要管理事务 EnableTransactionManagement读取外部的properties配置文件 PropertySource整合Mybatis需要引入Mybatis相关配置类 Import 第三方数据源配置类 JdbcConfig 构建DataSource数据源DruidDataSouroce,需要注入数据库连接四要素 Bean Value构建平台事务管理器DataSourceTransactionManager,Bean Mybatis配置类 MybatisConfig 构建SqlSessionFactoryBean并设置别名扫描与数据源Bean构建MapperScannerConfigurer并设置DAO层的包扫描 SpringMvcConfig 标识该类为配置类 Configuration扫描Controller所在的包 ComponentScan开启SpringMVC注解支持 EnableWebMvc (3)功能模块[与具体的业务模块有关] 创建数据库表根据数据库表创建对应的模型类通过Dao层完成数据库表的增删改查(接口自动代理)编写Service层[Service接口实现类] ServiceTransactional整合Junit对业务层进行单元测试 RunWithContextConfigurationTest 编写Controller层 接收请求 RequestMapping GetMapping PostMapping PutMapping DeleteMapping接收数据 简单、POJO、嵌套POJO、集合、数组、JSON数据类型 RequestParamPathVariableRequestBody 转发业务层 Autowired 响应结果 ResponseBody 1.2 整合配置 掌握上述的知识点后接下来我们就可以按照上述的步骤一步步的来完成SSM的整合。 步骤1创建Maven的web项目 可以使用Maven的骨架创建 步骤2:添加依赖 pom.xml添加SSM所需要的依赖jar包 ?xml version1.0 encodingUTF-8?project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.itheima/groupIdartifactIdspringmvc_08_ssm/artifactIdversion1.0-SNAPSHOT/versionpackagingwar/packagingdependenciesdependencygroupIdorg.springframework/groupIdartifactIdspring-webmvc/artifactIdversion5.2.10.RELEASE/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion5.2.10.RELEASE/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion5.2.10.RELEASE/version/dependencydependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.5.6/version/dependencydependencygroupIdorg.mybatis/groupIdartifactIdmybatis-spring/artifactIdversion1.3.0/version/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion5.1.47/version/dependencydependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.1.16/version/dependencydependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependencydependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.1.0/versionscopeprovided/scope/dependencydependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-databind/artifactIdversion2.9.0/version/dependency/dependenciesbuildpluginsplugingroupIdorg.apache.tomcat.maven/groupIdartifactIdtomcat7-maven-plugin/artifactIdversion2.1/versionconfigurationport80/portpath//path/configuration/plugin/plugins/build /project 步骤3:创建项目包结构 Masked5 / heima_springmvc_codes · GitCode config目录存放的是相关的配置类controller编写的是Controller类dao存放的是Dao接口因为使用的是Mapper接口代理方式所以没有实现类包service存的是Service接口impl存放的是Service实现类resources:存入的是配置文件如Jdbc.propertieswebapp:目录可以存放静态资源test/java:存放的是测试类 步骤4:创建SpringConfig配置类 Configuration ComponentScan({com.itheima.service}) PropertySource(classpath:jdbc.properties) Import({JdbcConfig.class,MyBatisConfig.class}) EnableTransactionManagement public class SpringConfig { }步骤5:创建JdbcConfig配置类 public class JdbcConfig {Value(${jdbc.driver})private String driver;Value(${jdbc.url})private String url;Value(${jdbc.username})private String username;Value(${jdbc.password})private String password;Beanpublic DataSource dataSource(){DruidDataSource dataSource new DruidDataSource();dataSource.setDriverClassName(driver);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource){DataSourceTransactionManager ds new DataSourceTransactionManager();ds.setDataSource(dataSource);return ds;} }步骤6:创建MybatisConfig配置类 public class MyBatisConfig {Beanpublic SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){SqlSessionFactoryBean factoryBean new SqlSessionFactoryBean();factoryBean.setDataSource(dataSource);factoryBean.setTypeAliasesPackage(com.itheima.domain);return factoryBean;}Beanpublic MapperScannerConfigurer mapperScannerConfigurer(){MapperScannerConfigurer msc new MapperScannerConfigurer();msc.setBasePackage(com.itheima.dao);return msc;} }步骤7:创建jdbc.properties 在resources下提供jdbc.properties,设置数据库连接四要素 jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/ssm_db jdbc.usernameroot jdbc.passwordroot步骤8:创建SpringMVC配置类 Configuration ComponentScan(com.itheima.controller) EnableWebMvc public class SpringMvcConfig { }步骤9:创建Web项目入口配置类 public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {//加载Spring配置类protected Class?[] getRootConfigClasses() {return new Class[]{SpringConfig.class};}//加载SpringMVC配置类protected Class?[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};}//设置SpringMVC请求地址拦截规则protected String[] getServletMappings() {return new String[]{/};}//设置post请求中文乱码过滤器Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter filter new CharacterEncodingFilter();filter.setEncoding(utf-8);return new Filter[]{filter};} } 至此SSM整合的环境就已经搭建好了。在这个环境上我们如何进行功能模块的开发呢? 1.3 功能模块开发 需求:对表tbl_book进行新增、修改、删除、根据ID查询和查询所有 步骤1:创建数据库及表 create database ssm_db character set utf8; use ssm_db; create table tbl_book(id int primary key auto_increment,type varchar(20),name varchar(50),description varchar(255) )insert into tbl_book(id,type,name,description) values (1,计算机理论,Spring实战 第五版,Spring入门经典教程深入理解Spring原理技术内幕),(2,计算机理论,Spring 5核心原理与30个类手写实践,十年沉淀之作手写Spring精华思想),(3,计算机理论,Spring 5设计模式,深入Spring源码刨析Spring源码中蕴含的10大设计模式),(4,计算机理论,Spring MVCMybatis开发从入门到项目实战,全方位解析面向Web应用的轻量级框架带你成为Spring MVC开发高手),(5,计算机理论,轻量级Java Web企业应用实战,源码级刨析Spring框架适合已掌握Java基础的读者),(6,计算机理论,Java核心技术 卷Ⅰ 基础知识(原书第11版),Core Java第11版Jolt大奖获奖作品针对Java SE9、10、11全面更新),(7,计算机理论,深入理解Java虚拟机,5个纬度全面刨析JVM,大厂面试知识点全覆盖),(8,计算机理论,Java编程思想(第4版),Java学习必读经典殿堂级著作赢得了全球程序员的广泛赞誉),(9,计算机理论,零基础学Java(全彩版),零基础自学编程的入门图书由浅入深详解Java语言的编程思想和核心技术),(10,市场营销,直播就这么做:主播高效沟通实战指南,李子柒、李佳奇、薇娅成长为网红的秘密都在书中),(11,市场营销,直播销讲实战一本通,和秋叶一起学系列网络营销书籍),(12,市场营销,直播带货:淘宝、天猫直播从新手到高手,一本教你如何玩转直播的书10堂课轻松实现带货月入3W);步骤2:编写模型类 public class Book {private Integer id;private String type;private String name;private String description;//getter...setter...toString省略 }步骤3:编写Dao接口 public interface BookDao {// Insert(insert into tbl_book values(null,#{type},#{name},#{description}))Insert(insert into tbl_book (type,name,description) values(#{type},#{name},#{description}))public void save(Book book);Update(update tbl_book set type #{type}, name #{name}, description #{description} where id #{id})public void update(Book book);Delete(delete from tbl_book where id #{id})public void delete(Integer id);Select(select * from tbl_book where id #{id})public Book getById(Integer id);Select(select * from tbl_book)public ListBook getAll(); }步骤4:编写Service接口和实现类 Transactional public interface BookService {/*** 保存* param book* return*/public boolean save(Book book);/*** 修改* param book* return*/public boolean update(Book book);/*** 按id删除* param id* return*/public boolean delete(Integer id);/*** 按id查询* param id* return*/public Book getById(Integer id);/*** 查询全部* return*/public ListBook getAll(); }Service public class BookServiceImpl implements BookService {Autowiredprivate BookDao bookDao;public boolean save(Book book) {bookDao.save(book);return true;}public boolean update(Book book) {bookDao.update(book);return true;}public boolean delete(Integer id) {bookDao.delete(id);return true;}public Book getById(Integer id) {return bookDao.getById(id);}public ListBook getAll() {return bookDao.getAll();} }说明: bookDao在Service中注入的会提示一个红线提示为什么呢? BookDao是一个接口没有实现类接口是不能创建对象的所以最终注入的应该是代理对象代理对象是由Spring的IOC容器来创建管理的IOC容器又是在Web服务器启动的时候才会创建IDEA在检测依赖关系的时候没有找到适合的类注入所以会提示错误提示但是程序运行的时候代理对象就会被创建框架会使用DI进行注入所以程序运行无影响。 如何解决上述问题? 可以不用理会因为运行是正常的 设置错误提示级别 步骤5:编写Contorller类 RestController RequestMapping(/books) public class BookController {Autowiredprivate BookService bookService;PostMappingpublic boolean save(RequestBody Book book) {return bookService.save(book);}PutMappingpublic boolean update(RequestBody Book book) {return bookService.update(book);}DeleteMapping(/{id})public boolean delete(PathVariable Integer id) {return bookService.delete(id);}GetMapping(/{id})public Book getById(PathVariable Integer id) {return bookService.getById(id);}GetMappingpublic ListBook getAll() {return bookService.getAll();} }对于图书模块的增删改查就已经完成了编写我们可以从后往前写也可以从前往后写最终只需要能把功能实现即可。 接下来我们就先把业务层的代码使用Spring整合Junit的知识点进行单元测试: 1.4 单元测试 步骤1:新建测试类 RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(classes SpringConfig.class) public class BookServiceTest {}步骤2:注入Service类 RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(classes SpringConfig.class) public class BookServiceTest {Autowiredprivate BookService bookService;}步骤3:编写测试方法 我们先来对查询进行单元测试。 RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(classes SpringConfig.class) public class BookServiceTest {Autowiredprivate BookService bookService;Testpublic void testGetById(){Book book bookService.getById(1);System.out.println(book);}Testpublic void testGetAll(){ListBook all bookService.getAll();System.out.println(all);}}根据ID查询测试的结果为: 查询所有测试的结果为: 1.5 PostMan测试 新增 http://localhost/books {type:类别测试数据,name:书名测试数据,description:描述测试数据 }修改 http://localhost/books {id:13,type:类别测试数据,name:书名测试数据,description:描述测试数据 }删除 http://localhost/books/14 查询单个 http://localhost/books/1 查询所有 http://localhost/books 2统一结果封装 2.1 表现层与前端数据传输协议定义 SSM整合以及功能模块开发完成后接下来我们在上述案例的基础上分析下有哪些问题需要我们去解决下。首先第一个问题是: 在Controller层增删改返回给前端的是boolean类型数据 在Controller层查询单个返回给前端的是对象 在Controller层查询所有返回给前端的是集合对象 目前我们就已经有三种数据类型返回给前端如果随着业务的增长我们需要返回的数据类型会越来越多。对于前端开发人员在解析数据的时候就比较凌乱了所以对于前端来说如果后台能够返回一个统一的数据结果前端在解析的时候就可以按照一种方式进行解析。开发就会变得更加简单。 所以我们就想能不能将返回结果的数据进行统一具体如何来做大体的思路为: 为了封装返回的结果数据:创建结果模型类封装数据到data属性中为了封装返回的数据是何种操作及是否操作成功:封装操作结果到code属性中操作失败后为了封装返回的错误信息:封装特殊消息到message(msg)属性中 根据分析我们可以设置统一数据返回结果类 public class Result{private Object data;private Integer code;private String msg; }注意 Result类名及类中的字段并不是固定的可以根据需要自行增减提供若干个构造方法方便操作。 2.2 表现层与前端数据传输协议实现 前面我们已经分析了如何封装返回结果数据具体在项目中该如何实现我们通过个例子来操作一把 2.2.1 环境准备 创建一个Web的Maven项目pom.xml添加SSM整合所需jar包创建对应的配置类编写Controller、Service接口、Service实现类、Dao接口和模型类resources下提供jdbc.properties配置文件 因为这个项目环境的内容和SSM整合的内容是一致的所以我们就不在把代码粘出来了大家在练习的时候可以在前面整合的例子案例环境下进行本节内容的开发。 最终创建好的项目结构如下: 2.2.2 结果封装 对于结果封装我们应该是在表现层进行处理所以我们把结果类放在controller包下当然你也可以放在domain包这个都是可以的具体如何实现结果封装具体的步骤为: 步骤1:创建Result类 public class Result {//描述统一格式中的数据private Object data;//描述统一格式中的编码用于区分操作可以简化配置0或1表示成功失败private Integer code;//描述统一格式中的消息可选属性private String msg;public Result() {}//构造方法是方便对象的创建public Result(Integer code,Object data) {this.data data;this.code code;}//构造方法是方便对象的创建public Result(Integer code, Object data, String msg) {this.data data;this.code code;this.msg msg;}//setter...getter...省略 }步骤2:定义返回码Code类 //状态码 public class Code {public static final Integer SAVE_OK 20011;public static final Integer DELETE_OK 20021;public static final Integer UPDATE_OK 20031;public static final Integer GET_OK 20041;public static final Integer SAVE_ERR 20010;public static final Integer DELETE_ERR 20020;public static final Integer UPDATE_ERR 20030;public static final Integer GET_ERR 20040; }**注意:**code类中的常量设计也不是固定的可以根据需要自行增减例如将查询再进行细分为GET_OK,GET_ALL_OK,GET_PAGE_OK等。 步骤3:修改Controller类的返回值 //统一每一个控制器方法返回值 RestController RequestMapping(/books) public class BookController {Autowiredprivate BookService bookService;PostMappingpublic Result save(RequestBody Book book) {boolean flag bookService.save(book);return new Result(flag ? Code.SAVE_OK:Code.SAVE_ERR,flag);}PutMappingpublic Result update(RequestBody Book book) {boolean flag bookService.update(book);return new Result(flag ? Code.UPDATE_OK:Code.UPDATE_ERR,flag);}DeleteMapping(/{id})public Result delete(PathVariable Integer id) {boolean flag bookService.delete(id);return new Result(flag ? Code.DELETE_OK:Code.DELETE_ERR,flag);}GetMapping(/{id})public Result getById(PathVariable Integer id) {Book book bookService.getById(id);Integer code book ! null ? Code.GET_OK : Code.GET_ERR;String msg book ! null ? : 数据查询失败请重试;return new Result(code,book,msg);}GetMappingpublic Result getAll() {ListBook bookList bookService.getAll();Integer code bookList ! null ? Code.GET_OK : Code.GET_ERR;String msg bookList ! null ? : 数据查询失败请重试;return new Result(code,bookList,msg);} }步骤4:启动服务测试 至此我们的返回结果就已经能以一种统一的格式返回给前端。前端根据返回的结果先从中获取code,根据code判断如果成功则取data属性的值如果失败则取msg中的值做提示。 3统一异常处理 3.1 问题描述 在讲解这一部分知识点之前我们先来演示个效果修改BookController类的getById方法 GetMapping(/{id}) public Result getById(PathVariable Integer id) {//手动添加一个错误信息if(id1){int i 1/0;}Book book bookService.getById(id);Integer code book ! null ? Code.GET_OK : Code.GET_ERR;String msg book ! null ? : 数据查询失败请重试;return new Result(code,book,msg); }重新启动运行项目使用PostMan发送请求当传入的id为1则会出现如下效果 前端接收到这个信息后和之前我们约定的格式不一致这个问题该如何解决? 在解决问题之前我们先来看下异常的种类及出现异常的原因: 框架内部抛出的异常因使用不合规导致数据层抛出的异常因外部服务器故障导致例如服务器访问超时业务层抛出的异常因业务逻辑书写错误导致例如遍历业务书写操作导致索引异常等表现层抛出的异常因数据收集、校验等规则导致例如不匹配的数据类型间导致异常工具类抛出的异常因工具类书写不严谨不够健壮导致例如必要释放的连接长期未释放等 看完上面这些出现异常的位置你会发现在我们开发的任何一个位置都有可能出现异常而且这些异常是不能避免的。所以我们就得将异常进行处理。 思考 各个层级均出现异常异常处理代码书写在哪一层? 所有的异常均抛出到表现层进行处理 异常的种类很多表现层如何将所有的异常都处理到呢? 异常分类 表现层处理异常每个方法中单独书写代码书写量巨大且意义不强如何解决? AOP 对于上面这些问题及解决方案SpringMVC已经为我们提供了一套解决方案: 异常处理器: 集中的、统一的处理项目中出现的异常。 3.2 异常处理器的使用 3.2.1 环境准备 创建一个Web的Maven项目pom.xml添加SSM整合所需jar包创建对应的配置类编写Controller、Service接口、Service实现类、Dao接口和模型类resources下提供jdbc.properties配置文件 内容参考前面的项目或者直接使用前面的项目进行本节内容的学习。 最终创建好的项目结构如下: 3.2.2 使用步骤 步骤1:创建异常处理器类 //RestControllerAdvice用于标识当前类为REST风格对应的异常处理器 RestControllerAdvice public class ProjectExceptionAdvice {//除了自定义的异常处理器保留对Exception类型的异常处理用于处理非预期的异常ExceptionHandler(Exception.class)public void doException(Exception ex){System.out.println(嘿嘿,异常你哪里跑)} } 确保SpringMvcConfig能够扫描到异常处理器类 步骤2:让程序抛出异常 修改BookController的getById方法添加int i 1/0. GetMapping(/{id}) public Result getById(PathVariable Integer id) {int i 1/0;Book book bookService.getById(id);Integer code book ! null ? Code.GET_OK : Code.GET_ERR;String msg book ! null ? : 数据查询失败请重试;return new Result(code,book,msg); }步骤3:运行程序测试 说明异常已经被拦截并执行了doException方法。 异常处理器类返回结果给前端 //RestControllerAdvice用于标识当前类为REST风格对应的异常处理器 RestControllerAdvice public class ProjectExceptionAdvice {//除了自定义的异常处理器保留对Exception类型的异常处理用于处理非预期的异常ExceptionHandler(Exception.class)public Result doException(Exception ex){System.out.println(嘿嘿,异常你哪里跑)return new Result(666,null,嘿嘿,异常你哪里跑);} } 启动运行程序测试 至此就算后台执行的过程中抛出异常最终也能按照我们和前端约定好的格式返回给前端。 知识点1RestControllerAdvice 名称RestControllerAdvice类型类注解位置Rest风格开发的控制器增强类定义上方作用为Rest风格开发的控制器类做增强 **说明:**此注解自带ResponseBody注解与Component注解具备对应的功能 知识点2ExceptionHandler 名称ExceptionHandler类型方法注解位置专用于异常处理的控制器方法上方作用设置指定异常的处理方案功能等同于控制器方法出现异常后终止原始控制器执行,并转入当前方法执行 **说明**此类方法可以根据处理的异常不同制作多个方法分别处理对应的异常 3.3 项目异常处理方案 3.3.1 异常分类 异常处理器我们已经能够使用了那么在咱们的项目中该如何来处理异常呢? 因为异常的种类有很多如果每一个异常都对应一个ExceptionHandler那得写多少个方法来处理各自的异常所以我们在处理异常之前需要对异常进行一个分类: 业务异常BusinessException 规范的用户行为产生的异常 用户在页面输入内容的时候未按照指定格式进行数据填写如在年龄框输入的是字符串 不规范的用户行为操作产生的异常 如用户故意传递错误数据 系统异常SystemException 项目运行过程中可预计但无法避免的异常 比如数据库或服务器宕机 其他异常Exception 编程人员未预期到的异常如:用到的文件不存在- - 将异常分类以后针对不同类型的异常要提供具体的解决方案: 3.3.2 异常解决方案 业务异常BusinessException 发送对应消息传递给用户提醒规范操作 大家常见的就是提示用户名已存在或密码格式不正确等 系统异常SystemException 发送固定消息传递给用户安抚用户 系统繁忙请稍后再试系统正在维护升级请稍后再试系统出问题请联系系统管理员等 发送特定消息给运维人员提醒维护 可以发送短信、邮箱或者是公司内部通信软件 记录日志 发消息和记录日志对用户来说是不可见的属于后台程序 其他异常Exception 发送固定消息传递给用户安抚用户发送特定消息给编程人员提醒维护纳入预期范围内 一般是程序没有考虑全比如未做非空校验等 记录日志 3.3.3 异常解决方案的具体实现 思路: 1.先通过自定义异常完成BusinessException和SystemException的定义 2.将其他异常包装成自定义异常类型 3.在异常处理器类中对不同的异常进行处理 步骤1:自定义异常类 // 自定义异常处理器用于封装异常信息对异常进行分类 public class SystemException extends RuntimeException{private Integer code;public Integer getCode() {return code;}public void setCode(Integer code) {this.code code;}public SystemException(Integer code, String message) {super(message);this.code code;}public SystemException(Integer code, String message, Throwable cause) {super(message, cause);this.code code;}}//自定义异常处理器用于封装异常信息对异常进行分类 public class BusinessException extends RuntimeException{private Integer code;public Integer getCode() {return code;}public void setCode(Integer code) {this.code code;}public BusinessException(Integer code, String message) {super(message);this.code code;}public BusinessException(Integer code, String message, Throwable cause) {super(message, cause);this.code code;}}说明: 让自定义异常类继承RuntimeException的好处是后期在抛出这两个异常的时候就不用在try…catch…或throws了自定义异常类中添加code属性的原因是为了更好的区分异常是来自哪个业务的 步骤2:将其他异常包成自定义异常 假如在BookServiceImpl的getById方法抛异常了该如何来包装呢? public Book getById(Integer id) {//模拟业务异常包装成自定义异常if(id 1){throw new BusinessException(Code.BUSINESS_ERR,请不要使用你的技术挑战我的耐性!);}//模拟系统异常将可能出现的异常进行包装转换成自定义异常try{int i 1/0;}catch (Exception e){throw new SystemException(Code.SYSTEM_TIMEOUT_ERR,服务器访问超时请重试!,e);}return bookDao.getById(id); }具体的包装方式有 方式一:try{}catch(){}在catch中重新throw我们自定义异常即可。方式二:直接throw自定义异常即可 上面为了使code看着更专业些我们在Code类中再新增需要的属性 //状态码 public class Code {public static final Integer SAVE_OK 20011;public static final Integer DELETE_OK 20021;public static final Integer UPDATE_OK 20031;public static final Integer GET_OK 20041;public static final Integer SAVE_ERR 20010;public static final Integer DELETE_ERR 20020;public static final Integer UPDATE_ERR 20030;public static final Integer GET_ERR 20040;public static final Integer SYSTEM_ERR 50001;public static final Integer SYSTEM_TIMEOUT_ERR 50002;public static final Integer SYSTEM_UNKNOW_ERR 59999;public static final Integer BUSINESS_ERR 60002; } 步骤3:处理器类中处理自定义异常 //RestControllerAdvice用于标识当前类为REST风格对应的异常处理器 RestControllerAdvice public class ProjectExceptionAdvice {//ExceptionHandler用于设置当前处理器类对应的异常类型ExceptionHandler(SystemException.class)public Result doSystemException(SystemException ex){//记录日志//发送消息给运维//发送邮件给开发人员,ex对象发送给开发人员return new Result(ex.getCode(),null,ex.getMessage());}ExceptionHandler(BusinessException.class)public Result doBusinessException(BusinessException ex){return new Result(ex.getCode(),null,ex.getMessage());}//除了自定义的异常处理器保留对Exception类型的异常处理用于处理非预期的异常ExceptionHandler(Exception.class)public Result doOtherException(Exception ex){//记录日志//发送消息给运维//发送邮件给开发人员,ex对象发送给开发人员return new Result(Code.SYSTEM_UNKNOW_ERR,null,系统繁忙请稍后再试);} }步骤4:运行程序 根据ID查询 如果传入的参数为1会报BusinessException 如果传入的是其他参数会报SystemException 对于异常我们就已经处理完成了不管后台哪一层抛出异常都会以我们与前端约定好的方式进行返回前端只需要把信息获取到根据返回的正确与否来展示不同的内容即可。 小结 以后项目中的异常处理方式为: 4前后台协议联调 4.1 环境准备 创建一个Web的Maven项目pom.xml添加SSM整合所需jar包创建对应的配置类编写Controller、Service接口、Service实现类、Dao接口和模型类resources下提供jdbc.properties配置文件 内容参考前面的项目或者直接使用前面的项目进行本节内容的学习。 最终创建好的项目结构如下: 将资料\SSM功能页面下面的静态资源拷贝到webapp下。 Masked5 / heima_springmvc_codes · GitCode 因为添加了静态资源SpringMVC会拦截所有需要在SpringConfig的配置类中将静态资源进行放行。 新建SpringMvcSupport Configuration public class SpringMvcSupport extends WebMvcConfigurationSupport {Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler(/pages/**).addResourceLocations(/pages/);registry.addResourceHandler(/css/**).addResourceLocations(/css/);registry.addResourceHandler(/js/**).addResourceLocations(/js/);registry.addResourceHandler(/plugins/**).addResourceLocations(/plugins/);} }在SpringMvcConfig中扫描SpringMvcSupport Configuration ComponentScan({com.itheima.controller,com.itheima.config}) EnableWebMvc public class SpringMvcConfig { }接下来我们就需要将所有的列表查询、新增、修改、删除等功能一个个来实现下。 4.2 列表功能 需求:页面加载完后发送异步请求到后台获取列表数据进行展示。 1.找到页面的钩子函数created() 2.created()方法中调用了this.getAll()方法 3.在getAll()方法中使用axios发送异步请求从后台获取数据 4.访问的路径为http://localhost/books 5.返回数据 返回数据res.data的内容如下: {data: [{id: 1,type: 计算机理论,name: Spring实战 第五版,description: Spring入门经典教程深入理解Spring原理技术内幕},{id: 2,type: 计算机理论,name: Spring 5核心原理与30个类手写实践,description: 十年沉淀之作手写Spring精华思想},...],code: 20041,msg: }发送方式: getAll() {//发送ajax请求axios.get(/books).then((res){this.dataList res.data.data;}); }4.3 添加功能 需求:完成图片的新增功能模块 1.找到页面上的新建按钮按钮上绑定了clickhandleCreate()方法 2.在method中找到handleCreate方法方法中打开新增面板 3.新增面板中找到确定按钮,按钮上绑定了clickhandleAdd()方法 4.在method中找到handleAdd方法 5.在方法中发送请求和数据响应成功后将新增面板关闭并重新查询数据 handleCreate打开新增面板 handleCreate() {this.dialogFormVisible true; },handleAdd方法发送异步请求并携带数据 handleAdd () {//发送ajax请求//this.formData是表单中的数据最后是一个json数据axios.post(/books,this.formData).then((res){this.dialogFormVisible false;this.getAll();}); }4.4 添加功能状态处理 基础的新增功能已经完成但是还有一些问题需要解决下: 需求:新增成功是关闭面板重新查询数据那么新增失败以后该如何处理? 1.在handlerAdd方法中根据后台返回的数据来进行不同的处理 2.如果后台返回的是成功则提示成功信息并关闭面板 3.如果后台返回的是失败则提示错误信息 (1)修改前端页面 handleAdd () {//发送ajax请求axios.post(/books,this.formData).then((res){//如果操作成功关闭弹层显示数据if(res.data.code 20011){this.dialogFormVisible false;this.$message.success(添加成功);}else if(res.data.code 20010){this.$message.error(添加失败);}else{this.$message.error(res.data.msg);}}).finally((){this.getAll();}); }(2)后台返回操作结果将Dao层的增删改方法返回值从void改成int public interface BookDao {// Insert(insert into tbl_book values(null,#{type},#{name},#{description}))Insert(insert into tbl_book (type,name,description) values(#{type},#{name},#{description}))public int save(Book book);Update(update tbl_book set type #{type}, name #{name}, description #{description} where id #{id})public int update(Book book);Delete(delete from tbl_book where id #{id})public int delete(Integer id);Select(select * from tbl_book where id #{id})public Book getById(Integer id);Select(select * from tbl_book)public ListBook getAll(); }(3)在BookServiceImpl中增删改方法根据DAO的返回值来决定返回true/false Service public class BookServiceImpl implements BookService {Autowiredprivate BookDao bookDao;public boolean save(Book book) {return bookDao.save(book) 0;}public boolean update(Book book) {return bookDao.update(book) 0;}public boolean delete(Integer id) {return bookDao.delete(id) 0;}public Book getById(Integer id) {if(id 1){throw new BusinessException(Code.BUSINESS_ERR,请不要使用你的技术挑战我的耐性!);} // //将可能出现的异常进行包装转换成自定义异常 // try{ // int i 1/0; // }catch (Exception e){ // throw new SystemException(Code.SYSTEM_TIMEOUT_ERR,服务器访问超时请重试!,e); // }return bookDao.getById(id);}public ListBook getAll() {return bookDao.getAll();} } (4)测试错误情况将图书类别长度设置超出范围即可 处理完新增后会发现新增还存在一个问题 新增成功后再次点击新增按钮会发现之前的数据还存在这个时候就需要在新增的时候将表单内容清空。 resetForm(){this.formData {}; } handleCreate() {this.dialogFormVisible true;this.resetForm(); }4.5 修改功能 需求:完成图书信息的修改功能 1.找到页面中的编辑按钮该按钮绑定了clickhandleUpdate(scope.row) 2.在method的handleUpdate方法中发送异步请求根据ID查询图书信息 3.根据后台返回的结果判断是否查询成功 ​ 如果查询成功打开修改面板回显数据如果失败提示错误信息 4.修改完成后找到修改面板的确定按钮该按钮绑定了clickhandleEdit() 5.在method的handleEdit方法中发送异步请求提交修改数据 6.根据后台返回的结果判断是否修改成功 ​ 如果成功提示错误信息关闭修改面板重新查询数据如果失败提示错误信息 scope.row代表的是当前行的行数据也就是说,scope.row就是选中行对应的json数据如下: {id: 1,type: 计算机理论,name: Spring实战 第五版,description: Spring入门经典教程深入理解Spring原理技术内幕 }修改handleUpdate方法 //弹出编辑窗口 handleUpdate(row) {// console.log(row); //row.id 查询条件//查询数据根据id查询axios.get(/books/row.id).then((res){if(res.data.code 20041){//展示弹层加载数据this.formData res.data.data;this.dialogFormVisible4Edit true;}else{this.$message.error(res.data.msg);}}); }修改handleEdit方法 handleEdit() {//发送ajax请求axios.put(/books,this.formData).then((res){//如果操作成功关闭弹层显示数据if(res.data.code 20031){this.dialogFormVisible4Edit false;this.$message.success(修改成功);}else if(res.data.code 20030){this.$message.error(修改失败);}else{this.$message.error(res.data.msg);}}).finally((){this.getAll();}); }至此修改功能就已经完成。 4.6 删除功能 需求:完成页面的删除功能。 1.找到页面的删除按钮按钮上绑定了clickhandleDelete(scope.row) 2.method的handleDelete方法弹出提示框 3.用户点击取消,提示操作已经被取消。 4.用户点击确定发送异步请求并携带需要删除数据的主键ID 5.根据后台返回结果做不同的操作 ​ 如果返回成功提示成功信息并重新查询数据 ​ 如果返回失败提示错误信息并重新查询数据 修改handleDelete方法 handleDelete(row) {//1.弹出提示框this.$confirm(此操作永久删除当前数据是否继续,提示,{type:info}).then((){//2.做删除业务axios.delete(/books/row.id).then((res){if(res.data.code 20021){this.$message.success(删除成功);}else{this.$message.error(删除失败);}}).finally((){this.getAll();});}).catch((){//3.取消删除this.$message.info(取消删除操作);}); }接下来下面是一个完整页面 !DOCTYPE htmlhtmlhead!-- 页面meta --meta charsetutf-8meta http-equivX-UA-Compatible contentIEedgetitleSpringMVC案例/titlemeta contentwidthdevice-width,initial-scale1,maximum-scale1,user-scalableno nameviewport!-- 引入样式 --link relstylesheet href../plugins/elementui/index.csslink relstylesheet href../plugins/font-awesome/css/font-awesome.min.csslink relstylesheet href../css/style.css/headbody classhold-transitiondiv idappdiv classcontent-headerh1图书管理/h1/divdiv classapp-containerdiv classboxdiv classfilter-containerel-input placeholder图书名称 v-modelpagination.queryString stylewidth: 200px; classfilter-item/el-inputel-button clickgetAll() classdalfBut查询/el-buttonel-button typeprimary classbutT clickhandleCreate()新建/el-button/divel-table sizesmall current-row-keyid :datadataList stripe highlight-current-rowel-table-column typeindex aligncenter label序号/el-table-columnel-table-column proptype label图书类别 aligncenter/el-table-columnel-table-column propname label图书名称 aligncenter/el-table-columnel-table-column propdescription label描述 aligncenter/el-table-columnel-table-column label操作 aligncentertemplate slot-scopescopeel-button typeprimary sizemini clickhandleUpdate(scope.row)编辑/el-buttonel-button typedanger sizemini clickhandleDelete(scope.row)删除/el-button/template/el-table-column/el-table!-- 新增标签弹层 --div classadd-formel-dialog title新增图书 :visible.syncdialogFormVisibleel-form refdataAddForm :modelformData :rulesrules label-positionright label-width100pxel-rowel-col :span12el-form-item label图书类别 proptypeel-input v-modelformData.type//el-form-item/el-colel-col :span12el-form-item label图书名称 propnameel-input v-modelformData.name//el-form-item/el-col/el-rowel-rowel-col :span24el-form-item label描述el-input v-modelformData.description typetextarea/el-input/el-form-item/el-col/el-row/el-formdiv slotfooter classdialog-footerel-button clickdialogFormVisible false取消/el-buttonel-button typeprimary clickhandleAdd()确定/el-button/div/el-dialog/div!-- 编辑标签弹层 --div classadd-formel-dialog title编辑检查项 :visible.syncdialogFormVisible4Editel-form refdataEditForm :modelformData :rulesrules label-positionright label-width100pxel-rowel-col :span12el-form-item label图书类别 proptypeel-input v-modelformData.type//el-form-item/el-colel-col :span12el-form-item label图书名称 propnameel-input v-modelformData.name//el-form-item/el-col/el-rowel-rowel-col :span24el-form-item label描述el-input v-modelformData.description typetextarea/el-input/el-form-item/el-col/el-row/el-formdiv slotfooter classdialog-footerel-button clickdialogFormVisible4Edit false取消/el-buttonel-button typeprimary clickhandleEdit()确定/el-button/div/el-dialog/div/div/div/div/body!-- 引入组件库 --script src../js/vue.js/scriptscript src../plugins/elementui/index.js/scriptscript typetext/javascript src../js/jquery.min.js/scriptscript src../js/axios-0.18.0.js/scriptscriptvar vue new Vue({el: #app,data:{pagination: {},dataList: [],//当前页要展示的列表数据formData: {},//表单数据dialogFormVisible: false,//控制表单是否可见dialogFormVisible4Edit:false,//编辑表单是否可见rules: {//校验规则type: [{ required: true, message: 图书类别为必填项, trigger: blur }],name: [{ required: true, message: 图书名称为必填项, trigger: blur }]}},//钩子函数VUE对象初始化完成后自动执行created() {this.getAll();},methods: {//列表getAll() {//发送ajax请求axios.get(/books).then((res){this.dataList res.data.data;});},//弹出添加窗口handleCreate() {this.dialogFormVisible true;this.resetForm();},//重置表单resetForm() {this.formData {};},//添加handleAdd () {//发送ajax请求axios.post(/books,this.formData).then((res){console.log(res.data);//如果操作成功关闭弹层显示数据if(res.data.code 20011){this.dialogFormVisible false;this.$message.success(添加成功);}else if(res.data.code 20010){this.$message.error(添加失败);}else{this.$message.error(res.data.msg);}}).finally((){this.getAll();});},//弹出编辑窗口handleUpdate(row) {// console.log(row); //row.id 查询条件//查询数据根据id查询axios.get(/books/row.id).then((res){// console.log(res.data.data);if(res.data.code 20041){//展示弹层加载数据this.formData res.data.data;this.dialogFormVisible4Edit true;}else{this.$message.error(res.data.msg);}});},//编辑handleEdit() {//发送ajax请求axios.put(/books,this.formData).then((res){//如果操作成功关闭弹层显示数据if(res.data.code 20031){this.dialogFormVisible4Edit false;this.$message.success(修改成功);}else if(res.data.code 20030){this.$message.error(修改失败);}else{this.$message.error(res.data.msg);}}).finally((){this.getAll();});},// 删除handleDelete(row) {//1.弹出提示框this.$confirm(此操作永久删除当前数据是否继续,提示,{type:info}).then((){//2.做删除业务axios.delete(/books/row.id).then((res){if(res.data.code 20021){this.$message.success(删除成功);}else{this.$message.error(删除失败);}}).finally((){this.getAll();});}).catch((){//3.取消删除this.$message.info(取消删除操作);});}}})/script/html
文章转载自:
http://www.morning.zbqsg.cn.gov.cn.zbqsg.cn
http://www.morning.ruifund.com.gov.cn.ruifund.com
http://www.morning.jfqqs.cn.gov.cn.jfqqs.cn
http://www.morning.rggky.cn.gov.cn.rggky.cn
http://www.morning.clhyj.cn.gov.cn.clhyj.cn
http://www.morning.jhwwr.cn.gov.cn.jhwwr.cn
http://www.morning.tjjkn.cn.gov.cn.tjjkn.cn
http://www.morning.wwkft.cn.gov.cn.wwkft.cn
http://www.morning.hxwrs.cn.gov.cn.hxwrs.cn
http://www.morning.wjzzh.cn.gov.cn.wjzzh.cn
http://www.morning.tssmk.cn.gov.cn.tssmk.cn
http://www.morning.xrftt.cn.gov.cn.xrftt.cn
http://www.morning.bhdyr.cn.gov.cn.bhdyr.cn
http://www.morning.sfnjr.cn.gov.cn.sfnjr.cn
http://www.morning.hxpsp.cn.gov.cn.hxpsp.cn
http://www.morning.qghjc.cn.gov.cn.qghjc.cn
http://www.morning.zwdrz.cn.gov.cn.zwdrz.cn
http://www.morning.xjmyq.com.gov.cn.xjmyq.com
http://www.morning.fxkgp.cn.gov.cn.fxkgp.cn
http://www.morning.lfcnj.cn.gov.cn.lfcnj.cn
http://www.morning.hnkkf.cn.gov.cn.hnkkf.cn
http://www.morning.51meihou.cn.gov.cn.51meihou.cn
http://www.morning.wynnb.cn.gov.cn.wynnb.cn
http://www.morning.nlkm.cn.gov.cn.nlkm.cn
http://www.morning.pwdrc.cn.gov.cn.pwdrc.cn
http://www.morning.mehrim.com.gov.cn.mehrim.com
http://www.morning.hgbzc.cn.gov.cn.hgbzc.cn
http://www.morning.ydrfl.cn.gov.cn.ydrfl.cn
http://www.morning.xnqjs.cn.gov.cn.xnqjs.cn
http://www.morning.nnwmd.cn.gov.cn.nnwmd.cn
http://www.morning.pmjw.cn.gov.cn.pmjw.cn
http://www.morning.hqbk.cn.gov.cn.hqbk.cn
http://www.morning.ncqzb.cn.gov.cn.ncqzb.cn
http://www.morning.wdpbq.cn.gov.cn.wdpbq.cn
http://www.morning.piekr.com.gov.cn.piekr.com
http://www.morning.mkfhx.cn.gov.cn.mkfhx.cn
http://www.morning.lbqt.cn.gov.cn.lbqt.cn
http://www.morning.qnzgr.cn.gov.cn.qnzgr.cn
http://www.morning.ghrlx.cn.gov.cn.ghrlx.cn
http://www.morning.dnls.cn.gov.cn.dnls.cn
http://www.morning.clgbb.cn.gov.cn.clgbb.cn
http://www.morning.yfddl.cn.gov.cn.yfddl.cn
http://www.morning.qlry.cn.gov.cn.qlry.cn
http://www.morning.mnsmb.cn.gov.cn.mnsmb.cn
http://www.morning.hbkkc.cn.gov.cn.hbkkc.cn
http://www.morning.dkslm.cn.gov.cn.dkslm.cn
http://www.morning.zlmbc.cn.gov.cn.zlmbc.cn
http://www.morning.ygqjn.cn.gov.cn.ygqjn.cn
http://www.morning.mfmbn.cn.gov.cn.mfmbn.cn
http://www.morning.mngh.cn.gov.cn.mngh.cn
http://www.morning.rqxch.cn.gov.cn.rqxch.cn
http://www.morning.znrgq.cn.gov.cn.znrgq.cn
http://www.morning.dpwcl.cn.gov.cn.dpwcl.cn
http://www.morning.bswhr.cn.gov.cn.bswhr.cn
http://www.morning.fslrx.cn.gov.cn.fslrx.cn
http://www.morning.rfdqr.cn.gov.cn.rfdqr.cn
http://www.morning.fnzbx.cn.gov.cn.fnzbx.cn
http://www.morning.cqrenli.com.gov.cn.cqrenli.com
http://www.morning.fqpgf.cn.gov.cn.fqpgf.cn
http://www.morning.gwmjy.cn.gov.cn.gwmjy.cn
http://www.morning.yrmpr.cn.gov.cn.yrmpr.cn
http://www.morning.zcnfm.cn.gov.cn.zcnfm.cn
http://www.morning.ggtgl.cn.gov.cn.ggtgl.cn
http://www.morning.jfqqs.cn.gov.cn.jfqqs.cn
http://www.morning.xdlwm.cn.gov.cn.xdlwm.cn
http://www.morning.xclgf.cn.gov.cn.xclgf.cn
http://www.morning.cnqff.cn.gov.cn.cnqff.cn
http://www.morning.fkwp.cn.gov.cn.fkwp.cn
http://www.morning.kmcby.cn.gov.cn.kmcby.cn
http://www.morning.fbjqq.cn.gov.cn.fbjqq.cn
http://www.morning.zfyr.cn.gov.cn.zfyr.cn
http://www.morning.rnrfs.cn.gov.cn.rnrfs.cn
http://www.morning.bsbcp.cn.gov.cn.bsbcp.cn
http://www.morning.rqjxc.cn.gov.cn.rqjxc.cn
http://www.morning.gxfzrb.com.gov.cn.gxfzrb.com
http://www.morning.zpstm.cn.gov.cn.zpstm.cn
http://www.morning.zfrs.cn.gov.cn.zfrs.cn
http://www.morning.rqkck.cn.gov.cn.rqkck.cn
http://www.morning.xgbq.cn.gov.cn.xgbq.cn
http://www.morning.qbfqb.cn.gov.cn.qbfqb.cn
http://www.tj-hxxt.cn/news/248412.html

相关文章:

  • 建设网站请示宣传广州建站模板搭建
  • 博物馆建设网站的作用WordPress通讯目录
  • 自己建私人网站做外贸不好做石家庄官网制作
  • 中山网站建设解决方案网站建设如何交税
  • 赣州市开发区建设局网站海口网约车
  • 分销网站怎么做大连金州高级中学
  • wap企业网站模板h5网站开发方案
  • 网站默认主页名桂城网站制作
  • 信阳市住房和城乡建设局网站西安专业网站建设价格
  • 某运动服网站建设规划书wordpress id从0开始
  • 网站开发嫌工时长北京企业网站模板建站怎么用
  • 外包网站开发安全吗甘肃建设厅官方网站项目负责人
  • 软件开发做网站爱站挖词
  • 设计网站的步骤wordpress怎么换主题
  • 网站前端建设90设计供稿平台任务
  • 东城做企业网站多少钱选择合肥网站建设
  • 便宜的网站空间网站后台内容管理系统
  • 湘潭做网站 搜搜磐石网络制作公司网站哪个好
  • 网站做qq发送链接流感吃什么药最好
  • 做网站推广的公司未备案域名
  • 云酒店网站建设米各庄网站建设
  • 网站开发工具 下载手机百度安装下载
  • 中国智慧城市建设门户网站市北区网站建设
  • 网站开发公司怎么查询电脑制作视频的软件有哪些
  • 视频网站开发方法淘宝优惠券网站怎么做的
  • 网站弹出一张图怎么做代码wordpress 邀请码
  • 阿里云怎么做淘宝客网站开发板原理图
  • 网站测速潍坊网站建设公司排名
  • 哪个网站上可以做外贸郴州seo推广
  • 爱做网站yeele电商网站开发 报价