最近写博客,看见博客系统可以自定义文章的路径。很好奇这个是如何实现的,就想着自己来实现一下。
实现思路
1 既然是自定义的 url 地址,那么肯定要保存到数据库。
2 拦截所有的请求,然后判断请求的地址是不是一个博文的自定义 url 地址。
3 如果是就重定向或者转发到博文统一展示页(重定向或者转发时将博文的 ID 传过去)。
4 博文统一展示页就通过博文的 id 就可以展示文章内容了。
拦截器学习
既然是通过拦截器实现,那么就需要知道该在何时拦截,如何在拦截器当中实现重定向跳转等等。
/**
* @author 海加尔金鹰 www.hjljy.cn
**/
public class MlogPathInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
SpringBoot 当中实现拦截器非常简单,自需要实现 HandlerInterceptor 这个类就可以。
主要是他的三个方法:
preHandle 方法
范围:所有的请求都会进入这个请求 包括静态资源的请求
若返回 false,则中断执行,不会进入后续的方法
执行顺序:按照声明的顺序一个接一个执行(重点)
postHandle
调用前提:preHandle 返回 true
调用时间:请求在进入到 Controller 方法后,并且 Controller 方法处理完之后,DispatcherServlet 进行视图的渲染之前。post、get 方法都能处理
执行顺序:按照声明的顺序倒着执行。(重点)
afterCompletion:
调用时间:DispatcherServlet 进行视图的渲染之后
执行顺序:按照声明的顺序倒着执行。
关于执行顺序看这篇文章:https://www.cnblogs.com/pypua/p/10075259.html
最终实现功能的拦截器代码
拦截器代码
/**
* @author 海加尔金鹰 www.hjljy.cn
**/
public class MlogPathInterceptor implements HandlerInterceptor {
@Autowired
IMlogArticlesService mlogArticlesService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取所有文章的URL
List<String> allUrl = mlogArticlesService.getAllUrl();
//获取请求的路径
String servletPath = request.getServletPath();
//如果包含就跳转
if(allUrl.contains(servletPath)){
//将本次请求转发到 /details/{id} 这个请求路径上
request.getRequestDispatcher("/details/123").forward(request,response);
return false;
}
return true;
}
}
添加所有请求的拦截器
@Configuration
public class MlogWebConfig implements WebMvcConfigurer {
@Bean
MlogPathInterceptor getMlogPathInterceptor() {
return new MlogPathInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getMlogPathInterceptor()).addPathPatterns("/**");
}
}
文章统一展示页处理
@GetMapping("/details/{id}")
public String details(@PathVariable int id) {
//todo
return "details?id="+id;
}
到此,功能就实现了。