特点:
1.用URL描述资源
2.使用HTTP方法描述行为。使用HTTP状态码来表示不同的结果
3.使用json交互数据
4.RESTful只是一种风格,并不是强制标准
restful API 的拦截
过滤器(Filter)
@Component public class TimeFilter implements Filter { @Override public void destroy() { System.out.println("time filter destroy"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("time filter start"); long start = new Date().getTime(); chain.doFilter(request, response); System.out.println("time filter 耗时:"+(new Date().getTime() - start)); System.out.println("time filter finish"); } @Override public void init(FilterConfig arg0) throws ServletException { System.out.println("time filter init"); } }
SpringBoot将第三方过滤器filter(没有@Component注解)加入自己项目:
@Configuration public class WebConfig { //以TimeFilter作为第三方过滤器为例 @Bean public FilterRegistrationBean timeFilter() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); TimeFilter timeFilter = new TimeFilter(); registrationBean.setFilter(timeFilter); List<String> urls = new ArrayList<>(); urls.add("/*"); registrationBean.setUrlPatterns(urls); return registrationBean; } }
filter局限性:只能获取http的请求和响应以及它们的参数,不知由哪个控制器和方法处理的,因为Filter接口是由JavaEE规范定义的并不知跟Spring相关任何东西。这时需要Spring框架提供的机制Interceptor。
拦截器(Interceptor)
@Component public class TimeInterceptor implements HandlerInterceptor { //控制器某个方法被调用之前此方法先被调用 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle"); System.out.println(((HandlerMethod)handler).getBean().getClass().getName()); System.out.println(((HandlerMethod)handler).getMethod().getName()); request.setAttribute("startTime", new Date().getTime()); return true; } //控制器方法被调用之后此方法被调用,如果控制器方法抛异常此方法不被调用 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); Long start = (Long) request.getAttribute("startTime"); System.out.println("time interceptor 耗时:" + (new Date().getTime() - start)); } //不管控制器方法是否正常被调用此方法都被调用 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) throws Exception { System.out.println("afterHandle"); Long start = (Long) request.getAttribute("startTime"); System.out.println("time interceptor 耗时:" + (new Date().getTime() - start)); System.out.println("Exception is " + e); } }
还需要额外配置
@Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Autowired private TimeInterceptor timeInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(timeInterceptor); } }
Interceptor局限性:无法获取获取控制器被调用方法参数的值。这时需要AOP面向切面编程Aspect。
切片(Aspect)
切片简介:
1.切入点 ( 注解 ):在哪些方法上起作用,在什么时候起作用
2.增强 ( 方法 ):起作用时执行的业务逻辑
@Aspect @Component public class TimeAspect { @Around("execution(* com.hclz.web.controller.UserController.*(..))") public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable { System.out.println("time aspect start"); //获取控制器别调用方法的参数 Object[] args = pjp.getArgs(); for(Object arg : args) { System.out.println("arg is " + arg); } long start = new Date().getTime(); Object object = pjp.proceed(); System.out.println("time aspect 耗时:" + (new Date().getTime() - start)); System.out.println("time aspect end"); return object; } }
aspect局限性:无法获取原始http和http响应的对象
restful API 起作用的顺序