热门框架学习笔记-创新互联
1-Spring框架
1. Spring框架
文章名称:热门框架学习笔记-创新互联
文章链接:http://scyanting.com/article/hcjgc.html
- Spring框架优势:简化开发、框架整合;
- Spring架构图
- Spring的学习内容:Spring的IOC/DI、Spring的AOP、AOP的具体应用与事务管理、IOC/DI的具体应用与整合Mybatis。
- IOC:控制反转;IOC容器;Bean;DI依赖注入。
- bean的基础配置
- bean的实例化:
- bean的创建:构造方法
- Spring的IOC实例化对象的三种方式
- 构造方法(常用)
- 静态工厂(了解)
- 实例工厂(了解)
- FactoryBean(实用)
- bean的生命周期
- 对于引用数据类型:
- 对于简单数据类型:
3.2 构造器注入- 引用数据类型
- 简单数据类型
3.3 自动配置- 将
标签删除; - 在
标签中添加 autowire 属性。 - 分类:按照类型注入、按照名称注入
在
或
标签内部写array
、list
、set
、map
、props
标签。
管理第三方bean步骤:
- 添加依赖;
- 配置第三方 bean,通过 setter 注入为第三方 bean 注入必要的参数;
- 从 IOC 容器获取对应的 bean 对象使用。
- 开启 context 命名空间:
- 加载 properties 配置文件
- 在applicationContext.xml引入properties配置文件中的值
${key}
5. 核心容器- 容器创建的两种方式
- ClassPathXmlApplicationContext[掌握]
- FileSystemXmlApplicationContext[知道即可]
- 获取 Bean 的三种方式
- getBean(“名称”):需要类型转换
- getBean(“名称”,类型.class):多了一个参数
- getBean(类型.class):容器中不能有多个该类的bean对象
- 容器类层次结构:最顶层的父接口 BeanFactory
- BeanFactory:
- 使用BeanFactory创建的容器是延迟加载
- 使用ApplicationContext创建的容器是立即加载
- 具体BeanFactory如何创建只需要了解即可。
- bean 相关:
- 依赖注入相关
- 创建配置类 SpringConfig;
- 在配置类上添加
@Configuration
注解,将其标识为一个配置类,替换applicationContext.xml
; - 在配置类上添加包扫描注解
@ComponentScan
替换
@Configuration
@ComponentScan("com.itheima")
public class SpringConfig {}
6.2 注解开发bean作用范围与生命周期管理@Scope
:设置该类创建对象的作用范围,可用于设置创建出的bean是否为单例对象@PostConstruct
:设置该方法为初始化方法@PreDestroy
:设置该方法为销毁方法
注解开发只提供了自动装配的注解实现。
@Autowired
:为引用类型属性设置值,自动装配;@Qualifier
:为引用类型属性指定注入的beanId,即可以在多个实现类中指定注入Bean的 Id;@Value
:为 基本数据类型 或 字符串类型 属性设置值;@PropertySource
:加载properties文件中的属性值,属性值可以使用@Value("${key}")
注入。
- 定义外部配置类管理第三方bean
- 定义获取第三方bean的方法,并通过
@Bean
注解将方法的返回值制作为Spring管理的一个bean对象 @Bean
:设置该方法的返回值作为spring管理的bean- 在Spring配置类中使用
@Import({JdbcConfig.class})
引入第三方bean @Import
:导入配置类
- 简单数据类型:在类中提供属性,用
@Value
注解引入值,在第三方bean的方法中传递参数进去即可; - 引用数据类型:让 Spring 扫描管理到需要的bean,为第三方bean定义方法设置形参即可,容器会根据类型自动装配对象。
要整合的内容:
第一件事是:Spring要管理MyBatis中的SqlSessionFactory
第二件事是:Spring要管理Mapper接口的扫描
整合步骤:
- 项目中导入整合需要的jar包:spring-jdbc、mybatis-spring
- 创建Spring的主配置类
- 创建数据源的配置类 JdbcConfig ,配置 DruidDataSource
- 主配置类中读properties并引入数据源配置类
- 创建Mybatis配置类并配置SqlSessionFactory,类里面定义两个Bean,一个用于产生SqlSessionFactory对象;一个返回MapperScannerConfigurer对象,用来处理原始配置文件中的mappers相关配置,加载数据层的Mapper接口类
- SqlSessionFactoryBean封装SqlSessionFactory需要的环境信息
- MapperScannerConfigurer加载Dao接口,创建代理对象保存到IOC容器中
- SqlSessionFactoryBean封装SqlSessionFactory需要的环境信息
- 主配置类中引入Mybatis配置类
- 编写运行类运行
- 引入依赖:junit、spring-test
- 在test\java下创建一个测试类,添加两个注解:
- 设置类运行器:
@RunWith(SpringJUnit4ClassRunner.class)
- 设置Spring环境对应的配置类:
@ContextConfiguration(classes = {SpringConfig.class}) //加载配置类
类里面自动装配注入 service bean,正常写 @Test 运行测试即可。
- 设置类运行器:
- 添加依赖:
spring-context
、aspectjweaver
- 定义接口与实现类、Spring的配置类、App运行类
- 定义通知类和通知
- 定义切入点
@Pointcut("execution(void com.itheima.dao.BookDao.update())")
private void pt(){}
- 制作切面:通知方法上添加注解
@Before("pt()")
- 将通知类配给容器并标识其为切面类
@Component
、@Aspect
- 开启注解格式AOP功能:在Spring配置类上添加注解
@EnableAspectJAutoProxy
- 运行程序
- 概念:AOP(Aspect Oriented Programming)面向切面编程,一种编程范式
- 作用:在不惊动原始设计的基础上为方法进行功能增强
- 核心概念:
- 代理(Proxy):SpringAOP的核心本质是采用代理模式实现的
- 连接点(JoinPoint):在SpringAOP中,理解为任意方法的执行
- 切入点(Pointcut):匹配连接点的式子,也是具有共性功能的方法描述
- 通知(Advice):若干个方法的共性功能,在切入点处执行,最终体现为一个方法
- 切面(Aspect):描述通知与切入点的对应关系
- 目标对象(Target):被代理的原始对象称为目标对象
- 切入点表达式标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数)异常名)
execution(* com.itheima.service.*Service.*(..))
- 切入点表达式描述通配符:
- 作用:用于快速描述,范围描述
- *:匹配任意符号(常用)
- … :匹配多个连续的任意符号(常用)
- +:匹配子类类型
- 前置通知
- 后置通知
- 环绕通知(重点)
- 返回后通知
- 抛出异常后通知
9.5 通知中获取参数- 获取切入点方法的参数,所有的通知类型都可以获取参数
- JoinPoint:适用于前置、后置、返回后、抛出异常后通知
- ProceedingJoinPoint:适用于环绕通知
- 获取切入点方法返回值,前置和抛出异常后通知是没有返回值,后置通知可有可无,所以不做研究
- 返回后通知
- 环绕通知
- 获取切入点方法运行异常信息,前置和返回后通知是不会有,后置通知可有可无,所以不做研究
- 抛出异常后通知
- 环绕通知
- AOP 配置
@EnableAspectJAutoProxy
:配置类定义上方,开启注解格式AOP功能@Aspect
:切面类定义上方,设置当前类为AOP切面类@Pointcut
:切入点方法定义上方,设置切入点方法@Before
:通知方法定义上方,设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前运行
- 通知类型总结
@Before
@After
:通知方法定义上方,设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法后运行@AfterReturning
:通知方法定义上方,设置当前通知方法与切入点之间绑定关系,当前通知方法在原始切入点方法正常执行完毕后执行@AfterThrowing
:通知方法定义上方,设置当前通知方法与切入点之间绑定关系,当前通知方法在原始切入点方法运行抛出异常后执行@Around
:通知方法定义上方,设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前后运行,对原始方法的调用通过pjp.proceed();
实现
- 在需要被事务管理的方法上添加注解
@Transactional
,可以写在接口类上、接口方法上、实现类上和实现类方法上,建议写在实现类或实现类的方法上 - 在JdbcConfig类中配置事务管理器,配置第三方 bean :DataSourceTransactionManager
- 开启事务注解:在SpringConfig的配置类中开启
@EnableTransactionManagement
- 运行测试
- 知识点:
@EnableTransactionManagement
:配置类定义上方,设置当前Spring环境中开启注解式事务支持;@Transactional
:业务层接口上方、业务层实现类上方、业务方法上方,为当前业务层方法添加事务(如果设置在类或接口上方则类或接口中所有方法均添加事务)
- 事务管理员:发起事务方,在Spring中通常指代业务层开启事务的方法
- 事务协调员:加入事务方,在Spring中通常指代数据层方法,也可以是业务层方法
- 事务配置,作为属性在
@Transactional
注解的参数上进行设置 - 事务传播行为:转账业务追加日志案例
- 创建日志表
- 添加LogDao接口
- 添加LogService接口与实现类,实现类方法配置
@Transactional
- 在转账的业务中添加记录日志
- 结果运行:正常运行时,日志表中日志记录成功;出现异常时,日志表未添加数据——日志的记录与转账操作隶属同一个事务,同成功同失败
- 需要效果:无论转账操作是否成功,日志必须保留
- 事务传播行为:事务协调员对事务管理员所携带事务的处理态度。
- 解决:修改logService改变事务的传播行为,在记录日志的业务方法上设置事务属性:传播行为设置为当前操作需要新事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(String out,String in,Double money ) {logDao.log("转账操作由"+out+"到"+in+",金额:"+money);
}
2-SpringMVC
1. SpringMVC概述与入门案例
1.1 SpringMVC- SpringMVC是一种基于Java实现MVC模型的轻量级Web框架
- 优点
- 使用简单、开发便捷(相比于Servlet)
- 灵活性强
- 负责功能
- controller如何接收请求和数据
- 如何将请求和数据转发给业务层
- 如何将响应数据转换成json发回到前端
- 创建 Maven 项目,不使用骨架,设置打包方式为 war 包——定义为 web 项目
- 补全目录结构
- 导入jar包:javax.servlet-api、spring-webmvc、tomcat7-maven-plugin插件
- 创建配置类
SpringMvcConfig
,添加注解:
@Configuration
@ComponentScan("com.itheima.controller")
- 创建Controller类,添加
@Controller
注解,定义方法添加@RequestMapping("/save")
注解设置当前控制器方法请求访问路径,添加注解@ResponseBody
设置返回数据为json - 使用配置类替换web.xml:将web.xml删除,换成ServletContainersInitConfig
public class ServletContainerInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer{@Override
protected Class>[] getRootConfigClasses() {return new Class[]{};
}
@Override
protected Class>[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};
}
@Override
protected String[] getServletMappings() {return new String[]{"/"};
}
}
- 配置Tomcat环境
- 启动运行项目
- Spring加载的bean设定扫描范围为精准范围,例如service包、dao包等
- Spring加载的bean设定扫描范围为com.itheima,排除掉controller包中的bean
@Configuration
@ComponentScan(value="com.itheima",
excludeFilters=@ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
) p
ublic class SpringConfig {}
- 方式三:不区分Spring与SpringMVC的环境,加载到同一个环境中[了解即可]
@Controller
:SpringMVC控制器类定义上方,设定SpringMVC的核心控制器bean;@RequestMapping
:SpringMVC控制器类或方法定义上方,设置当前控制器方法请求访问路径;@ResponseBody
:SpringMVC控制器类或方法定义上方,设置当前控制器方法响应内容为当前返回值,无需解析@ComponentScan
:类定义上方,设置spring配置类扫描路径,用于加载使用注解格式定义的bean;excludeFilters:排除扫描路径中加载的bean,需要指定类别(type)和具体项(classes)、includeFilters:加载指定的bean,需要指定类别(type)和具体项(classes)
- 设置请求映射路径:当有多个 Controller 时,可能具有相同的方法名,此时可以通过在 Controller 类上面添加
@@RequestMapping("/book")
、@RequestMapping("/user")
进行区分 - GET请求中文乱码:修改pom.xml中 tomcat 插件配置来解决GET请求中文乱码问题
- POST请求中文乱码:在 ServletContainersInitConfig 中配置过滤器
@Override
protected Filter[] getServletFilters() {CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[]{filter};
}
2.2 五种类型参数传递- 普通参数:
- 地址参数名与形参变量名相同:定义形参即可接收参数
- 形参与地址参数名不一致:写上
@RequestParam
注解
- POJO数据类型:请求参数与形参对象中的属性对应即可完成参数传递
- 嵌套POJO类型参数:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数
- 数组类型参数:同名请求参数可以直接映射到对应名称的形参数组对象中
- 集合类型参数:同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据
- 知识点
@RequestParam
:SpringMVC控制器方法形参定义前面,绑定请求参数与处理器方法形参间的关系
- SpringMVC接收JSON数据的实现步骤为:
- 导入jackson包,SpringMVC默认使用的是jackson来处理json的转换
- 使用PostMan发送JSON数据:JSON普通数组、JSON对象数据、JSON对象数组
- 开启SpringMVC注解驱动,在配置类上添加
@EnableWebMvc
注解 - Controller方法的参数前添加
@RequestBody
注解
- 知识点:
@EnableWebMvc
:SpringMVC配置类定义上方,开启SpringMVC多项辅助功能@RequestBody
:SpringMVC控制器方法形参定义前面,将请求中请求体所包含的数据传递给请求参数——用于接收 json 数据@RequestParam
:用于接收url地址传参,表单传参
@DateTimeFormat
:SpringMVC控制器方法形参前面,设定日期时间型数据格式- 参数传递内部原理:SpringMVC 做了类型转换,SpringMVC中提供了很多类型转换接口和实现类。
- 响应页面(了解):将页面名称返回回去,方法返回类型为 String,此处不能添加
@ResponseBody
,如果加了该注解,会直接将页面名称 page.jsp 当字符串返回前端 - 返回文本数据(了解):添加
@ResponseBody
注解,文本数据return回去即可 - 响应 json 数据:依赖
@ResponseBody
注解和@EnableWebMvc
注解,将实体类对象或集合对象 return 即可 @ResponseBody
:SpringMVC控制器方法定义上方和控制类上,设置当前控制器返回值作为响应体,写在类上,该类的所有方法都有该注解功能。方法上有@ReponseBody
注解后- 方法的返回值为字符串,会将其作为文本内容直接响应给前端
- 方法的返回值为对象,会将对象转换成JSON响应给前端
按照REST风格访问资源时使用行为动作区分对资源进行了何种操作
- http://localhost/users 查询全部用户信息 GET(查询)
- http://localhost/users/1 查询指定用户信息 GET(查询)
- http://localhost/users 添加用户信息 POST(新增/保存)
- http://localhost/users 修改用户信息 PUT(修改/更新)
- http://localhost/users/1 删除用户信息 DELETE(删除)
按照不同的请求方式代表不同的操作类型:
- 发送GET请求是用来做查询
- 发送POST请求是用来做新增
- 发送PUT请求是用来做修改
- 发送DELETE请求是用来做删除
- 将
@RequestMapping
提到类上面,用来定义所有方法共同的访问路径/books
、/user
- 使用
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
设置当前控制器方法请求访问路径与请求动作 - 使用
@RestController
注解替换@Controller
与@ResponseBody
注解写在 Controller 类上方 - 使用
@PathVariable
解决方法形参的名称和路径{}中的值不一致问题与多个参数的区分问题 - 知识点:
@PathVariable
:SpringMVC控制器方法形参定义前面,绑定路径参数与处理器方法形参间的关系,要求路径参数名与形参名一一对应@RestController
:基于SpringMVC的RESTful开发控制器类定义上方,设置当前控制器类为RESTful风格,等同于@Controller
与@ResponseBody
两个注解组合功能@GetMapping @PostMapping @PutMapping @DeleteMapping
:基于SpringMVC的RESTful开发控制器方法定义上方,设置当前控制器方法请求访问路径与请求动作,每种对应一个请求动作,例如@GetMapping
对应GET请求
- 问题:静态页面存放在项目的webapp目录下,访问pages目录下的books.html,SpringMVC拦截了静态资源,根据/pages/books.html去controller找对应的方法,找不到所以会报404的错误。
- 解决:在 config 包下定义 SpringMvcSupport 类将静态资源进行放行
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {//设置静态资源访问过滤,当前类需要设置为配置类,并被扫描加载
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry){//当访问/pages/????时候,从/pages目录下查找内容
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
}
}
同时注意让 SpringMvcConfig 配置类扫描到 config 包中的 SpringMvcSupport 类。
4. SSM 整合流程:
- 创建Maven的web项目,设置打包方式,补全目录
- 添加 SSM 需要的依赖:
- spring:
spring-jdbc
、spring-test
- 数据库:
mybatis
、mysql-connector-java
、druid
、mybatis-spring
- 单元测试:
junit
- servlet:
spring-webmvc
、javax.servlet-api
、jackson-databind
- tomcat:
tomcat7-maven-plugin
- spring:
- 创建项目包结构
- 创建SpringConfig配置类
@Configuration
@ComponentScan({"com.itheima.service"})
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MyBatisConfig.class})
@EnableTransactionManagement
public class SpringConfig {}
- 创建JdbcConfig配置类,包含数据库连接池 bean 和 事务管理的 bean
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;
@Bean
public DataSource dataSource(){DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){DataSourceTransactionManager dstm = new DataSourceTransactionManager();
dstm.setDataSource(dataSource);
return dstm;
}
}
- 创建MybatisConfig配置类,包含 SqlSessionFactoryBean 和 mapper映射文件的bean
public class MyBatisConfig {@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setTypeAliasesPackage("com.itheima.domain");
return sqlSessionFactoryBean;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("com.itheima.dao");
return mapperScannerConfigurer;
}
}
- 创建jdbc.properties
- 创建SpringMVC配置类
@Configuration
@ComponentScan({"com.itheima.controller", "com.itheima.config"})
@EnableWebMvc
public class SpringMvcConfig {}
- 创建Web项目入口配置类
// Web 项目入口配置类
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {// 加载 Spring 配置类
@Override
protected Class>[] getRootConfigClasses() {return new Class[]{SpringConfig.class};
}
// 加载 SpringMvc 配置类
@Override
protected Class>[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};
}
// 配置 SpringMVC 请求地址拦截规则
@Override
protected String[] getServletMappings() {return new String[]{"/"};
}
// 设置 post 请求中文乱码过滤器
@Override
protected Filter[] getServletFilters() {CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("utf-8");
return new Filter[]{filter};
}
}
- 创建数据库及表并初始化数据
- 编写模型类:domain 包下 Book 类
- 编写Dao接口:用注解编写 sql 语句:增、删、改、按 id 查询、查询所有。查询会返回查询的对象或者null,而正常增删改是没有返回值的,此时不能判断到底有没有增删改成功:将增删改的返回值改为 int ,会返回操作影响的行数,当成功操作,返回值 >0 再在 service 层返回 true 表示操作成功;否则返回 false 表示操作失败。
- 编写Service接口和实现类
- 编写Contorller类,使用 REST 风格
@RestController
@RequestMapping("/books")
public class BookController {@Autowired
private BookService bookService;
@PostMapping
public Result save(@RequestBody Book book){boolean flag = bookService.save(book);
return new Result(flag ? Code.SAVE_OK : Code.SAVE_ERR, flag);
}
@PutMapping
public 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);
}
@GetMapping
public Result getAll(){Listlist = bookService.getAll();
Integer code = list != null ? Code.GET_OK : Code.GET_ERR;
String msg = list != null ? "" : "数据查询失败,请重试!";
return new Result(code,list,msg);
}
}
- 单元测试 Service 类
- PostMan测试各个功能
- 为了封装返回的结果数据:创建结果模型类,封装数据到data属性中
- 为了封装返回的数据是何种操作及是否操作成功:封装操作结果到code属性中
- 操作失败后为了封装返回的错误信息:封装特殊消息到message(msg)属性中
- 在 controller 包下创建 Result 类:三个属性、构造方法、setter、getter
- 在 controller 包下定义返回码 Code 类:各种操作成功、失败编码(自己定义)
- 修改Controller类的返回值,让所有方法的返回值类型都是 Result ,在 return 语句中将封装好的 Result 对象返回回去
目的:出现异常的时候,也会返回一个 Result 标准结果对象回去,在 msg 属性中添加异常信息。
6.1 异常分类- 业务异常(BusinessException):规范的用户行为产生的异常如输入错数据类型、不规范的用户行为操作产生的异常如故意传递错误的请求数据
- 解决:发送对应消息传递给用户,提醒规范操作
- 系统异常(SystemException):项目运行过程中可预计但无法避免的异常如系统宕机
- 解决:发送固定消息传递给用户,安抚用户;发送特定消息给运维人员,提醒维护;记录日志
- 其他异常(Exception):编程人员未预期到的异常如用到的文件不存在
- 解决:发送固定消息传递给用户,安抚用户;发送特定消息给编程人员,提醒维护(纳入预期范围内);记录日志
- 在 exception 包下定义自定义异常类,封装业务异常和系统异常
// 自定义业务异常类
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;
}
}
// 自定义系统异常类
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;
}
}
- 将其他异常包成自定义异常:即在代码处理中遇到可以预测到的异常情况时,抛出我们自定义的异常
- try{}catch(){}在catch中重新throw我们自定义异常
- 直接throw自定义异常即可
@Override
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);
}
- 在 controller 包下定义异常处理器类 ProjectExceptionAdvice,在出现异常的时候依然正常返回标准的 Result 对象给前端,同时要确保SpringMvcConfig能够扫描到异常处理器类
@RestControllerAdvice
public class ProjectExceptionAdvice {// @ExceptionHandler 用于设置当前处理器类对应的异常类型
@ExceptionHandler(SystemException.class)
public Result doSystemException(SystemException ex){//其他处理:记录日志、发送消息给运维、发送邮件给开发人员
// 接替 controller 返回结果
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){//其他处理
return new Result(Code.SYSTEM_UNKNOW_ERR, null, "系统繁忙,请稍后再试");
}
}
6.3 知识点- 异常处理器:集中的、统一的处理项目中出现的异常
@RestControllerAdvice
:Rest风格开发的控制器增强类定义上方,为Rest风格开发的控制器类做增强——此注解自带@ResponseBody
注解与@Component
注解,具备对应的功能@ExceptionHandler
:专用于异常处理的控制器方法上方,设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原始控制器执行,并转入当前方法执行
- 拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行
- 作用:
- 在指定的方法调用前后执行预先设定的代码
- 阻止原始方法的执行
- 总结:拦截器就是用来做增强
- 拦截器和过滤器:
- 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
- 拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强
- 在 controller 包下添加 interceptor 包,创建拦截器类 ProjectInterceptor,让类实现 HandlerInterceptor 接口,重写接口中的三个方法;拦截器类要被SpringMVC容器扫描到
@Component
//定义拦截器类,实现HandlerInterceptor接口
//注意当前类必须受Spring容器控制
public class ProjectInterceptor implements HandlerInterceptor {@Override
//原始方法调用前执行的内容
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle...");
return true;
}
@Override
//原始方法调用后执行的内容
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle...");
}
@Override
//原始方法调用完成后执行的内容
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
{System.out.println("afterCompletion...");
}
}
- 配置拦截器类:在 config 包下的 SpringMvcSupport 类中,定义一个 ProjectInterceptor 对象并自动装配,覆盖 addInterceptors 方法配置拦截器
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {@Autowired
private ProjectInterceptor projectInterceptor;
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
}
@Override
protected void addInterceptors(InterceptorRegistry registry) {//配置拦截器
registry.addInterceptor(projectInterceptor).addPathPatterns("/books");
}
}
- SpringMVC添加SpringMvcSupport包扫描
- 修改拦截器拦截规则,让 /books 下一级目录也被包含
@Override
protected void addInterceptors(InterceptorRegistry registry) {//配置拦截器
registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*" );
}
- 简化SpringMvcSupport的编写
@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
//实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
public class SpringMvcConfig implements WebMvcConfigurer {@Autowired
private ProjectInterceptor projectInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {//配置多拦截器
registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");
}
}
7.3 拦截器参数- 前置处理方法
- 后置处理方法
- 完成处理方法
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
文章名称:热门框架学习笔记-创新互联
文章链接:http://scyanting.com/article/hcjgc.html