目录
- 自定义错误页
- CORS支持(前端跨域请求)
- 拦截器HandlerInterceptor
- 启动系统任务
- springboot配置AOP
- 整合servlet、filter、listener
下图为本节内容
1、自定义错误页
springboot中默认错误是由BasicErrorController类来处理的,该类核心方法有errorHtml(返回Html),error(返回json),DefaultErrorViewResolver是Springboot默认错误解析器。该类源码中可以看出4xx、5xx文件作为错误视图,找不到会回到errorHtml方法中,使用error作为默认的错误页面视图。
1)、自定义Error数据
BasicErrorController的errorHtml、error都是通过getErrorAttributes方法获取error信息。该方法会调用DefaultErrorAttributes类的getErrorAttributes方法,而DefaultErrorAttributes类是在ErrorMvcAutoCongfigutration默认提供的。
@Bean
@ConditionalOnMissingBean(
value = {ErrorAttributes.class},
search = SearchStrategy.CURRENT
)
public DefaultErrorAttributes errorAttributes() {
return new DefaultErrorAttributes(this.serverProperties.getError().isIncludeException());
}
从这段源码可以看出,当系统没有听过ErrorAttributes时才会采用DefaultErrorAttributes,因此自定义错误时,只需要自己提供一个ErrorAttributes。
@Component
public class MyErrorAttribute extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace);
errorAttributes.put("custommsg","出错了");
errorAttributes.remove("error");
return errorAttributes;
}
}
2)、自定义error视图
BasicErrorController的errorHtml方法中调用resolveErrorView方法获取一个ModelAndView实例。resolveErrorView是由ErrorViewResolver提供的。
@Bean
@ConditionalOnBean({DispatcherServlet.class})
@ConditionalOnMissingBean
public DefaultErrorViewResolver conventionErrorViewResolver() {
return new DefaultErrorViewResolver(this.applicationContext, this.resourceProperties);
}
想要自定义自己的视图,只需要提供自己的ErrorViewResolver
@Component
public class MyErrorViewResolver implements ErrorViewResolver {
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
ModelAndView modelAndView = new ModelAndView("errorPage");
modelAndView.addObject("custommsg","出错了");
modelAndView.addAllObjects(model);
return modelAndView;
}
}
3)、自定义视图和自定义数据
查看Error自动化配置类ErrorMvcAutoConfiguration,BasicErrorController是一个默认的配置。
@Bean
@ConditionalOnMissingBean(
value = {ErrorController.class},
search = SearchStrategy.CURRENT
)
public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) {
return new BasicErrorController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers);
}
从这段源码可以看到,如果没有提供自己的ErrorController,则springboot提供BasicErrorController作为默认的ErrorController。
@Controller
public class MyErrorController extends BasicErrorController {
public MyErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties,
List<ErrorViewResolver> errorViewResolvers) {
super(errorAttributes,serverProperties.getError(),errorViewResolvers);
}
@Override
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = getStatus(request);
Map<String, Object> model =
getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
model.put("custommsg","出错了");
ModelAndView modelAndView = new ModelAndView("myErrorPage",model,status);
return modelAndView;
}
@Override
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> errorAttributes = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
errorAttributes.put("custommsg","出错了");
HttpStatus status = getStatus(request);
return new ResponseEntity<>(errorAttributes,status);
}
}
2、CORS支持(前端跨域请求)
配置跨域可以在方法上加注解、全局配置。
在方法上加注解
@PostMapping("/book")
@CrossOrigin(value = "http://localhost:8081",maxAge = 1800,allowedHeaders = "*")
public String addBook(String name) {
return "receive:" + name;
}
全局配置
//跨域全局配置
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/book/**")
.allowedHeaders("*")
.allowedMethods("*")
.maxAge(1800)
.allowedOrigins("http://localhost:8081");
}
3、拦截器HandlerInterceptor
配置拦截器,定义配置类进行拦截器的配置
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/static/**");
}
4、启动系统任务
1)、CommandLineRunner
/**
* CommandLineRunner 系统启动时加载参数
* @author shuliangzhao
* @Title: MyCommandLineRunner
* @ProjectName spring-boot-learn
* @Description: TODO
* @date 2019/7/21 12:34
*/
@Component
@Order(1)
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("Runner>>>" + Arrays.toString(args));
}
}
2)、ApplicationRunner
/**
* --name = zhangsan getOptionNames getOptionValues
* 路遥 平凡的世界 getNonOptionArgs取值
* @author shuliangzhao
* @Title: MyApplicationRunner
* @ProjectName spring-boot-learn
* @Description: TODO
* @date 2019/7/21 12:36
*/
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
List<String> nonOptionArgs = args.getNonOptionArgs();
System.out.println("nonOptionArgs>>>" + nonOptionArgs);
Set<String> optionNames = args.getOptionNames();
for (String optionName:optionNames) {
System.out.println("key:" + optionName + ";value:" + args.getOptionValues(optionName));
}
}
}
5、springboot配置AOP
Joinpoint:连接点,类里面可以被增强的方法即为连接点,例如想修改哪个方法的功能,那么这个方法即为连接点
Pointcut:切入点,对于Joinpoint进行拦截的定义即为切入点,例如拦截所有的insert
Advice:通知,拦截到Joinpoint之后所要做的事就是通知,
Aspect:切面,Pointcut和Advice的结合
Target:目标对象,要增强类为target
@Component
@Aspect
public class LogAspect {
@Pointcut("execution(* com.sl.service.*.*(..))")
public void pc() {
}
@Before(value = "pc()")
public void before(JoinPoint jp) {
String name = jp.getSignature().getName();
System.out.println(name + "方法开始执行...");
}
@After(value = "pc()")
public void after(JoinPoint jp) {
String name = jp.getSignature().getName();
System.out.println(name + "方法执行结束...");
}
@AfterReturning(value = "pc()",returning = "result")
public void afterReturning(JoinPoint jp,Object result) {
String name = jp.getSignature().getName();
System.out.println(name + "方法返回值为:" + result);
}
@AfterThrowing(value = "pc()",throwing = "e")
public void afterThrowing(JoinPoint jp,Exception e) {
String name = jp.getSignature().getName();
System.out.println(name + "方法抛出异常,异常时:" + e);
}
@Around("pc()")
public Object around(ProceedingJoinPoint pj) throws Throwable {
return pj.proceed();
}
}
6、整合servlet、filter、listener
以servle为例,需要在启动类上加上@ServletComponentScan
@WebServlet
public class MyHttpServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("name>>>" + req.getParameter("name"));
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
我的github地址上都有单独的工程讲解,可以去参考:https://github.com/FadeHub/spring-boot-learn