目录
- 自定义错误页
- 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); } }