1.数据库中测试按年份分类排序语句;
点击右侧Database;
点击Query Console下选择console(Default);
点开t_news表手动修改几条新闻的年份以做年份归档SQL语句测试,后点击Submit提交数据更新;
在刚才打开的console(Default)页面键入如下SQL语句测试新闻的年份归档,点击Execute执行;
select date_format(n.update_time,'%Y') from t_news n group by date_format(n.update_time,'%Y') order by date_format(n.update_time,'%Y') desc
//从时间戳年月日+时分秒格式中提取出year分组降序
select * from t_news n where date_format(n.update_Time,'%Y') = 2020
//归档某一具体年份的所有新闻
2.修改NewRepository接口;
NewRepository:中添加
//select date_format(n.update_time,'%Y') from t_news n group by date_format(n.update_time,'%Y') order by date_format(n.update_time,'%Y') desc
@Query("select function('date_format',n.updateTime,'%Y') as year from News n group by year order by year desc")
List<String> findGroupYear();
@Query("select n from News n where function('date_format',n.updateTime,'%Y') = ?1 ")
List<News> findByYear(String year);
2.修改NewService接口;
NewService:中添加
List<Comment> listCommentByNewId(Long newId);
3.修改NewServiceImpl类;
NewServiceImpl:中添加
@Override
public List<Comment> listCommentByNewId(Long newId) {
Sort sort = Sort.by("createTime");
List<Comment> comments = commentRepository.findByNewsIdAndParentCommentNull(newId,sort);
return eachComment(comments);
}
private List<Comment> eachComment(List<Comment> comments){
List<Comment> commentsView = new ArrayList<>();
for (Comment comment:comments){
Comment c = new Comment();
BeanUtils.copyProperties(comment,c);
commentsView.add(c);
}
//合并评论的各层子代到第一级子代集合中
combineChildren(commentsView);
return commentsView;
}
private void combineChildren(List<Comment> comments){
for (Comment comment:comments){
List<Comment> replys1 = comment.getReplyComments();
for (Comment reply1:replys1){
//循环迭代,找出子代
recursively(reply1);
}
comment.setReplyComments(tempReplys);
//清楚临时缓存区
tempReplys = new ArrayList<>();
}
}
private List<Comment> tempReplys = new ArrayList<>();
private void recursively(Comment comment){
tempReplys.add(comment); //顶节点添加到临时存放区
if (comment.getReplyComments().size()>0){
List<Comment> replys = comment.getReplyComments();
for (Comment reply:replys){
tempReplys.add(reply);
if(reply.getReplyComments().size()>0){
recursively(reply);
}
}
}
}
4.web下创ArchiveShowController类;
ArchiveShowController:中添加
@GetMapping("/comments/{newId}")
public String comments(@PathVariable Long newId, Model model){
model.addAttribute("comments",commentService.listCommentByNewId(newId));
return "new::commentList";
}
Test
1.点击新闻主页上方导航栏中的归档,即可查看按年份归档的新闻;
2.也可点击新闻进入新闻详情页;
1.news下创建NotFoundException类进行全局异常处理;
NotFoundException中添加:
@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException {
public NotFoundException() {
}
public NotFoundException(String message) {
super(message);
}
public NotFoundException(String message, Throwable cause) {
//cause 异常原因
super(message, cause);
}
}
2.news下创建handler包下创建ControllerExceptionHandler类;
ControllerExceptionHandler中添加:
@ControllerAdvice
public class ControllerExceptionHandler {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@ExceptionHandler(Exception.class)
public ModelAndView exceptionHandler(HttpServletRequest request, Exception e) throws Exception {
logger.error("Request: URL: {},Exception: {}",request.getRequestURL(),e);
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class)!=null){
throw e;
}
ModelAndView mv = new ModelAndView();
mv.addObject("url",request.getRequestURL());
mv.addObject("exception",e);
mv.setViewName("/error/error");
return mv;
}
}
拦截器:
依赖web框架
面向切面编程(AOP)
1.news下创建interceptor包下创建LoginInterceptor类;
LoginInterceptor中添加:
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception{
if (request.getSession().getAttribute("user")==null){
response.sendRedirect("/admin");
return false;
}
return true;
}
}
2.interceptor下创建WebConfig类;
WebConfig中添加:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/admin/**")
.excludePathPatterns("/admin")
.excludePathPatterns("/admin/login");
}
}