Myblog
项目架构
分两个部分一个是blog主页,一个是后台主页;
blog主页要实现的功能有
- blog文章详情,文章简述,友链,分类,评论展示;
- 分页;
- 搜索文章,标签搜索;
- 评论提交;
后台要实现的功能,
- 登陆注销;
- blog文章,标签,分类,友链接,系统配置以及用户信息的crud,
- 图片文件的上传;
- 异常拦截;
- blog数据(标签总数,blog总数,友链总数,分类总数,评论总数);
- 验证码确认;
配置类
登陆拦截(关于拦截这一块的原理还不是很明白,到后面再深度学习一下)
/**
* 后台系统身份验证拦截器
*/
@Component
public class AdminLoginInterceptor implements HandlerInterceptor {
/**
* 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
* 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
String uri = request.getRequestURI();
if (uri.startsWith("/admin") && null == request.getSession().getAttribute("loginUserId")) {
request.getSession().setAttribute("errorMsg", "请重新登陆");
response.sendRedirect(request.getContextPath() + "/admin/v1/login");
return false;
} else {
request.getSession().removeAttribute("errorMsg");
return true;
}
}
/**
* 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
*/
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
/**
* 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
*/
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
拦截器
@Configuration
public class MyBlogWebMvcConfigurer implements WebMvcConfigurer {
@Resource
private AdminLoginInterceptor adminLoginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加一个拦截器,拦截以/admin为前缀的url路径
//addInterceptor增加一个拦截器,这个拦截器需要你自己再继承HandlerInterceptor,自己写,后面则是拦截的路径和不包括的路径
registry.addInterceptor(adminLoginInterceptor)
.addPathPatterns("/admin/**")
.excludePathPatterns("/admin/v1/login")
.excludePathPatterns("/admin/v1/reload")
.excludePathPatterns("/admin/dist/**")
.excludePathPatterns("/admin/plugins/**")
.excludePathPatterns("/X-admin/**");
}
/**
* @Description: 重写addResourceHandlers映射文件路径,这里相当于本地储存文件映射到网页域名上的
* 文件
* @Param: [registry]
* @return: void
* @date: 2019/8/7 9:06
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//这里要用file,如果用classpath会找不到路径!
registry.addResourceHandler("/authorImg/**").addResourceLocations("file:" + UploadConstants.UPLOAD_AUTHOR_IMG);
registry.addResourceHandler("/upload/**").addResourceLocations("file:" + UploadConstants.UPLOAD_AUTHOR_IMG);
}
}
全局异常统一处理类(这里我暂时不是很懂,等后面再补充这一块全局异常捕捉)
@ControllerAdvice
public class ApplicationControllerExceptionHandler {
/**
* 方法参数效验
* @param e
* @return com.zhulin.ascentweb.dto.Result
* @date 2019/9/8 9:58
*/
@ExceptionHandler(value = BindException.class)
@ResponseBody
public Result BindException(BindException e) {
return ResultGenerator.getResultByHttp(HttpStatusConstants.BAD_REQUEST, Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
}
/**
* 方法参数效验
* @param e
* @return com.zhulin.ascentweb.dto.Result
* @date 2019/9/8 9:58
*/
@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseBody
public Result handlerMethodArgumentNotValidException(MethodArgumentNotValidException e) {
return ResultGenerator.getResultByHttp(HttpStatusConstants.BAD_REQUEST, Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
}
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Result handlerError(HttpServletRequest req, Exception e) {
return ResultGenerator.genFailResult("出现异常错误,请及时查看后台日志!");
}
}
Mybatis-plus分页插件
@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
Druid
@Configuration
public class DruidConfig {
/**
* 将自定义的 Druid数据源添加到容器中,不再让 Spring Boot 自动创建
* 绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource从而让它们生效
* @ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置文件中
* 前缀为 spring.datasource的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中
*/
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource duridDataSource() {
return new DruidDataSource();
}
/**
* 配置 Druid 监控管理后台的Servlet;
* 内置 Servler 容器时没有web.xml文件,所以使用 Spring Boot 的注册 Servlet 方式
* */
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map<String, String> initParams = new HashMap<>();
//后台管理界面的登录账号
initParams.put("loginUsername", "admin");
//后台管理界面的登录密码
initParams.put("loginPassword", "123456");
//后台允许谁可以访问
//initParams.put("allow", "localhost"):表示只有本机可以访问
//initParams.put("allow", ""):为空或者为null时,表示允许所有访问
initParams.put("allow", "");
//deny:Druid 后台拒绝谁访问
//initParams.put("kuangshen", "192.168.1.20");表示禁止此ip访问
//设置初始化参数
bean.setInitParameters(initParams);
return bean;
//这些参数可以在 com.alibaba.druid.support.http.StatViewServlet 的父类 com.alibaba.druid.support.http.ResourceServlet 中找到
}
/**
* 配置 Druid 监控 之 web 监控的 filter
* WebStatFilter:用于配置Web和Druid数据源之间的管理关联监控统计
* */
@Bean
public FilterRegistrationBean webStatFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
//exclusions:设置哪些请求进行过滤排除掉,从而不进行统计
Map<String, String> initParams = new HashMap<>();
initParams.put("exclusions", "*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
//"/*" 表示过滤所有请求
bean.setUrlPatterns(Collections.singletonList("/*"));
return bean;
}
}