GitHub:https://github.com/Werdio66/myblog
gradle 依赖:
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-aop'
compile group: 'com.github.pagehelper', name: 'pagehelper-spring-boot-starter', version: '1.2.13'
compile group: 'com.atlassian.commonmark', name: 'commonmark', version: '0.14.0'
compile group: 'com.atlassian.commonmark', name: 'commonmark-ext-gfm-tables', version: '0.14.0'
compile group: 'com.atlassian.commonmark', name: 'commonmark-ext-heading-anchor', version: '0.14.0'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.1'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'mysql:mysql-connector-java'
annotationProcessor 'org.projectlombok:lombok'
分类:展示所有的分类和当前分类下的博客数,并分页显示每一个分类的博客
标签:展示所有的标签和当前标签下的博客数,并分页显示每一个标签的博客
归档:按时间分类
关于我:从配置文件中读取个人信息
博客管理
分类管理:分类的分页显示,增加分类,删除和批量删除分类
标签管理:标签的分页显示,增加标签,删除和批量删除未实现,和分类管理类似
对 /admin/** 路径下的请求做登录拦截,后台管理页面需要权限
/**
* 登录请求拦截
*/
@Slf4j
public class LoginFilter implements Filter {
private String noAuthUrl = "/admin";
private Set<String> exclusionUrlSet = new ConcurrentSkipListSet<>();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String url = filterConfig.getInitParameter("loginUrl");
exclusionUrlSet.add(noAuthUrl);
exclusionUrlSet.add("/login");
exclusionUrlSet.add("redirect:/main.html");
exclusionUrlSet.add("redirect:/admin");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String uri = req.getRequestURI();
log.info("【LongFilter】当前请求 uri = {}", uri);
// 只对 /admin/** 下的资源拦截
if (!uri.startsWith(noAuthUrl)){
chain.doFilter(request, response);
return;
}
// 自己添加的 url,可以配置到 yml 文件中
if (exclusionUrlSet.contains(uri)){
chain.doFilter(request, response);
return;
}
String username = (String) req.getSession().getAttribute("loginUser");
log.info("session 中的用户:{}", username);
if (StringUtils.isEmpty(username)){
log.error("您没有访问权限,请先登录");
resp.sendRedirect("/admin");
return;
}
// 登录成功
chain.doFilter(request, response);
}
}
在 controller 层每一个请求之前记录请求的 ip,uri,方法名
@Slf4j
@Aspect
@Component
public class LogAspect {
@Pointcut("execution(* com._520.myblog.controller.*.*(..))")
public void log(){}
@Before(value = "log()")
public void before(JoinPoint joinPoint){
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
String uri = request.getRequestURL().toString();
String ip = request.getRemoteAddr();
String method = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
RequestLog requestLog = new RequestLog(uri, ip, method, args);
log.info("{}", requestLog);
}
@AfterReturning(returning = "result", pointcut = "log()")
public void afterReturn(Object result){
log.info("返回的页面:{}", result);
}
@AllArgsConstructor
private static class RequestLog{
private final String url;
private final String ip;
private final String reqMethod;
private final Object[] args;
@Override
public String toString() {
return "RequestLog{" +
"url='" + url + '\'' +
", ip='" + ip + '\'' +
", reqMethod='" + reqMethod + '\'' +
", args=" + Arrays.toString(args) +
'}';
}
}
}
@Override
public List<Comment> queryAllByBlogId(Long id) {
// 查询指定博客对应的所有评论
List<Comment> allComments = commentMapper.queryAllByBlogId(id);
// 存放父评论
List<Comment> parentComments = new ArrayList<>();
Map<Long, Comment> map = new HashMap<>();
Map<Long, Comment> allComms = new HashMap<>();
// 找出父评论
for (Comment comment : allComments){
if (comment.getParentId() == -1){
parentComments.add(comment);
// 将父评论存入 map 中,便于设置子评论
map.put(comment.getId(), comment);
}
allComms.put(comment.getId(), comment);
}
// 设置子评论
for (Comment comment : allComments){
if (comment.getParentId() != -1){
// 取出当前评论的父评论
Comment parent = map.get(comment.getParentId());
// 父评论有可能不是根结点,所以从所有的评论中取获取
if (parent == null){
parent = allComms.get(comment.getParentId());
}
// 将当前评论加到父评论的子评论中
parent.getChildComments().add(comment);
// 为当前评论设置父评论
comment.setParentName(parent.getNickName());
}
}
for (int i = 0; i < parentComments.size(); i++) {
merge(parentComments.get(i));
}
// parentComments.forEach(System.out::println);
return parentComments;
}
private void merge(Comment parentComment) {
if (parentComment.getChildComments().isEmpty()){
return;
}
List<Comment> childComments = parentComment.getChildComments();
for (int i = 0; i < childComments.size(); i++) {
merge(childComments.get(i));
parentComment.getChildComments().addAll(childComments.get(i).getChildComments());
}
}
对博客主页进行压测
对博客详情页进行压力测试