基于Spring Boot网站架构参考 文件说明:
文件名称 
文件说明 
 
 
pom.xml 
项目配置文件 
 
in.md 
开发参考说明文档 
 
application.yml 
SpringBoot开发环境配置文件(公共环境下配置) 
 
application-pro.yml 
SpringBoot开发环境配置文件(生产环境下配置) 
 
application-dev.yml 
SpringBoot开发环境配置文件(开发环境下配置) 
 
logback-spring.xml 
日志模块配置文件 
 
404.html 
404错误页面 
 
505.html 
505错误页面 
 
error.html 
BeBug页面 
 
blogs.html 
后台管理页面 
 
blogs-input.html 
博客后台发布页面 
 
type.html 
后台分类管理页面 
 
type-input.html 
后台分类新增页面 
 
about.html 
关于我页面 
 
archives.html 
归档页面 
 
blog.html 
博客详情页面 
 
index.html 
博客首页 
 
tags.html 
标签页面 
 
type.html 
分类页面 
 
login.html 
登录页面 
 
search.html 
搜索页面 
 
_fragments.html 
动态页面 定义Thymeleaf片段 
 
IndexController.java 
Web控制器 
 
LoginController.java 
WEB登录模块控制器 
 
BlogController.java 
Blog后台页面权限过滤管理类 
 
TypeController.java 
Web层分类模块操作 
 
TagController.java 
Web层标签模块操作 
 
CommentController.java 
评论模块处理 
 
TypeShowController.java 
分类模块处理 
 
TagShowController.java 
标签模块处理 
 
ArchiveShowController.java 
归档模块处理 
 
AboutShowController.java 
个人模块处理 
 
LongInterceptor.java 
Blog后台页面权限(登录过滤)类 
 
WebConfig.html 
Blog后台页面权限(拦截配置) 类 
 
ControllerExceptionHandler.java 
BeBug拦截器 
 
NotFoundException.java 
异常类,业务相关(如果没有页面报错404) 
 
Blog.java 
Blog实体类 
 
Type.java 
分类实体类 
 
Tag.java 
标签实体类 
 
Comment.java 
评论实体类 
 
User.java 
用户实体类 
 
UserService.java 
User登录业务逻辑处理接口类 
 
UserServiceImpl.java 
User登录业务逻辑处理实现类 
 
TypeService.java 
分类业务逻辑处理接口 
 
TypeServiceImpl.java 
分类业务逻辑处理实现类 
 
TagService.java 
标签业务逻辑处理接口 
 
BlogService.java 
博客业务逻辑处理接口 
 
BlogServiceImpl.java 
博客业务逻辑处理实现类 
 
TagServiceImpl.java 
标签业务逻辑处理实现类 
 
CommentService.java 
评论业务逻辑处理接口 
 
CommentServiceImpl.java 
评论业务逻辑处理实现类 
 
UserRepository.java 
引用SpringJPA SQL操作接口 
 
TypeRepository.java 
分类业务处理 SQL操作接口 
 
TagRepository.java 
标签业务处理 SQL操作接口 
 
BlogRepository.java 
博客业务处理 SQL操作接口 
 
CommentRepository.java 
评论业务处理 SQL操作接口 
 
BlogQuery.java 
博客搜索查询类 
 
MD5Utils.java 
MD5加密类 
 
MyBeanUtils.java 
修复SQL数据修改后为null工具类(过滤掉数据值为null) 
 
MarkdownUtils.java 
Markdown转换HTML工具类 
 
messages.properties 
数据配置文件 
 
项目配置(Jar包)
<?xml version="1.0" encoding="UTF-8"?> <project  xmlns ="http://maven.apache.org/POM/4.0.0"  xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"           xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" >     <modelVersion > 4.0.0</modelVersion >      <parent >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-starter-parent</artifactId >          <version > 2.4.2</version >          <relativePath />       </parent >      <groupId > com.cxkj</groupId >      <artifactId > blog</artifactId >      <version > 0.0.1-SNAPSHOT</version >      <name > blog</name >      <description > Demo project for Spring Boot</description >      <properties >          <java.version > 1.8</java.version >          <tymeleaf.version > 3.0.2.RELEASE</tymeleaf.version >          <tymeleaf-layout-dialect.version > 2.1.1</tymeleaf-layout-dialect.version >      </properties >      <dependencies >          <dependency >              <groupId > org.springframework.boot</groupId >              <artifactId > spring-boot-starter-aop</artifactId >          </dependency >          <dependency >              <groupId > org.springframework.boot</groupId >              <artifactId > spring-boot-starter-data-jpa</artifactId >          </dependency >          <dependency >              <groupId > org.springframework.boot</groupId >              <artifactId > spring-boot-starter-thymeleaf</artifactId >          </dependency >          <dependency >              <groupId > org.springframework.boot</groupId >              <artifactId > spring-boot-starter-web</artifactId >          </dependency >          <dependency >              <groupId > org.springframework.boot</groupId >              <artifactId > spring-boot-devtools</artifactId >              <scope > runtime</scope >              <optional > true</optional >          </dependency >          <dependency >              <groupId > mysql</groupId >              <artifactId > mysql-connector-java</artifactId >              <scope > runtime</scope >          </dependency >          <dependency >              <groupId > org.springframework.boot</groupId >              <artifactId > spring-boot-starter-test</artifactId >              <scope > test</scope >          </dependency >      </dependencies >      <build >          <plugins >              <plugin >                  <groupId > org.springframework.boot</groupId >                  <artifactId > spring-boot-maven-plugin</artifactId >              </plugin >          </plugins >      </build >  </project > 
后面导入的Jar包(新版本原因曾经的Jar不包含了)
<dependency >     <groupId > javax.validation</groupId >      <artifactId > validation-api</artifactId >  </dependency > <dependency >     <groupId > org.hibernate</groupId >      <artifactId > hibernate-validator</artifactId >      <version > 6.0.13.Final</version >  </dependency > 
Markdown转换HTML第三方Jar包配置
<dependency >     <groupId > com.atlassian.commonmark</groupId >      <artifactId > commonmark</artifactId >      <version > 0.10.0</version >  </dependency > <dependency >     <groupId > com.atlassian.commonmark</groupId >      <artifactId > commonmark-ext-heading-anchor</artifactId >      <version > 0.10.0</version >  </dependency > <dependency >     <groupId > com.atlassian.commonmark</groupId >      <artifactId > commonmark-ext-gfm-tables</artifactId >      <version > 0.10.0</version >  </dependency > 
Application.yml配置文件 thymeleaf模板配置
spring:   thymeleaf:       mode:  HTML  
数据库相关连接配置
datasource:   driver-class-name:  com.mysql.cj.jdbc.Driver    url:  jdbc:mysql://localhost:3306/blog?useSSL=false&useUnicode=true&characterEncoding=utf-8    username:  root    password:  123456789  
JPA的连接配置
jpa: hibernate:   ddl-auto:  update  show-sql:  true 
日志配置
logging:   level:      root:  info      com.cxkj:  debug    file:      name:  log/blog.log  
日志的细节操作(logback-spring.xml)
<?xml version="1.0" encoding="UTF-8" ?> <configuration >          <include  resource ="org/springframework/boot/logging/logback/defaults.xml"  />      <property  name ="LOG_FILE"  value ="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}" />      <include  resource ="org/springframework/boot/logging/logback/console-appender.xml"  />           <appender  name ="TIME_FILE"                 class ="ch.qos.logback.core.rolling.RollingFileAppender" >         <encoder >              <pattern > ${FILE_LOG_PATTERN}</pattern >          </encoder >          <file > ${LOG_FILE}</file >          <rollingPolicy  class ="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" >              <fileNamePattern > ${LOG_FILE}.%d{yyyy-MM-dd}.%i</fileNamePattern >                           <maxHistory > 30</maxHistory >                           <timeBasedFileNamingAndTriggeringPolicy  class ="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP" >                  <maxFileSize > 10MB</maxFileSize >              </timeBasedFileNamingAndTriggeringPolicy >          </rollingPolicy >      </appender >      <root  level ="INFO" >          <appender-ref  ref ="CONSOLE"  />          <appender-ref  ref ="TIME_FILE"  />      </root >  </configuration >          
公共环境(开发环境指定为dev)
spring:   thymeleaf:      mode:  HTML    profiles:      active:  dev  
开发环境
spring:   datasource:      driver-class-name:  com.mysql.cj.jdbc.Driver      url:  jdbc:mysql://localhost:3306/blog?useSSL=false&useUnicode=true&characterEncoding=utf-8      username:  root      password:  123456789    jpa:      hibernate:        ddl-auto:  update      show-sql:  true  logging:   level:      root:  info      com.cxkj:  debug    file:      name:  log/blog-dev.log  
生产环境
spring:   datasource:      driver-class-name:  com.mysql.jdbc.Driver      url:  jdbc:mysql://localhost:3306/blog?useSSL=false&useUnicode=true&characterEncoding=utf-8      username:  root      password:  123456789    jpa:      hibernate:        ddl-auto:  none      show-sql:  true  logging:   level:      root:  warn      com.cxkj:  info    file:      name:  log/blog-pro.log  server:   port:  808  
异常处理 IndexController.java Web控制器
package  com.cxkj.blog.web;import  com.cxkj.blog.NotFoundException;import  org.springframework.stereotype.Controller;import  org.springframework.web.bind.annotation.GetMapping;@Controller public  class  IndexController      @GetMapping("/")      public  String index ()          String blog = null ;         if  (blog == null ){             throw   new  NotFoundException("博客不存在" );         }         return  "index" ;     } } 
ControllerExceptionHandler.java BeBug拦截器
package  com.cxkj.blog.handler;import  org.slf4j.Logger;import  org.slf4j.LoggerFactory;import  org.springframework.core.annotation.AnnotationUtils;import  org.springframework.web.bind.annotation.ControllerAdvice;import  org.springframework.web.bind.annotation.ExceptionHandler;import  org.springframework.web.bind.annotation.ResponseStatus;import  org.springframework.web.servlet.ModelAndView;import  javax.servlet.http.HttpServletRequest;@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("Requst URL : {},Exception : {}" , request.getRequestURI(),e);         if  (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null ){             throw  e;         }         ModelAndView mv = new  ModelAndView();         mv.addObject("url" ,request.getRequestURI());         mv.addObject("exception" ,e);         mv.setViewName("error/error" );         return  mv;     } } 
error.html BeBug页面
<!DOCTYPE html > <html  lang ="en"  xmlns:th ="http://www.w3.org/1999/xhtml" >     <head >          <meta  charset ="UTF-8" >          <title > BeBug</title >      </head >      <body >          <h1 > BeBug</h1 >          <div >              <div  th:utext ="'< !--'"  th:remove ="tag" > </div >              <div  th:utext ="'Failed Request URL : ' + ${url}"  th:remove ="tag" > </div >              <div  th:utext ="'Exception message : ' + ${exception.message}"  th:remove ="tag" > </div >              <ul  th:remove ="tag" >                  <li  th:each ="st : ${exception.stackTrace}"  th:remove ="tag" > <span  th:utext ="${st}"  th:remove ="tag" > </span > </li >              </ul >              <div  th:utext ="'--> '"  th:remove ="tag" > </div >          </div >      </body >  </html > 
NotFoundException.java 异常类,业务相关(如果没有页面报错404)
package  com.cxkj.blog;import  org.springframework.http.HttpStatus;import  org.springframework.web.bind.annotation.ResponseStatus;@ResponseStatus(HttpStatus.NOT_FOUND) public  class  NotFoundException  extends  RuntimeException     public  NotFoundException ()       }     public  NotFoundException (String message)           super (message);     }     public  NotFoundException (String message, Throwable cause)           super (message, cause);     } } 
日志处理 LogAspect.java 接口记录日志AOP类
package  com.cxkj.blog.aspect;import  org.aspectj.lang.JoinPoint;import  org.aspectj.lang.annotation.*;import  org.slf4j.Logger;import  org.slf4j.LoggerFactory;import  org.springframework.stereotype.Component;import  org.springframework.web.context.request.RequestContextHolder;import  org.springframework.web.context.request.ServletRequestAttributes;import  javax.servlet.http.HttpServletRequest;import  java.util.Arrays;@Aspect @Component public  class  LogAspect      private  final  Logger logger = LoggerFactory.getLogger(this .getClass());     @Pointcut("execution(* com.cxkj.blog.web.*.*(..))")      public  void  log ()       }     @Before("log()")      public  void  doBefore (JoinPoint joinPoint)           ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();         HttpServletRequest request = attributes.getRequest();         String url = request.getRequestURL().toString();         String ip = request.getRemoteAddr();         String classMethod = joinPoint.getSignature().getDeclaringTypeName() + "."  + joinPoint.getSignature().getName();         Object[] args = joinPoint.getArgs();         RequestLog requestLog = new  RequestLog(url, ip, classMethod, args);         logger.info("Request : {}" , requestLog);     }     @After("log()")      public  void  doAfter ()                }     @AfterReturning(returning = "result", pointcut = "log()")      public  void  doAfterReturning (Object result)           logger.info("Result : {}"  + result);     }     private  class  RequestLog           private  final  String url;         private  final  String ip;         private  final  String classMethod;         private  final  Object[] args;         public  RequestLog (String url, String ip, String classMethod, Object[] args)               this .url = url;             this .ip = ip;             this .classMethod = classMethod;             this .args = args;         }         @Override          public  String toString ()               return  "{"  +                     "url='"  + url + '\''  +                     ", ip='"  + ip + '\''  +                     ", classMethod='"  + classMethod + '\''  +                     ", args="  + Arrays.toString(args) +                     '}' ;         }     } } 
IndexController.java
package  com.cxkj.blog.web;import  com.cxkj.blog.NotFoundException;import  org.springframework.stereotype.Controller;import  org.springframework.web.bind.annotation.GetMapping;import  org.springframework.web.bind.annotation.PathVariable;@Controller public  class  IndexController      @GetMapping("/{id}/{name}")      public  String index (@PathVariable  Integer id,@PathVariable  String name)                       System.out.println("------ Index ------" );         return  "index" ;     } } 
页面处理 IndexController.java Web控制器
package  com.cxkj.blog.web;import  com.cxkj.blog.NotFoundException;import  org.springframework.stereotype.Controller;import  org.springframework.web.bind.annotation.GetMapping;import  org.springframework.web.bind.annotation.PathVariable;@Controller public  class  IndexController      @GetMapping("/")      public  String index ()                       return  "index" ;     } } 
动态页面 定义Thymeleaf片段
<!DOCTYPE html > <html  lang ="en"  xmlns:th ="http://www.w3.org/1999/xhtml" >     <head  th:fragment ="head(title)" >          <meta  charset ="UTF-8" >          <meta  name ="viewport"  content ="width=device-width,initial-scale=1.0" >          <title  th:replace ="${title}" > 详情</title >          <link  rel ="stylesheet"  href ="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css" >          <link  rel ="stylesheet"  href ="../static/css/typo.css"  th:href  = "@{/css/typo.css}" >          <link  rel ="stylesheet"  href ="../static/css/animate.css"  th:href  = "@{/css/animate.css}" >          <link  rel ="stylesheet"  href ="../static/lib/prism/prism.css"  th:href  = "@{/lib/prism/prism.css}" >          <link  rel ="stylesheet"  href ="../static/lib/tocbot/tocbot.css"  th:href  = "@{/lib/tocbot/tocbot.css}" >          <link  rel ="stylesheet"  href ="../static/css/meCs.css"  th:href  = "@{/css/meCs.css}" >      </head >      <body >                   <nav  th:fragment ="menu(n)"  class ="ui inverted attached segment m-padded-tb-mini m-shadow-small" >              <div  class ="ui container" >                  <div  class ="ui inverted secondary stackable menu" >                      <h2  class ="ui teal header item" > Guest Island</h2 >                      <a  href ="#"  class ="m-item item m-mobile-hide"  th:classappend ="${n==1} ? 'active'" > <i  class ="home icon" > </i > 首页</a >                      <a  href ="#"  class ="m-item item m-mobile-hide"  th:classappend ="${n==2} ? 'active'" > <i  class ="idea icon" > </i > 分类</a >                      <a  href ="#"  class ="m-item item m-mobile-hide"  th:classappend ="${n==3} ? 'active'" > <i  class ="tags icon" > </i > 标签</a >                      <a  href ="#"  class ="m-item item m-mobile-hide"  th:classappend ="${n==4} ? 'active'" > <i  class ="clone icon" > </i > 归档</a >                      <a  href ="#"  class ="m-item item m-mobile-hide"  th:classappend ="${n==5} ? 'active'" > <i  class ="info icon" > </i > 关于我</a >                                           <div  class ="right m-item item m-mobile-hide" >                          <div  class ="ui icon inverted transparent input" >                              <input  type ="text"  placeholder ="Search......" >                              <i  class ="search link icon" > </i >                          </div >                      </div >                  </div >              </div >              <a  href ="#"  class ="ui menu toggle black icon button m-right-top m-mobile-show" >                  <i  class ="sidebar icon" > </i >              </a >          </nav >                   <footer  th:fragment ="footer"  class ="ui inverted vertical segment m-padded-tb-massivs" >              <div  class ="ui center aligned container" >                  <div  class ="ui inverted divided stackable grid" >                      <div  class ="three wide column" >                          <div  class ="ui inverted link list" >                              <div  class ="item" >                                  <img  src ="../static/images/WX_Arvin.jpg"  th:src  = "@{/images/WX_Arvin.jpg}"  class ="ui rounded image"  alt ="Guest Island"  style ="width: 100px" >                              </div >                          </div >                      </div >                      <div  class ="three wide column" >                          <h4  class ="ui inverted header m-text-thin m-text-spaced" > 最新博客</h4 >                          <div  class ="ui inverted link list" >                              <a  href ="#"  class ="item" > 用户故事 (User Story) </a >                              <a  href ="#"  class ="item" > 关于脑机的那些事</a >                              <a  href ="#"  class ="item" > 2021年计划</a >                          </div >                      </div >                      <div  class ="three wide column" >                          <h4  class ="ui inverted header m-text-thin m-text-spaced" > 关于我</h4 >                          <div  class ="ui inverted link list" >                              <a  href ="#"  class ="item" > Email: 2644266656@qq.com</a >                              <a  href ="#"  class ="item" > QQ: 2644266656</a >                          </div >                      </div >                      <div  class ="seven wide column" >                          <h4  class ="ui inverted header m-text-thin m-text-spaced" > Guest Island</h4 >                          <p  class ="m-text-thin m-text-spaced m-opacity-mini" > 南有孤岛北有亡梦,南柯一梦终是虚无。</p >                      </div >                  </div >                  <div  class ="ui inverted section divider" > </div >                  <p  class ="m-text-thin m-text-spaced m-opacity-tiny" > Copyright ©  2020-2021 Guest Island Personal blog</p >              </div >          </footer >                   <th:block  th:fragment ="script" >              <script  src ="https://cdn.jsdelivr.net/npm/jquery@3.2/dist/jquery.min.js" > </script >              <script  src ="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.js" > </script >              <script  src ="//cdn.jsdelivr.net/npm/jquery.scrollto@2.1.2/jquery.scrollTo.min.js" > </script >              <script  src ="../static/lib/prism/prism.js"  th:src ="@{/lib/prism/prism.js}" > </script >              <script  src ="../static/lib/tocbot/tocbot.min.js"  th:src ="@{/lib/tocbot/tocbot.min.js}" > </script >              <script  src ="../static/lib/qrcode/qrcode.min.js"  th:src ="@{/lib/qrcode/qrcode.min.js}" > </script >              <script  src ="../static/lib/waypoints/jquery.waypoints.min.js"  th:src ="@{/lib/waypoints/jquery.waypoints.min.js}" > </script >          </th:block >      </body >  </html > 
实体设计 blog.java 博客实体类
package  com.cxkj.blog.pojo;import  javax.persistence.*;import  java.util.ArrayList;import  java.util.Date;import  java.util.List;@Entity @Table(name = "t_blog") public  class  Blog      @Id      @GeneratedValue      private  Long id;     private  String title;     private  String content;     private  String firstPicture;     private  String flag;     private  Integer views;     private  boolean  appreciation;     private  boolean  shareStatement;     private  boolean  commentabled;     private  boolean  published;     private  boolean  recommend;     @Temporal(TemporalType.TIMESTAMP)      private  Date createTime;     @Temporal(TemporalType.TIMESTAMP)      private  Date updateTime;     @ManyToOne      private  Type type;     @ManyToMany(cascade = {CascadeType.PERSIST})      private  List<Tag> tags = new  ArrayList<>();     @ManyToOne      private  User user;     @OneToMany(mappedBy = "blog")      private  List<Comment> comments = new  ArrayList<>();     public  Blog ()       }     public  Long getId ()           return  id;     }     public  void  setId (Long id)           this .id = id;     }     public  String getTitle ()           return  title;     }     public  void  setTitle (String title)           this .title = title;     }     public  String getContent ()           return  content;     }     public  void  setContent (String content)           this .content = content;     }     public  String getFirstPicture ()           return  firstPicture;     }     public  void  setFirstPicture (String firstPicture)           this .firstPicture = firstPicture;     }     public  String getFlag ()           return  flag;     }     public  void  setFlag (String flag)           this .flag = flag;     }     public  Integer getViews ()           return  views;     }     public  void  setViews (Integer views)           this .views = views;     }     public  boolean  isAppreciation ()           return  appreciation;     }     public  void  setAppreciation (boolean  appreciation)           this .appreciation = appreciation;     }     public  boolean  isShareStatement ()           return  shareStatement;     }     public  void  setShareStatement (boolean  shareStatement)           this .shareStatement = shareStatement;     }     public  boolean  isCommentabled ()           return  commentabled;     }     public  void  setCommentabled (boolean  commentabled)           this .commentabled = commentabled;     }     public  boolean  isPublished ()           return  published;     }     public  void  setPublished (boolean  published)           this .published = published;     }     public  boolean  isRecommend ()           return  recommend;     }     public  void  setRecommend (boolean  recommend)           this .recommend = recommend;     }     public  Date getCreateTime ()           return  createTime;     }     public  void  setCreateTime (Date createTime)           this .createTime = createTime;     }     public  Date getUpdateTime ()           return  updateTime;     }     public  void  setUpdateTime (Date updateTime)           this .updateTime = updateTime;     }     public  Type getType ()           return  type;     }     public  void  setType (Type type)           this .type = type;     }     public  List<Tag> getTags ()           return  tags;     }     public  void  setTags (List<Tag> tags)           this .tags = tags;     }     public  User getUser ()           return  user;     }     public  void  setUser (User user)           this .user = user;     }     public  List<Comment> getComments ()           return  comments;     }     public  void  setComments (List<Comment> comments)           this .comments = comments;     }     @Override      public  String toString ()           return  "Blog{"  +                 "id="  + id +                 ", title='"  + title + '\''  +                 ", content='"  + content + '\''  +                 ", firstPicture='"  + firstPicture + '\''  +                 ", flag='"  + flag + '\''  +                 ", views="  + views +                 ", appreciation="  + appreciation +                 ", shareStatement="  + shareStatement +                 ", commentabled="  + commentabled +                 ", published="  + published +                 ", recommend="  + recommend +                 ", createTime="  + createTime +                 ", updateTime="  + updateTime +                 '}' ;     } } 
Type.java 分类实体类
package  com.cxkj.blog.pojo;import  javax.persistence.*;import  javax.validation.constraints.NotBlank;import  java.util.ArrayList;import  java.util.List;@Entity @Table(name = "t_type") public  class  Type      @Id      @GeneratedValue      private  Long id;     @NotBlank(message = "分类名称不能为空哦")      private  String name;     @OneToMany(mappedBy = "type")      private  List<Blog> blogs = new  ArrayList<>();     public  Type ()       }     public  Long getId ()           return  id;     }     public  void  setId (Long id)           this .id = id;     }     public  String getName ()           return  name;     }     public  void  setName (String name)           this .name = name;     }     public  List<Blog> getBlogs ()           return  blogs;     }     public  void  setBlogs (List<Blog> blogs)           this .blogs = blogs;     }     @Override      public  String toString ()           return  "Type{"  +                 "id="  + id +                 ", name='"  + name + '\''  +                 '}' ;     } } 
Tag.java 标签实体类
package  com.cxkj.blog.pojo;import  javax.persistence.*;import  java.util.ArrayList;import  java.util.List;@Entity @Table(name = "t_tag") public  class  Tag      @Id      @GeneratedValue      private  Long id;     private  String name;     @ManyToMany(mappedBy = "tags")      private  List<Blog> blogs = new  ArrayList<>();     public  Tag ()       }     public  Long getId ()           return  id;     }     public  void  setId (Long id)           this .id = id;     }     public  String getName ()           return  name;     }     public  void  setName (String name)           this .name = name;     }     public  List<Blog> getBlogs ()           return  blogs;     }     public  void  setBlogs (List<Blog> blogs)           this .blogs = blogs;     }     @Override      public  String toString ()           return  "Tag{"  +                 "id="  + id +                 ", name='"  + name + '\''  +                 '}' ;     } } 
Comment.java 评论实体类
package  com.cxkj.blog.pojo;import  javax.persistence.*;import  java.util.ArrayList;import  java.util.Date;import  java.util.List;@Entity @Table(name = "t_comment") public  class  Comment      @Id      @GeneratedValue      private  Long id;     private  String nickname;     private  String email;     private  String content;     private  String avatar;     @Temporal(TemporalType.TIMESTAMP)      private  Date createTime;     @ManyToOne      private  Blog blog;     @OneToMany(mappedBy = "parentComment")      private  List<Comment> replyComments = new  ArrayList<>();     @ManyToOne      private  Comment parentComment;     public  Comment ()       }     public  Long getId ()           return  id;     }     public  void  setId (Long id)           this .id = id;     }     public  String getNickname ()           return  nickname;     }     public  void  setNickname (String nickname)           this .nickname = nickname;     }     public  String getEmail ()           return  email;     }     public  void  setEmail (String email)           this .email = email;     }     public  String getContent ()           return  content;     }     public  void  setContent (String content)           this .content = content;     }     public  String getAvatar ()           return  avatar;     }     public  void  setAvatar (String avatar)           this .avatar = avatar;     }     public  Date getCreateTime ()           return  createTime;     }     public  void  setCreateTime (Date createTime)           this .createTime = createTime;     }     public  Blog getBlog ()           return  blog;     }     public  void  setBlog (Blog blog)           this .blog = blog;     }     public  List<Comment> getReplyComments ()           return  replyComments;     }     public  void  setReplyComments (List<Comment> replyComments)           this .replyComments = replyComments;     }     public  Comment getParentComment ()           return  parentComment;     }     public  void  setParentComment (Comment parentComment)           this .parentComment = parentComment;     }     @Override      public  String toString ()           return  "Comment{"  +                 "id="  + id +                 ", nickname='"  + nickname + '\''  +                 ", email='"  + email + '\''  +                 ", content='"  + content + '\''  +                 ", avatar='"  + avatar + '\''  +                 ", createTime="  + createTime +                 '}' ;     } } 
User.java 用户实体类
package  com.cxkj.blog.pojo;import  javax.persistence.*;import  java.util.ArrayList;import  java.util.Date;import  java.util.List;@Entity @Table(name = "t_user") public  class  User      @Id      @GeneratedValue      private  Long id;     private  String nickname;     private  String username;     private  String password;     private  String email;     private  String avatar;     private  Integer type;     @Temporal(TemporalType.TIMESTAMP)      private  Date CreateTime;     @Temporal(TemporalType.TIMESTAMP)      private  Date updateTime;     @OneToMany(mappedBy = "user")      private  List<Blog> blogs = new  ArrayList<>();     public  User ()       }     public  Long getId ()           return  id;     }     public  void  setId (Long id)           this .id = id;     }     public  String getNickname ()           return  nickname;     }     public  void  setNickname (String nickname)           this .nickname = nickname;     }     public  String getUsername ()           return  username;     }     public  void  setUsername (String username)           this .username = username;     }     public  String getPassword ()           return  password;     }     public  void  setPassword (String password)           this .password = password;     }     public  String getEmail ()           return  email;     }     public  void  setEmail (String email)           this .email = email;     }     public  String getAvatar ()           return  avatar;     }     public  void  setAvatar (String avatar)           this .avatar = avatar;     }     public  Integer getType ()           return  type;     }     public  void  setType (Integer type)           this .type = type;     }     public  Date getCreateTime ()           return  CreateTime;     }     public  void  setCreateTime (Date createTime)           CreateTime = createTime;     }     public  Date getUpdateTime ()           return  updateTime;     }     public  void  setUpdateTime (Date updateTime)           this .updateTime = updateTime;     }     public  List<Blog> getBlogs ()           return  blogs;     }     public  void  setBlogs (List<Blog> blogs)           this .blogs = blogs;     }     @Override      public  String toString ()           return  "User{"  +                 "id="  + id +                 ", nickname='"  + nickname + '\''  +                 ", username='"  + username + '\''  +                 ", password='"  + password + '\''  +                 ", email='"  + email + '\''  +                 ", avatar='"  + avatar + '\''  +                 ", type="  + type +                 ", CreateTime="  + CreateTime +                 ", updateTime="  + updateTime +                 '}' ;     } } 
后台登录业务 UserService.java User登录业务逻辑处理接口类
package  com.cxkj.blog.service;import  com.cxkj.blog.pojo.User;public  interface  UserService           User checkUser (String username,String password)  ; } 
UserServiceImpl.java User登录业务逻辑处理实现类
package  com.cxkj.blog.service;import  com.cxkj.blog.dao.UserRepository;import  com.cxkj.blog.pojo.User;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.stereotype.Service;@Service public  class  UserServiceImpl  implements  UserService          @Autowired      private  UserRepository userRepository;          @Override      public  User checkUser (String username, String password)           User user = userRepository.findByUsernameAndPassword(username,password);         return  user;     }      } 
UserRepository.java 引用SpringJPA SQL操作接口
package  com.cxkj.blog.dao;import  com.cxkj.blog.pojo.User;import  org.springframework.data.jpa.repository.JpaRepository;public  interface  UserRepository  extends  JpaRepository <User ,Long >          User findByUsernameAndPassword (String username,String password)  ; } 
LoginController.java WEB登录模块控制器
package  com.cxkj.blog.web.admin;import  com.cxkj.blog.pojo.User;import  com.cxkj.blog.service.UserService;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.stereotype.Controller;import  org.springframework.ui.Model;import  org.springframework.web.bind.annotation.GetMapping;import  org.springframework.web.bind.annotation.PostMapping;import  org.springframework.web.bind.annotation.RequestMapping;import  org.springframework.web.bind.annotation.RequestParam;import  org.springframework.web.servlet.mvc.support.RedirectAttributes;import  javax.servlet.http.HttpSession;@Controller @RequestMapping("/admin") public  class  LoginController           @Autowired      private  UserService userService;          @GetMapping      public  String loginPage ()          return  "admin/login" ;     }          @PostMapping("/login")      public  String login (@RequestParam  String username, @RequestParam  String password, HttpSession session, RedirectAttributes attributes)          User user = userService.checkUser(username,password);         if  (user != null ){             user.setPassword(null );             session.setAttribute("user" ,user);             return  "admin/index" ;         }else  {             attributes.addFlashAttribute("message" ,"用户名和密码存在异常错误" );             return  "redirect:/admin" ;         }              }          @GetMapping("/logout")      public  String logout (HttpSession session)          session.removeAttribute("user" );         return  "redirect:/admin" ;     } } 
MD5加密 MD5Utils.java MD5加密工具类
package  com.cxkj.blog.util;import  java.security.MessageDigest;import  java.security.NoSuchAlgorithmException;public  class  MD5Utils      public  static  String code (String str)          try  {             MessageDigest md = MessageDigest.getInstance("MD5" );             md.update(str.getBytes());             byte [] bytesDigest = md.digest();             int  i;             StringBuffer buffer = new  StringBuffer("" );             for  (int  offset = 0 ;offset<bytesDigest.length;offset++){                 i = bytesDigest[offset];                 if  (i<0 )                     i+= 256 ;                 if  (i<16 )                     buffer.append("0" );                 buffer.append(Integer.toHexString(i));             }                          return  buffer.toString();                                   } catch  (NoSuchAlgorithmException e) {             e.printStackTrace();             return  null ;         }     }               public  static  void  main (String[] args)           System.out.println(code("123456789" ));     } } 
UserServiceImpl.java
package  com.cxkj.blog.service;import  com.cxkj.blog.dao.UserRepository;import  com.cxkj.blog.pojo.User;import  com.cxkj.blog.util.MD5Utils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.stereotype.Service;@Service public  class  UserServiceImpl  implements  UserService     @Autowired      private  UserRepository userRepository;     @Override      public  User checkUser (String username, String password)           User user = userRepository.findByUsernameAndPassword(username, MD5Utils.code(password));         return  user;     } } 
BlogController.java 博客后台页面权限过滤管理类
package  com.cxkj.blog.web.admin;import  org.springframework.stereotype.Controller;import  org.springframework.web.bind.annotation.GetMapping;import  org.springframework.web.bind.annotation.RequestMapping;@Controller @RequestMapping("/admin") public  class  BlogController      @GetMapping("/blogs")      public  String blogs ()           return  "blogs" ;     } } 
LongInterceptor.java Blog后台页面权限(登录过滤)类
package  com.cxkj.blog.interceptor;import  org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import  javax.servlet.http.HttpServletRequest;import  javax.servlet.http.HttpServletResponse;public  class  LongInterceptor  extends  WebMvcConfigurerAdapter                @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 ;     } } 
WebConfig.java Blog后台页面权限(拦截配置)类
package  com.cxkj.blog.interceptor;import  org.springframework.context.annotation.Configuration;import  org.springframework.web.servlet.config.annotation.InterceptorRegistry;import  org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;@Configuration public  class  WebConfig  extends  WebMvcConfigurerAdapter                @Override      public  void  addInterceptors (InterceptorRegistry registry)           registry.addInterceptor(new  LongInterceptor()).addPathPatterns("/admin/**" )                 .excludePathPatterns("/admin" )                 .excludePathPatterns("/admin/login" );     } } 
关于弃用类整改 LongInterceptor.java Blog后台页面权限(登录过滤)类
package  com.cxkj.blog.interceptor;import  org.springframework.web.servlet.HandlerInterceptor;import  org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import  javax.servlet.http.HttpServletRequest;import  javax.servlet.http.HttpServletResponse;public  class  LongInterceptor  implements  HandlerInterceptor      @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 ;     } } 
WebConfig.java Blog后台页面权限(拦截配置)类
package  com.cxkj.blog.interceptor;import  org.springframework.context.annotation.Configuration;import  org.springframework.web.servlet.config.annotation.InterceptorRegistry;import  org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration public  class  WebConfig  implements  WebMvcConfigurer      @Override      public  void  addInterceptors (InterceptorRegistry registry)           registry.addInterceptor(new  LongInterceptor()).addPathPatterns("/admin/**" )                 .excludePathPatterns("/admin" )                 .excludePathPatterns("/admin/login" );     } } 
分类业务处理 TypeService.java 分类业务逻辑处理接口
package  com.cxkj.blog.service;import  com.cxkj.blog.pojo.Type;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  java.util.List;public  interface  TypeService      Type saveType (Type type)  ;     Type getType (Long id)  ;     Type getTypeByName (String name)  ;     Page<Type> listType (Pageable pageable)  ;     List<Type> listType ()  ;     Type updateType (Long id,Type type)  ;     void  deleteType (Long id)  } 
TypeServiceImpl.java 分类业务逻辑处理实现类
package  com.cxkj.blog.service;import  com.cxkj.blog.NotFoundException;import  com.cxkj.blog.dao.TypeRepository;import  com.cxkj.blog.pojo.Type;import  org.springframework.beans.BeanUtils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  java.util.List;@Service public  class  TypeServiceImpl  implements  TypeService     @Autowired      private  TypeRepository typeRepository;     @Transactional      @Override      public  Type saveType (Type type)           return  typeRepository.save(type);     }     @Transactional      @Override      public  Type getType (Long id)           return  typeRepository.findById(id).get();     }     @Override      public  Type getTypeByName (String name)           return  typeRepository.findByName(name);     }     @Transactional      @Override      public  Page<Type> listType (Pageable pageable)           return  typeRepository.findAll(pageable);     }     @Override      public  List<Type> listType ()           return  typeRepository.findAll();     }     @Transactional      @Override      public  Type updateType (Long id, Type type)           Type t = typeRepository.findById(id).get();         if  (t == null ){             throw  new  NotFoundException("您查找的信息不存在(︶︹︺)" );         }         BeanUtils.copyProperties(type,t);         return  typeRepository.save(t);     }     @Transactional      @Override      public  void  deleteType (Long id)           typeRepository.deleteById(id);     } } 
TypeRepository.java 分类业务 SQL操作接口
package  com.cxkj.blog.dao;import  com.cxkj.blog.pojo.Type;import  org.springframework.data.jpa.repository.JpaRepository;public  interface  TypeRepository  extends  JpaRepository <Type ,Long >     Type findByName (String name)  ; } 
TypeController.java Web层操作
package  com.cxkj.blog.web.admin;import  com.cxkj.blog.pojo.Type;import  com.cxkj.blog.service.TypeService;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.data.web.PageableDefault;import  org.springframework.stereotype.Controller;import  org.springframework.ui.Model;import  org.springframework.validation.BindingResult;import  org.springframework.web.bind.annotation.GetMapping;import  org.springframework.web.bind.annotation.PathVariable;import  org.springframework.web.bind.annotation.PostMapping;import  org.springframework.web.bind.annotation.RequestMapping;import  org.springframework.web.servlet.mvc.support.RedirectAttributes;import  javax.validation.Valid;@Controller @RequestMapping("/admin") public  class  TypeController      @Autowired      private  TypeService typeService;     @GetMapping("/types")      public  String types (@PageableDefault(size = 10,sort = {"id"},direction = Sort.Direction.DESC)                                   Pageable pageable, Model model)         model.addAttribute("page" ,typeService.listType(pageable));         return  "/admin/types" ;     }     @GetMapping("/types/input")      public  String input (Model model)          model.addAttribute("type" ,new  Type());         return  "/admin/types-input" ;     }     @GetMapping("types/{id}/input")      public  String editInput (@PathVariable  Long id, Model model)          model.addAttribute("type" ,typeService.getType(id));         return  "/admin/types-input" ;     }     @PostMapping("/types")      public  String post (@Valid  Type type, BindingResult result, RedirectAttributes attributes)          Type typename = typeService.getTypeByName(type.getName());         if  (typename != null ){             result.rejectValue("name" ,"nameError" ,"管理员大大,这个分类已经有了。((٩(//̀Д/́/)۶))做人要专一哦!" );         }         if  (result.hasErrors()){             return  "/admin/types-input" ;         }         Type t =  typeService.saveType(type);         if  (t == null ){             attributes.addFlashAttribute("message" ,"新增失败 ヘ(;´Д`ヘ),管理员大大重新试下吧" );         }else  {             attributes.addFlashAttribute("message" ,"新增成功 ≖‿≖✧ 快去发布新内容吧" );         }         return  "redirect:../admin/types" ;     }     @PostMapping("/types/{id}")      public  String editPost (@Valid  Type type, BindingResult result,@PathVariable  Long id, RedirectAttributes attributes)          Type typename = typeService.getTypeByName(type.getName());         if  (typename != null ){             result.rejectValue("name" ,"nameError" ,"管理员大大,这个分类已经有了。((٩(//̀Д/́/)۶))做人要专一哦!" );         }         if  (result.hasErrors()){             return  "/admin/types-input" ;         }         Type t =  typeService.updateType(id,type);         if  (t == null ){             attributes.addFlashAttribute("message" ,"更新失败(⊙o⊙),管理员大大重新试下吧" );         }else  {             attributes.addFlashAttribute("message" ,"更新成功 (≥◇≤) 快去发布新内容吧" );         }         return  "redirect:../types" ;     }     @GetMapping("/types/{id}/delete")      public  String delete (@PathVariable  Long id,RedirectAttributes attributes)          typeService.deleteType(id);         attributes.addFlashAttribute("message" ,"删除成功,可能是管理员大大不喜欢它了吧(.◕ฺˇд ˇ◕ฺ)" );         return  "redirect:../" ;     } } 
标签业务处理 TagService.java 标签业务逻辑处理接口
package  com.cxkj.blog.service;import  com.cxkj.blog.pojo.Tag;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  java.util.List;public  interface  TagService      Tag saveTag (Tag tag)  ;     Tag getTag (Long id)  ;     Tag getTagByName (String name)  ;     Page<Tag> listTag (Pageable pageable)  ;     List<Tag> listTag ()  ;     List<Tag> listTag (String ids)  ;     Tag updateTag (Long id,Tag tag)  ;     void  deleteTag (Long id)  } 
TagServiceImpl.java 标签业务逻辑处理实现类
package  com.cxkj.blog.service;import  com.cxkj.blog.NotFoundException;import  com.cxkj.blog.dao.TagRepository;import  com.cxkj.blog.pojo.Tag;import  org.springframework.beans.BeanUtils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  org.thymeleaf.util.StringUtils;import  java.util.ArrayList;import  java.util.List;@Service public  class  TagServiceImpl  implements  TagService     @Autowired      private  TagRepository tagRepository;     @Transactional      @Override      public  Tag saveTag (Tag tag)           return  tagRepository.save(tag);     }     @Transactional      @Override      public  Tag getTag (Long id)           return  tagRepository.findById(id).get();     }     @Transactional      @Override      public  Tag getTagByName (String name)           return  tagRepository.findByName(name);     }     @Transactional      @Override      public  Page<Tag> listTag (Pageable pageable)           return  tagRepository.findAll(pageable);     }     @Override      public  List<Tag> listTag ()           return  tagRepository.findAll();     }     @Override      public  List<Tag> listTag (String ids)           return  tagRepository.findAllById(convertToList(ids));     }     private  List<Long> convertToList (String ids)          List<Long> list = new  ArrayList<>();         if  ("" .equals(ids) && ids != null ){             String[] idarray = ids.split("," );             for  (int  i=0 ; i<idarray.length; i++){                 list.add(new  Long(idarray[i]));             }         }         return  list;     }     @Transactional      @Override      public  Tag updateTag (Long id, Tag tag)           Tag t = tagRepository.findById(id).get();         if  (t == null ){             throw  new  NotFoundException("您查找的信息不存在(︶︹︺)" );         }         BeanUtils.copyProperties(tag,t);         return  tagRepository.save(t);     }     @Transactional      @Override      public  void  deleteTag (Long id)           tagRepository.deleteById(id);     } } 
TagRepository.java 标签业务 SQL操作接口
package  com.cxkj.blog.dao;import  com.cxkj.blog.pojo.Tag;import  org.springframework.data.jpa.repository.JpaRepository;public  interface  TagRepository  extends  JpaRepository <Tag ,Long >          Tag findByName (String name)  ; } 
TagController.java WEB操作
package  com.cxkj.blog.service;import  com.cxkj.blog.NotFoundException;import  com.cxkj.blog.dao.TagRepository;import  com.cxkj.blog.pojo.Tag;import  org.springframework.beans.BeanUtils;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;@Service public  class  TagServiceImpl  implements  TagService     private  TagRepository tagRepository;     @Transactional      @Override      public  Tag saveTag (Tag tag)           return  tagRepository.save(tag);     }     @Transactional      @Override      public  Tag getTag (Long id)           return  tagRepository.findById(id).get();     }     @Transactional      @Override      public  Tag getTagByName (String name)           return  tagRepository.findByName(name);     }     @Transactional      @Override      public  Page<Tag> listTag (Pageable pageable)           return  tagRepository.findAll(pageable);     }     @Transactional      @Override      public  Tag updateTag (Long id, Tag tag)           Tag t = tagRepository.findById(id).get();         if  (t == null ){             throw  new  NotFoundException("您查找的信息不存在(︶︹︺)" );         }         BeanUtils.copyProperties(tag,t);         return  tagRepository.save(t);     }     @Transactional      @Override      public  void  deleteTag (Long id)           tagRepository.deleteById(id);     } } 
博客业务处理 BlogService.java 博客业务处理逻辑接口
package  com.cxkj.blog.service;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;public  interface  BlogService      Blog getBlog (Long id)  ;     Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)  ;     Blog saveBlog (Blog blog)  ;     Blog updateBlog (Long id,Blog blog)  ;     void  deleteBlog (Long id)  } 
BlogServiceImpl.java 博客业务处理逻辑实现类
package  com.cxkj.blog.service;import  com.cxkj.blog.NotFoundException;import  com.cxkj.blog.dao.BlogRepository;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.pojo.Type;import  com.cxkj.blog.util.MyBeanUtils;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.beans.BeanUtils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  org.springframework.data.jpa.domain.Specification;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  javax.persistence.criteria.CriteriaBuilder;import  javax.persistence.criteria.CriteriaQuery;import  javax.persistence.criteria.Predicate;import  javax.persistence.criteria.Root;import  java.util.ArrayList;import  java.util.Date;import  java.util.List;@Service public  class  BlogServiceImpl  implements  BlogService     @Autowired      private  BlogRepository blogRepository;     @Override      public  Blog getBlog (Long id)           return  blogRepository.findById(id).get();     }     @Override      public  Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)           return  blogRepository.findAll(new  Specification<Blog>() {             @Override              public  Predicate toPredicate (Root<Blog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder)                   List<Predicate> predicateList = new  ArrayList<>();                 if  (!"" .equals(blogQuery.getTitle()) && blogQuery.getTitle() != null ){                     predicateList.add(criteriaBuilder.like(root.<String>get("title" ),"%" +blogQuery.getTitle()+"%" ));                 }                 if  (blogQuery.getTypeID() != null ){                     predicateList.add(criteriaBuilder.equal(root.<Type>get("type" ).get("id" ),blogQuery.getTypeID()));                 }                 if  (blogQuery.isRecommend()){                     predicateList.add(criteriaBuilder.equal(root.<Boolean>get("recommend" ),blogQuery.isRecommend()));                 }                 criteriaQuery.where(predicateList.toArray(new  Predicate[predicateList.size()]));                 return  null ;             }         },pageable);     }     @Transactional      @Override      public  Blog saveBlog (Blog blog)           if  (blog.getId() == null ){             blog.setCreateTime(new  Date());             blog.setUpdateTime(new  Date());             blog.setViews(0 );         }else  {             blog.setUpdateTime(new  Date());         }         return  blogRepository.save(blog);     }     @Transactional      @Override      public  Blog updateBlog (Long id, Blog blog)           Blog b = blogRepository.findById(id).get();         if  (b == null ){             throw  new  NotFoundException("管理员大大,这个博客不存在哦!~( TロT)σ" );         }         BeanUtils.copyProperties(blog,b, MyBeanUtils.getNullPropertyNames(blog));         b.setUpdateTime(new  Date());         return  blogRepository.save(b);     }     @Transactional      @Override      public  void  deleteBlog (Long id)           blogRepository.deleteById(id);     } } 
BlogRepository.java 博客业务 SQL操作接口
package  com.cxkj.blog.dao;import  com.cxkj.blog.pojo.Blog;import  org.springframework.data.jpa.repository.JpaRepository;import  org.springframework.data.jpa.repository.JpaSpecificationExecutor;public  interface  BlogRepository  extends  JpaRepository <Blog ,Long >, JpaSpecificationExecutor <Blog >      } 
BlogController.java WEB操作
package  com.cxkj.blog.web.admin;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.pojo.Tag;import  com.cxkj.blog.pojo.User;import  com.cxkj.blog.service.BlogService;import  com.cxkj.blog.service.TagService;import  com.cxkj.blog.service.TypeService;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.data.web.PageableDefault;import  org.springframework.stereotype.Controller;import  org.springframework.ui.Model;import  org.springframework.web.bind.annotation.GetMapping;import  org.springframework.web.bind.annotation.PathVariable;import  org.springframework.web.bind.annotation.PostMapping;import  org.springframework.web.bind.annotation.RequestMapping;import  org.springframework.web.servlet.mvc.support.RedirectAttributes;import  javax.servlet.http.HttpSession;@Controller @RequestMapping("/admin") public  class  BlogController      private  static  final   String INPUT = "/admin/blogs-input" ;     private  static  final   String LIST = "/admin/blogs" ;     private  static  final   String REDIRECT_LIST = "redirect:/admin/blogs" ;     @Autowired      private  BlogService blogService;     @Autowired      private  TypeService typeService;     @Autowired      private  TagService tagService;     @GetMapping("/blogs")      public  String blogs (@PageableDefault(size = 10,sort = {"updateTime"},direction = Sort.Direction.DESC)  Pageable pageable, BlogQuery blogQuery, Model model)          model.addAttribute("types" ,typeService.listType());         model.addAttribute("page" ,blogService.listBlog(pageable,blogQuery));         return  LIST;     }     @PostMapping("/blogs/search")      public  String search (@PageableDefault(size = 10,sort = {"updateTime"},direction = Sort.Direction.DESC)  Pageable pageable,BlogQuery blogQuery,Model model)          model.addAttribute("page" ,blogService.listBlog(pageable,blogQuery));         return  "/admin/blogs :: blogList" ;     }     @GetMapping("/blogs/input")      public  String input (Model model)          setTypeAndTag(model);         model.addAttribute("blog" ,new  Blog());         return  INPUT;     }     private  void  setTypeAndTag (Model model)          model.addAttribute("types" ,typeService.listType());         model.addAttribute("tags" ,tagService.listTag());     }     @GetMapping("/blogs/{id}/input")      public  String editInput  (@PathVariable  Long id, Model model)          setTypeAndTag(model);         Blog blog = blogService.getBlog(id);         blog.init();         model.addAttribute("blog" ,blog);         return  INPUT;     }     @PostMapping("/blogs")      public  String post (Blog blog, RedirectAttributes attributes, HttpSession session)          blog.setUser((User) session.getAttribute("user" ));         blog.setType(typeService.getType(blog.getType().getId()));         blog.setTags(tagService.listTag(blog.getTagIds()));         Blog b;         if  (blog.getId() == null ){             b = blogService.saveBlog(blog);         }else  {             b = blogService.updateBlog(blog.getId(),blog);         }         if  (b == null ){             attributes.addFlashAttribute("message" ,"操作失败 ヘ(;´Д`ヘ),管理员大大重新试下吧" );         }else  {             attributes.addFlashAttribute("message" ,"操作成功 ≖‿≖✧ 快去发布新内容吧" );         }         return  REDIRECT_LIST;     }     @GetMapping("/blogs/{id}/delete")      public  String delete (@PathVariable  Long id,RedirectAttributes attributes)          blogService.deleteBlog(id);         attributes.addFlashAttribute("message" ,"删除成功,期待您发布更加美好的内容︿( ̄︶ ̄)︿" );         return  REDIRECT_LIST;     } } 
BlogQuery.java 博客搜索查询类
package  com.cxkj.blog.vo;public  class  BlogQuery           private  String title;     private  Long typeID;     private  boolean  recommend;     public  BlogQuery ()       }     public  String getTitle ()           return  title;     }     public  void  setTitle (String title)           this .title = title;     }     public  Long getTypeID ()           return  typeID;     }     public  void  setTypeID (Long typeID)           this .typeID = typeID;     }     public  boolean  isRecommend ()           return  recommend;     }     public  void  setRecommend (boolean  recommend)           this .recommend = recommend;     } } 
Blog.java 博客实体类
package  com.cxkj.blog.pojo;import  javax.persistence.*;import  java.util.ArrayList;import  java.util.Date;import  java.util.List;@Entity @Table(name = "t_blog") public  class  Blog      @Id      @GeneratedValue      private  Long id;     private  String title;     @Basic(fetch = FetchType.LAZY)      @Lob      private  String content;     private  String firstPicture;     private  String flag;     private  Integer views;     private  boolean  appreciation;     private  boolean  shareStatement;     private  boolean  commentabled;     private  boolean  published;     private  boolean  recommend;     @Temporal(TemporalType.TIMESTAMP)      private  Date createTime;     @Temporal(TemporalType.TIMESTAMP)      private  Date updateTime;     @ManyToOne      private  Type type;     @ManyToMany(cascade = {CascadeType.PERSIST})      private  List<Tag> tags = new  ArrayList<>();     @ManyToOne      private  User user;     @OneToMany(mappedBy = "blog")      private  List<Comment> comments = new  ArrayList<>();     @Transient      private  String tagIds;     private  String description;     public  Blog ()       }     public  Long getId ()           return  id;     }     public  void  setId (Long id)           this .id = id;     }     public  String getTitle ()           return  title;     }     public  void  setTitle (String title)           this .title = title;     }     public  String getContent ()           return  content;     }     public  void  setContent (String content)           this .content = content;     }     public  String getFirstPicture ()           return  firstPicture;     }     public  void  setFirstPicture (String firstPicture)           this .firstPicture = firstPicture;     }     public  String getFlag ()           return  flag;     }     public  void  setFlag (String flag)           this .flag = flag;     }     public  Integer getViews ()           return  views;     }     public  void  setViews (Integer views)           this .views = views;     }     public  boolean  isAppreciation ()           return  appreciation;     }     public  void  setAppreciation (boolean  appreciation)           this .appreciation = appreciation;     }     public  boolean  isShareStatement ()           return  shareStatement;     }     public  void  setShareStatement (boolean  shareStatement)           this .shareStatement = shareStatement;     }     public  boolean  isCommentabled ()           return  commentabled;     }     public  void  setCommentabled (boolean  commentabled)           this .commentabled = commentabled;     }     public  boolean  isPublished ()           return  published;     }     public  void  setPublished (boolean  published)           this .published = published;     }     public  boolean  isRecommend ()           return  recommend;     }     public  void  setRecommend (boolean  recommend)           this .recommend = recommend;     }     public  Date getCreateTime ()           return  createTime;     }     public  void  setCreateTime (Date createTime)           this .createTime = createTime;     }     public  Date getUpdateTime ()           return  updateTime;     }     public  void  setUpdateTime (Date updateTime)           this .updateTime = updateTime;     }     public  Type getType ()           return  type;     }     public  void  setType (Type type)           this .type = type;     }     public  List<Tag> getTags ()           return  tags;     }     public  void  setTags (List<Tag> tags)           this .tags = tags;     }     public  User getUser ()           return  user;     }     public  void  setUser (User user)           this .user = user;     }     public  List<Comment> getComments ()           return  comments;     }     public  void  setComments (List<Comment> comments)           this .comments = comments;     }     public  String getTagIds ()           return  tagIds;     }     public  void  setTagIds (String tagIds)           this .tagIds = tagIds;     }     public  String getDescription ()           return  description;     }     public  void  setDescription (String description)           this .description = description;     }          public  void  init ()          this .tagIds = tagsToIds(this .getTags());     }     private  String tagsToIds (List<Tag> tags)          if  (!tags.isEmpty()){             StringBuffer ids = new  StringBuffer();             boolean  flag = false ;             for  (Tag tag : tags){                 if  (flag){                     ids.append("," );                 }else  {                     flag = true ;                 }                 ids.append(tag.getId());             }             return  ids.toString();         }else  {             return  tagIds;         }     }     @Override      public  String toString ()           return  "Blog{"  +                 "id="  + id +                 ", title='"  + title + '\''  +                 ", content='"  + content + '\''  +                 ", firstPicture='"  + firstPicture + '\''  +                 ", flag='"  + flag + '\''  +                 ", views="  + views +                 ", appreciation="  + appreciation +                 ", shareStatement="  + shareStatement +                 ", commentabled="  + commentabled +                 ", published="  + published +                 ", recommend="  + recommend +                 ", createTime="  + createTime +                 ", updateTime="  + updateTime +                 ", type="  + type +                 ", tags="  + tags +                 ", user="  + user +                 ", comments="  + comments +                 ", tagIds='"  + tagIds + '\''  +                 ", description='"  + description + '\''  +                 '}' ;     } } 
后端细节优化 MyBeanUtils.java 修复SQL数据修改后为null工具类(过滤掉数据值为null)
package  com.cxkj.blog.util;import  org.springframework.beans.BeanWrapper;import  org.springframework.beans.BeanWrapperImpl;import  java.beans.PropertyDescriptor;import  java.util.ArrayList;import  java.util.List;public  class  MyBeanUtils           public  static  String[] getNullPropertyNames(Object source) {         BeanWrapper beanWrapper = new  BeanWrapperImpl(source);         PropertyDescriptor[] pds =  beanWrapper.getPropertyDescriptors();         List<String> nullPropertyNames = new  ArrayList<>();         for  (PropertyDescriptor pd : pds) {             String propertyName = pd.getName();             if  (beanWrapper.getPropertyValue(propertyName) == null ) {                 nullPropertyNames.add(propertyName);             }         }         return  nullPropertyNames.toArray(new  String[nullPropertyNames.size()]);     } } 
前端index优化
package  com.cxkj.blog.service;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;public  interface  BlogService      Blog getBlog (Long id)  ;     Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)  ;          Page<Blog> listBlog (Pageable pageable)  ;     Blog saveBlog (Blog blog)  ;     Blog updateBlog (Long id,Blog blog)  ;     void  deleteBlog (Long id)  } 
BlogServiceImpl.java
package  com.cxkj.blog.service;import  com.cxkj.blog.NotFoundException;import  com.cxkj.blog.dao.BlogRepository;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.pojo.Type;import  com.cxkj.blog.util.MyBeanUtils;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.beans.BeanUtils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  org.springframework.data.jpa.domain.Specification;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  javax.persistence.criteria.CriteriaBuilder;import  javax.persistence.criteria.CriteriaQuery;import  javax.persistence.criteria.Predicate;import  javax.persistence.criteria.Root;import  java.util.ArrayList;import  java.util.Date;import  java.util.List;@Service public  class  BlogServiceImpl  implements  BlogService     @Autowired      private  BlogRepository blogRepository;     @Override      public  Blog getBlog (Long id)           return  blogRepository.findById(id).get();     }     @Override      public  Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)           return  blogRepository.findAll(new  Specification<Blog>() {             @Override              public  Predicate toPredicate (Root<Blog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder)                   List<Predicate> predicateList = new  ArrayList<>();                 if  (!"" .equals(blogQuery.getTitle()) && blogQuery.getTitle() != null ){                     predicateList.add(criteriaBuilder.like(root.<String>get("title" ),"%" +blogQuery.getTitle()+"%" ));                 }                 if  (blogQuery.getTypeID() != null ){                     predicateList.add(criteriaBuilder.equal(root.<Type>get("type" ).get("id" ),blogQuery.getTypeID()));                 }                 if  (blogQuery.isRecommend()){                     predicateList.add(criteriaBuilder.equal(root.<Boolean>get("recommend" ),blogQuery.isRecommend()));                 }                 criteriaQuery.where(predicateList.toArray(new  Predicate[predicateList.size()]));                 return  null ;             }         },pageable);     }     @Override      public  Page<Blog> listBlog (Pageable pageable)           return  blogRepository.findAll(pageable);     }     @Transactional      @Override      public  Blog saveBlog (Blog blog)           if  (blog.getId() == null ){             blog.setCreateTime(new  Date());             blog.setUpdateTime(new  Date());             blog.setViews(0 );         }else  {             blog.setUpdateTime(new  Date());         }         return  blogRepository.save(blog);     }     @Transactional      @Override      public  Blog updateBlog (Long id, Blog blog)           Blog b = blogRepository.findById(id).get();         if  (b == null ){             throw  new  NotFoundException("管理员大大,这个博客不存在哦!~( TロT)σ" );         }         BeanUtils.copyProperties(blog,b, MyBeanUtils.getNullPropertyNames(blog));         b.setUpdateTime(new  Date());         return  blogRepository.save(b);     }     @Transactional      @Override      public  void  deleteBlog (Long id)           blogRepository.deleteById(id);     } } 
IndexController.java
package  com.cxkj.blog.web;import  com.cxkj.blog.service.BlogService;import  com.cxkj.blog.service.TagService;import  com.cxkj.blog.service.TypeService;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.data.web.PageableDefault;import  org.springframework.stereotype.Controller;import  org.springframework.ui.Model;import  org.springframework.web.bind.annotation.GetMapping;@Controller public  class  IndexController      @Autowired      private  BlogService blogService;     @Autowired      private  TypeService typeService;     @Autowired      private  TagService tagService;     @GetMapping("/")      public  String index (@PageableDefault(size = 10,sort = {"updateTime"},direction = Sort.Direction.DESC) Pageable pageable, Model model)          model.addAttribute("page" ,blogService.listBlog(pageable));         model.addAttribute("types" ,typeService.listTypeTop(6 ));         model.addAttribute("tags" ,tagService.listTagTop(10 ));         model.addAttribute("recommendBlogs" ,blogService.listRecommendBlogTop(8 ));         return  "index" ;     }     @GetMapping("/blog")      public  String blog ()                       return  "blog" ;     } } 
TypeService.java
package  com.cxkj.blog.service;import  com.cxkj.blog.pojo.Type;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  java.util.List;public  interface  TypeService      Type saveType (Type type)  ;     Type getType (Long id)  ;     Type getTypeByName (String name)  ;     Page<Type> listType (Pageable pageable)  ;     List<Type> listType ()  ;     List<Type> listTypeTop (Integer size)  ;     Type updateType (Long id,Type type)  ;     void  deleteType (Long id)  } 
TypeServiceImpl.java
package  com.cxkj.blog.service;import  com.cxkj.blog.NotFoundException;import  com.cxkj.blog.dao.TypeRepository;import  com.cxkj.blog.pojo.Type;import  org.springframework.beans.BeanUtils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.PageRequest;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  java.util.List;@Service public  class  TypeServiceImpl  implements  TypeService     @Autowired      private  TypeRepository typeRepository;     @Transactional      @Override      public  Type saveType (Type type)           return  typeRepository.save(type);     }     @Transactional      @Override      public  Type getType (Long id)           return  typeRepository.findById(id).get();     }     @Override      public  Type getTypeByName (String name)           return  typeRepository.findByName(name);     }     @Transactional      @Override      public  Page<Type> listType (Pageable pageable)           return  typeRepository.findAll(pageable);     }     @Override      public  List<Type> listType ()           return  typeRepository.findAll();     }     @Override      public  List<Type> listTypeTop (Integer size)           Sort sort = Sort.by(Sort.Direction.DESC,"blogs.size" );         Pageable pageable = PageRequest.of(0 ,size,sort);         return  typeRepository.findTop(pageable);     }     @Transactional      @Override      public  Type updateType (Long id, Type type)           Type t = typeRepository.findById(id).get();         if  (t == null ){             throw  new  NotFoundException("您查找的信息不存在(︶︹︺)" );         }         BeanUtils.copyProperties(type,t);         return  typeRepository.save(t);     }     @Transactional      @Override      public  void  deleteType (Long id)           typeRepository.deleteById(id);     } } 
TypeRepository.java
package  com.cxkj.blog.dao;import  com.cxkj.blog.pojo.Type;import  org.springframework.data.domain.Pageable;import  org.springframework.data.jpa.repository.JpaRepository;import  org.springframework.data.jpa.repository.Query;import  java.util.List;public  interface  TypeRepository  extends  JpaRepository <Type ,Long >     Type findByName (String name)  ;          @Query("select t from Type t")      List<Type> findTop (Pageable pageable)  ; } 
TagService.java
package  com.cxkj.blog.service;import  com.cxkj.blog.pojo.Tag;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  java.util.List;public  interface  TagService      Tag saveTag (Tag tag)  ;     Tag getTag (Long id)  ;     Tag getTagByName (String name)  ;     Page<Tag> listTag (Pageable pageable)  ;     List<Tag> listTag ()  ;          List<Tag> listTagTop (Integer size)  ;     List<Tag> listTag (String ids)  ;     Tag updateTag (Long id,Tag tag)  ;     void  deleteTag (Long id)  } 
TagServiceImpl.java
package  com.cxkj.blog.service;import  com.cxkj.blog.NotFoundException;import  com.cxkj.blog.dao.TagRepository;import  com.cxkj.blog.pojo.Tag;import  org.springframework.beans.BeanUtils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.PageRequest;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  java.util.ArrayList;import  java.util.List;@Service public  class  TagServiceImpl  implements  TagService     @Autowired      private  TagRepository tagRepository;     @Transactional      @Override      public  Tag saveTag (Tag tag)           return  tagRepository.save(tag);     }     @Transactional      @Override      public  Tag getTag (Long id)           return  tagRepository.findById(id).get();     }     @Transactional      @Override      public  Tag getTagByName (String name)           return  tagRepository.findByName(name);     }     @Transactional      @Override      public  Page<Tag> listTag (Pageable pageable)           return  tagRepository.findAll(pageable);     }     @Override      public  List<Tag> listTag ()           return  tagRepository.findAll();     }     @Override      public  List<Tag> listTagTop (Integer size)           Sort sort =  Sort.by(Sort.Direction.DESC,"blogs.size" );         Pageable pageable = PageRequest.of (0 ,size,sort);         return  tagRepository.findTop(pageable);     }     @Override      public  List<Tag> listTag (String ids)           return  tagRepository.findAllById(convertToList(ids));     }     private  List<Long> convertToList (String ids)          List<Long> list = new  ArrayList<>();         if  (!"" .equals(ids) && ids != null ){             String[] idarray = ids.split("," );             for  (int  i=0 ; i<idarray.length; i++){                 list.add(new  Long(idarray[i]));             }         }         return  list;     }     @Transactional      @Override      public  Tag updateTag (Long id, Tag tag)           Tag t = tagRepository.findById(id).get();         if  (t == null ){             throw  new  NotFoundException("您查找的信息不存在(︶︹︺)" );         }         BeanUtils.copyProperties(tag,t);         return  tagRepository.save(t);     }     @Transactional      @Override      public  void  deleteTag (Long id)           tagRepository.deleteById(id);     } } 
TagRepository.java
package  com.cxkj.blog.dao;import  com.cxkj.blog.pojo.Tag;import  org.springframework.data.domain.Pageable;import  org.springframework.data.jpa.repository.JpaRepository;import  org.springframework.data.jpa.repository.Query;import  java.util.List;public  interface  TagRepository  extends  JpaRepository <Tag ,Long >     Tag findByName (String name)  ;     @Query("select t from Tag t")      List<Tag> findTop (Pageable pageable)  ; } 
BlogService.java
package  com.cxkj.blog.service;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  java.util.List;public  interface  BlogService      Blog getBlog (Long id)  ;     Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)  ;     Page<Blog> listBlog (Pageable pageable)  ;     List<Blog> listRecommendBlogTop (Integer size)  ;     Blog saveBlog (Blog blog)  ;     Blog updateBlog (Long id,Blog blog)  ;     void  deleteBlog (Long id)  } 
BlogServiceImpl.java
package  com.cxkj.blog.service;import  com.cxkj.blog.NotFoundException;import  com.cxkj.blog.dao.BlogRepository;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.pojo.Type;import  com.cxkj.blog.util.MyBeanUtils;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.beans.BeanUtils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.PageRequest;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.data.jpa.domain.Specification;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  javax.persistence.criteria.CriteriaBuilder;import  javax.persistence.criteria.CriteriaQuery;import  javax.persistence.criteria.Predicate;import  javax.persistence.criteria.Root;import  java.util.ArrayList;import  java.util.Date;import  java.util.List;@Service public  class  BlogServiceImpl  implements  BlogService     @Autowired      private  BlogRepository blogRepository;     @Override      public  Blog getBlog (Long id)           return  blogRepository.findById(id).get();     }     @Override      public  Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)           return  blogRepository.findAll(new  Specification<Blog>() {             @Override              public  Predicate toPredicate (Root<Blog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder)                   List<Predicate> predicateList = new  ArrayList<>();                 if  (!"" .equals(blogQuery.getTitle()) && blogQuery.getTitle() != null ){                     predicateList.add(criteriaBuilder.like(root.<String>get("title" ),"%" +blogQuery.getTitle()+"%" ));                 }                 if  (blogQuery.getTypeID() != null ){                     predicateList.add(criteriaBuilder.equal(root.<Type>get("type" ).get("id" ),blogQuery.getTypeID()));                 }                 if  (blogQuery.isRecommend()){                     predicateList.add(criteriaBuilder.equal(root.<Boolean>get("recommend" ),blogQuery.isRecommend()));                 }                 criteriaQuery.where(predicateList.toArray(new  Predicate[predicateList.size()]));                 return  null ;             }         },pageable);     }     @Override      public  Page<Blog> listBlog (Pageable pageable)           return  blogRepository.findAll(pageable);     }     @Override      public  List<Blog> listRecommendBlogTop (Integer size)           Sort sort = Sort.by(Sort.Direction.DESC,"updateTime" );         Pageable pageable = PageRequest.of(0 ,size,sort);         return  blogRepository.findTop(pageable);     }     @Transactional      @Override      public  Blog saveBlog (Blog blog)           if  (blog.getId() == null ){             blog.setCreateTime(new  Date());             blog.setUpdateTime(new  Date());             blog.setViews(0 );         }else  {             blog.setUpdateTime(new  Date());         }         return  blogRepository.save(blog);     }     @Transactional      @Override      public  Blog updateBlog (Long id, Blog blog)           Blog b = blogRepository.findById(id).get();         if  (b == null ){             throw  new  NotFoundException("管理员大大,这个博客不存在哦!~( TロT)σ" );         }         BeanUtils.copyProperties(blog,b, MyBeanUtils.getNullPropertyNames(blog));         b.setUpdateTime(new  Date());         return  blogRepository.save(b);     }     @Transactional      @Override      public  void  deleteBlog (Long id)           blogRepository.deleteById(id);     } } 
BlogRepository.java
package  com.cxkj.blog.dao;import  com.cxkj.blog.pojo.Blog;import  org.springframework.data.domain.Pageable;import  org.springframework.data.jpa.repository.JpaRepository;import  org.springframework.data.jpa.repository.JpaSpecificationExecutor;import  org.springframework.data.jpa.repository.Query;import  java.util.List;public  interface  BlogRepository  extends  JpaRepository <Blog ,Long >, JpaSpecificationExecutor <Blog >     @Query("select b from Blog b where b.recommend = true")      List<Blog> findTop (Pageable pageable)  ; } 
全局搜索 IndexController.java
package  com.cxkj.blog.web;import  com.cxkj.blog.service.BlogService;import  com.cxkj.blog.service.TagService;import  com.cxkj.blog.service.TypeService;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.data.web.PageableDefault;import  org.springframework.stereotype.Controller;import  org.springframework.ui.Model;import  org.springframework.web.bind.annotation.GetMapping;import  org.springframework.web.bind.annotation.PostMapping;import  org.springframework.web.bind.annotation.RequestParam;@Controller public  class  IndexController      @Autowired      private  BlogService blogService;     @Autowired      private  TypeService typeService;     @Autowired      private  TagService tagService;     @GetMapping("/")      public  String index (@PageableDefault(size = 10,sort = {"updateTime"},direction = Sort.Direction.DESC) Pageable pageable, Model model)          model.addAttribute("page" ,blogService.listBlog(pageable));         model.addAttribute("types" ,typeService.listTypeTop(6 ));         model.addAttribute("tags" ,tagService.listTagTop(10 ));         model.addAttribute("recommendBlogs" ,blogService.listRecommendBlogTop(8 ));         return  "index" ;     }     @PostMapping("/search")      public  String search (@PageableDefault(size = 10,sort = {"updateTime"},direction = Sort.Direction.DESC) Pageable pageable, @RequestParam  String query, Model model)          model.addAttribute("page" ,blogService.listBlog("%" +query+"%" ,pageable));         model.addAttribute("query" ,query);         return  "search" ;     }     @GetMapping("/blog/{id}")      public  String blog ()                       return  "blog" ;     } } 
BlogService.java
package  com.cxkj.blog.service;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  java.util.List;public  interface  BlogService      Blog getBlog (Long id)  ;     Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)  ;     Page<Blog> listBlog (Pageable pageable)  ;     Page<Blog> listBlog (String query,Pageable pageable)  ;     List<Blog> listRecommendBlogTop (Integer size)  ;     Blog saveBlog (Blog blog)  ;     Blog updateBlog (Long id,Blog blog)  ;     void  deleteBlog (Long id)  } 
BlogServiceImpl.java
package  com.cxkj.blog.service;import  com.cxkj.blog.NotFoundException;import  com.cxkj.blog.dao.BlogRepository;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.pojo.Type;import  com.cxkj.blog.util.MyBeanUtils;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.beans.BeanUtils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.PageRequest;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.data.jpa.domain.Specification;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  javax.persistence.criteria.CriteriaBuilder;import  javax.persistence.criteria.CriteriaQuery;import  javax.persistence.criteria.Predicate;import  javax.persistence.criteria.Root;import  java.util.ArrayList;import  java.util.Date;import  java.util.List;@Service public  class  BlogServiceImpl  implements  BlogService     @Autowired      private  BlogRepository blogRepository;     @Override      public  Blog getBlog (Long id)           return  blogRepository.findById(id).get();     }     @Override      public  Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)           return  blogRepository.findAll(new  Specification<Blog>() {             @Override              public  Predicate toPredicate (Root<Blog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder)                   List<Predicate> predicateList = new  ArrayList<>();                 if  (!"" .equals(blogQuery.getTitle()) && blogQuery.getTitle() != null ){                     predicateList.add(criteriaBuilder.like(root.<String>get("title" ),"%" +blogQuery.getTitle()+"%" ));                 }                 if  (blogQuery.getTypeID() != null ){                     predicateList.add(criteriaBuilder.equal(root.<Type>get("type" ).get("id" ),blogQuery.getTypeID()));                 }                 if  (blogQuery.isRecommend()){                     predicateList.add(criteriaBuilder.equal(root.<Boolean>get("recommend" ),blogQuery.isRecommend()));                 }                 criteriaQuery.where(predicateList.toArray(new  Predicate[predicateList.size()]));                 return  null ;             }         },pageable);     }     @Override      public  Page<Blog> listBlog (Pageable pageable)           return  blogRepository.findAll(pageable);     }     @Override      public  Page<Blog> listBlog (String query, Pageable pageable)           return  blogRepository.findByQuery(query,pageable);     }     @Override      public  List<Blog> listRecommendBlogTop (Integer size)           Sort sort = Sort.by(Sort.Direction.DESC,"updateTime" );         Pageable pageable = PageRequest.of(0 ,size,sort);         return  blogRepository.findTop(pageable);     }     @Transactional      @Override      public  Blog saveBlog (Blog blog)           if  (blog.getId() == null ){             blog.setCreateTime(new  Date());             blog.setUpdateTime(new  Date());             blog.setViews(0 );         }else  {             blog.setUpdateTime(new  Date());         }         return  blogRepository.save(blog);     }     @Transactional      @Override      public  Blog updateBlog (Long id, Blog blog)           Blog b = blogRepository.findById(id).get();         if  (b == null ){             throw  new  NotFoundException("管理员大大,这个博客不存在哦!~( TロT)σ" );         }         BeanUtils.copyProperties(blog,b, MyBeanUtils.getNullPropertyNames(blog));         b.setUpdateTime(new  Date());         return  blogRepository.save(b);     }     @Transactional      @Override      public  void  deleteBlog (Long id)           blogRepository.deleteById(id);     } } 
BlogRepository.java
package  com.cxkj.blog.dao;import  com.cxkj.blog.pojo.Blog;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  org.springframework.data.jpa.repository.JpaRepository;import  org.springframework.data.jpa.repository.JpaSpecificationExecutor;import  org.springframework.data.jpa.repository.Query;import  java.util.List;public  interface  BlogRepository  extends  JpaRepository <Blog ,Long >, JpaSpecificationExecutor <Blog >     @Query("select b from Blog b where b.recommend = true")      List<Blog> findTop (Pageable pageable)  ;          @Query("select b from Blog b where b.title like ?1 or b.content like ?1")      Page<Blog> findByQuery (String query,Pageable pageable)  ; } 
博客详情业务处理 IndexController.java
package  com.cxkj.blog.web;import  com.cxkj.blog.service.BlogService;import  com.cxkj.blog.service.TagService;import  com.cxkj.blog.service.TypeService;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.data.web.PageableDefault;import  org.springframework.stereotype.Controller;import  org.springframework.ui.Model;import  org.springframework.web.bind.annotation.GetMapping;import  org.springframework.web.bind.annotation.PathVariable;import  org.springframework.web.bind.annotation.PostMapping;import  org.springframework.web.bind.annotation.RequestParam;@Controller public  class  IndexController      @Autowired      private  BlogService blogService;     @Autowired      private  TypeService typeService;     @Autowired      private  TagService tagService;     @GetMapping("/")      public  String index (@PageableDefault(size = 10,sort = {"updateTime"},direction = Sort.Direction.DESC) Pageable pageable, Model model)          model.addAttribute("page" ,blogService.listBlog(pageable));         model.addAttribute("types" ,typeService.listTypeTop(6 ));         model.addAttribute("tags" ,tagService.listTagTop(10 ));         model.addAttribute("recommendBlogs" ,blogService.listRecommendBlogTop(8 ));         return  "index" ;     }     @PostMapping("/search")      public  String search (@PageableDefault(size = 10,sort = {"updateTime"},direction = Sort.Direction.DESC) Pageable pageable, @RequestParam  String query, Model model)          model.addAttribute("page" ,blogService.listBlog("%" +query+"%" ,pageable));         model.addAttribute("query" ,query);         return  "search" ;     }     @GetMapping("/blog/{id}")      public  String blog (@PathVariable  Long id, Model model)          model.addAttribute("blog" ,blogService.getAndConvert(id));         return  "blog" ;     } } 
MarkdownUtils.java Markdown转换HTML工具类
package  com.cxkj.blog.util;import  org.commonmark.Extension;import  org.commonmark.ext.gfm.tables.TableBlock;import  org.commonmark.ext.gfm.tables.TablesExtension;import  org.commonmark.ext.heading.anchor.HeadingAnchorExtension;import  org.commonmark.node.Link;import  org.commonmark.node.Node;import  org.commonmark.parser.Parser;import  org.commonmark.renderer.html.AttributeProvider;import  org.commonmark.renderer.html.AttributeProviderContext;import  org.commonmark.renderer.html.AttributeProviderFactory;import  org.commonmark.renderer.html.HtmlRenderer;import  java.util.*;public  class  MarkdownUtils           public  static  String markdownToHtml (String markdown)           Parser parser = Parser.builder().build();         Node document = parser.parse(markdown);         HtmlRenderer renderer = HtmlRenderer.builder().build();         return  renderer.render(document);     }          public  static  String markdownToHtmlExtensions (String markdown)                    Set<Extension> headingAnchorExtensions = Collections.singleton(HeadingAnchorExtension.create());                  List<Extension> tableExtension = Arrays.asList(TablesExtension.create());         Parser parser = Parser.builder()                 .extensions(tableExtension)                 .build();         Node document = parser.parse(markdown);         HtmlRenderer renderer = HtmlRenderer.builder()                 .extensions(headingAnchorExtensions)                 .extensions(tableExtension)                 .attributeProviderFactory(new  AttributeProviderFactory() {                     public  AttributeProvider create (AttributeProviderContext context)                           return  new  CustomAttributeProvider();                     }                 })                 .build();         return  renderer.render(document);     }          static  class  CustomAttributeProvider  implements  AttributeProvider           @Override          public  void  setAttributes (Node node, String tagName, Map<String, String> attributes)                            if  (node instanceof  Link) {                 attributes.put("target" , "_blank" );             }             if  (node instanceof  TableBlock) {                 attributes.put("class" , "ui celled table" );             }         }     }     public  static  void  main (String[] args)           String table = "| hello | hi   | 哈哈哈   |\n"  +                 "| ----- | ---- | ----- |\n"  +                 "| 斯维尔多  | 士大夫  | f啊    |\n"  +                 "| 阿什顿发  | 非固定杆 | 撒阿什顿发 |\n"  +                 "\n" ;         String a = "[imCoding 爱编程](http://www.lirenmi.cn)" ;         System.out.println(markdownToHtmlExtensions(a));     } } 
BlogService.java
package  com.cxkj.blog.service;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  java.util.List;public  interface  BlogService      Blog getBlog (Long id)  ;     Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)  ;     Page<Blog> listBlog (Pageable pageable)  ;     Page<Blog> listBlog (String query,Pageable pageable)  ;          Blog getAndConvert (Long id)  ;     List<Blog> listRecommendBlogTop (Integer size)  ;     Blog saveBlog (Blog blog)  ;     Blog updateBlog (Long id,Blog blog)  ;     void  deleteBlog (Long id)  } 
BlogServiceImpl.java
package  com.cxkj.blog.service;import  com.cxkj.blog.NotFoundException;import  com.cxkj.blog.dao.BlogRepository;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.pojo.Type;import  com.cxkj.blog.util.MarkdownUtils;import  com.cxkj.blog.util.MyBeanUtils;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.beans.BeanUtils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.PageRequest;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.data.jpa.domain.Specification;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  javax.persistence.criteria.CriteriaBuilder;import  javax.persistence.criteria.CriteriaQuery;import  javax.persistence.criteria.Predicate;import  javax.persistence.criteria.Root;import  java.util.ArrayList;import  java.util.Date;import  java.util.List;@Service public  class  BlogServiceImpl  implements  BlogService     @Autowired      private  BlogRepository blogRepository;     @Override      public  Blog getBlog (Long id)           return  blogRepository.findById(id).get();     }     @Override      public  Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)           return  blogRepository.findAll(new  Specification<Blog>() {             @Override              public  Predicate toPredicate (Root<Blog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder)                   List<Predicate> predicateList = new  ArrayList<>();                 if  (!"" .equals(blogQuery.getTitle()) && blogQuery.getTitle() != null ){                     predicateList.add(criteriaBuilder.like(root.<String>get("title" ),"%" +blogQuery.getTitle()+"%" ));                 }                 if  (blogQuery.getTypeID() != null ){                     predicateList.add(criteriaBuilder.equal(root.<Type>get("type" ).get("id" ),blogQuery.getTypeID()));                 }                 if  (blogQuery.isRecommend()){                     predicateList.add(criteriaBuilder.equal(root.<Boolean>get("recommend" ),blogQuery.isRecommend()));                 }                 criteriaQuery.where(predicateList.toArray(new  Predicate[predicateList.size()]));                 return  null ;             }         },pageable);     }     @Override      public  Page<Blog> listBlog (Pageable pageable)           return  blogRepository.findAll(pageable);     }     @Override      public  Page<Blog> listBlog (String query, Pageable pageable)           return  blogRepository.findByQuery(query,pageable);     }     @Override      public  Blog getAndConvert (Long id)           Blog blog = blogRepository.findById(id).get();         if  (blog == null ){             throw  new  NotFoundException("博客不存在哦" );         }         Blog b = new  Blog();         BeanUtils.copyProperties(blog,b);         String content = b.getContent();         b.setContent(MarkdownUtils.markdownToHtmlExtensions(content));         return  b;     }     @Override      public  List<Blog> listRecommendBlogTop (Integer size)           Sort sort = Sort.by(Sort.Direction.DESC,"updateTime" );         Pageable pageable = PageRequest.of(0 ,size,sort);         return  blogRepository.findTop(pageable);     }     @Transactional      @Override      public  Blog saveBlog (Blog blog)           if  (blog.getId() == null ){             blog.setCreateTime(new  Date());             blog.setUpdateTime(new  Date());             blog.setViews(0 );         }else  {             blog.setUpdateTime(new  Date());         }         return  blogRepository.save(blog);     }     @Transactional      @Override      public  Blog updateBlog (Long id, Blog blog)           Blog b = blogRepository.findById(id).get();         if  (b == null ){             throw  new  NotFoundException("管理员大大,这个博客不存在哦!~( TロT)σ" );         }         BeanUtils.copyProperties(blog,b, MyBeanUtils.getNullPropertyNames(blog));         b.setUpdateTime(new  Date());         return  blogRepository.save(b);     }     @Transactional      @Override      public  void  deleteBlog (Long id)           blogRepository.deleteById(id);     } } 
评论模块实现 CommentController.java
package  com.cxkj.blog.web;import  com.cxkj.blog.pojo.Comment;import  com.cxkj.blog.service.BlogService;import  com.cxkj.blog.service.CommentService;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.beans.factory.annotation.Value;import  org.springframework.stereotype.Controller;import  org.springframework.ui.Model;import  org.springframework.web.bind.annotation.GetMapping;import  org.springframework.web.bind.annotation.PathVariable;import  org.springframework.web.bind.annotation.PostMapping;import  javax.validation.Valid;@Controller public  class  CommentController      @Autowired      private  CommentService commentService;     @Autowired      private  BlogService blogService;     @Value("${comment.avatar}")      private  String avatar;     @GetMapping("/comments/{blogId}")      public  String comments (@PathVariable  Long blogId, Model model)          model.addAttribute("comments" ,commentService.listCommentByBlogId(blogId));         return  "blog :: commentList" ;     }     @PostMapping("/comments")      public  String post (Comment comment)           Long blogId = comment.getBlog().getId();         comment.setBlog(blogService.getBlog(blogId));         comment.setAvatar(avatar);         commentService.saveComment(comment);         return  "redirect:/comments/"  + blogId;     } } 
CommentService.java
package  com.cxkj.blog.service;import  com.cxkj.blog.pojo.Comment;import  java.util.List;public  interface  CommentService      List<Comment> listCommentByBlogId (Long blogId)  ;     Comment saveComment (Comment comment)  ; } 
CommentServiceImpl.java
package  com.cxkj.blog.service;import  com.cxkj.blog.dao.CommentRepository;import  com.cxkj.blog.pojo.Comment;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Sort;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  java.util.Date;import  java.util.List;@Service public  class  CommentServiceImpl  implements  CommentService     @Autowired      private  CommentRepository commentRepository;     @Override      public  List<Comment> listCommentByBlogId (Long blogId)           Sort sort = Sort.by(Sort.Direction.DESC,"createTime" );         return  commentRepository.findByBlogId(blogId,sort);     }     @Transactional      @Override      public  Comment saveComment (Comment comment)           Long parentCommentId = comment.getParentComment().getId();         if  (parentCommentId != -1 ){             comment.setParentComment(commentRepository.findById(parentCommentId).get());         }else  {             comment.setParentComment(null );         }         comment.setCreateTime(new  Date());         return  commentRepository.save(comment);     } } 
CommentRepository.java
package  com.cxkj.blog.dao;import  com.cxkj.blog.pojo.Comment;import  org.springframework.data.domain.Sort;import  org.springframework.data.jpa.repository.JpaRepository;import  java.util.List;public  interface  CommentRepository  extends  JpaRepository <Comment ,Long >     List<Comment> findByBlogId (Long blogId, Sort sort)  ; } 
评论模块细节优化 CommentRepository.java
package  com.cxkj.blog.dao;import  com.cxkj.blog.pojo.Comment;import  org.springframework.data.domain.Sort;import  org.springframework.data.jpa.repository.JpaRepository;import  java.util.List;public  interface  CommentRepository  extends  JpaRepository <Comment ,Long >     List<Comment> findByBlogIdAndParentCommentNull (Long blogId, Sort sort)  ; } 
CommentServiceImpl.java
package  com.cxkj.blog.service;import  com.cxkj.blog.dao.CommentRepository;import  com.cxkj.blog.pojo.Comment;import  org.springframework.beans.BeanUtils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Sort;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  java.util.ArrayList;import  java.util.Date;import  java.util.List;@Service public  class  CommentServiceImpl  implements  CommentService     @Autowired      private  CommentRepository commentRepository;     @Override      public  List<Comment> listCommentByBlogId (Long blogId)           Sort sort = Sort.by(Sort.Direction.DESC,"createTime" );         List<Comment> comments = commentRepository.findByBlogIdAndParentCommentNull(blogId,sort);         return  eachComment(comments);     }     @Transactional      @Override      public  Comment saveComment (Comment comment)           Long parentCommentId = comment.getParentComment().getId();         if  (parentCommentId != -1 ){             comment.setParentComment(commentRepository.findById(parentCommentId).get());         }else  {             comment.setParentComment(null );         }         comment.setCreateTime(new  Date());         return  commentRepository.save(comment);     }          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> replys = comment.getReplyComments();             for  (Comment reply : replys){                                  recursively(reply);             }                          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> replays = comment.getReplyComments();             for  (Comment reply : replays) {                 tempReplys.add(reply);                 if  (reply.getReplyComments().size()>0 ) {                     recursively(reply);                 }             }         }     } } 
CommentController.java
package  com.cxkj.blog.web;import  com.cxkj.blog.pojo.Comment;import  com.cxkj.blog.service.BlogService;import  com.cxkj.blog.service.CommentService;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.beans.factory.annotation.Value;import  org.springframework.stereotype.Controller;import  org.springframework.ui.Model;import  org.springframework.web.bind.annotation.GetMapping;import  org.springframework.web.bind.annotation.PathVariable;import  org.springframework.web.bind.annotation.PostMapping;import  javax.validation.Valid;@Controller public  class  CommentController      @Autowired      private  CommentService commentService;     @Autowired      private  BlogService blogService;     @Value("${comment.avatar}")      private  String avatar;     @GetMapping("/comments/{blogId}")      public  String comments (@PathVariable  Long blogId, Model model)          model.addAttribute("comments" ,commentService.listCommentByBlogId(blogId));         return  "blog :: commentList" ;     }     @PostMapping("/comments")      public  String post (Comment comment)           Long blogId = comment.getBlog().getId();         comment.setBlog(blogService.getBlog(blogId));         comment.setAvatar(avatar);         commentService.saveComment(comment);         return  "redirect:/comments/"  + blogId;     } } 
特殊用户评论模块 CommentServiceImpl.java
package  com.cxkj.blog.service;import  com.cxkj.blog.dao.CommentRepository;import  com.cxkj.blog.pojo.Comment;import  org.springframework.beans.BeanUtils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Sort;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  java.util.ArrayList;import  java.util.Date;import  java.util.List;@Service public  class  CommentServiceImpl  implements  CommentService     @Autowired      private  CommentRepository commentRepository;     @Override      public  List<Comment> listCommentByBlogId (Long blogId)           Sort sort = Sort.by(Sort.Direction.ASC,"createTime" );         List<Comment> comments = commentRepository.findByBlogIdAndParentCommentNull(blogId,sort);         return  eachComment(comments);     }     @Transactional      @Override      public  Comment saveComment (Comment comment)           Long parentCommentId = comment.getParentComment().getId();         if  (parentCommentId != -1 ){             comment.setParentComment(commentRepository.findById(parentCommentId).get());         }else  {             comment.setParentComment(null );         }         comment.setCreateTime(new  Date());         return  commentRepository.save(comment);     }          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> replys = comment.getReplyComments();             for  (Comment reply : replys){                                  recursively(reply);             }                          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> replays = comment.getReplyComments();             for  (Comment reply : replays) {                 tempReplys.add(reply);                 if  (reply.getReplyComments().size()>0 ) {                     recursively(reply);                 }             }         }     } } 
Comment.java
package  com.cxkj.blog.pojo;import  javax.persistence.*;import  java.util.ArrayList;import  java.util.Date;import  java.util.List;@Entity @Table(name = "t_comment") public  class  Comment      @Id      @GeneratedValue      private  Long id;     private  String nickname;     private  String email;     private  String content;     private  String avatar;     @Temporal(TemporalType.TIMESTAMP)      private  Date createTime;     @ManyToOne      private  Blog blog;     @OneToMany(mappedBy = "parentComment")      private  List<Comment> replyComments = new  ArrayList<>();     @ManyToOne      private  Comment parentComment;          private  boolean  adminComment;     public  Comment ()       }     public  Long getId ()           return  id;     }     public  void  setId (Long id)           this .id = id;     }     public  String getNickname ()           return  nickname;     }     public  void  setNickname (String nickname)           this .nickname = nickname;     }     public  String getEmail ()           return  email;     }     public  void  setEmail (String email)           this .email = email;     }     public  String getContent ()           return  content;     }     public  void  setContent (String content)           this .content = content;     }     public  String getAvatar ()           return  avatar;     }     public  void  setAvatar (String avatar)           this .avatar = avatar;     }     public  Date getCreateTime ()           return  createTime;     }     public  void  setCreateTime (Date createTime)           this .createTime = createTime;     }     public  Blog getBlog ()           return  blog;     }     public  void  setBlog (Blog blog)           this .blog = blog;     }     public  List<Comment> getReplyComments ()           return  replyComments;     }     public  void  setReplyComments (List<Comment> replyComments)           this .replyComments = replyComments;     }     public  Comment getParentComment ()           return  parentComment;     }     public  void  setParentComment (Comment parentComment)           this .parentComment = parentComment;     }     public  boolean  isAdminComment ()           return  adminComment;     }     public  void  setAdminComment (boolean  adminComment)           this .adminComment = adminComment;     }     @Override      public  String toString ()           return  "Comment{"  +                 "id="  + id +                 ", nickname='"  + nickname + '\''  +                 ", email='"  + email + '\''  +                 ", content='"  + content + '\''  +                 ", avatar='"  + avatar + '\''  +                 ", createTime="  + createTime +                 ", blog="  + blog +                 ", replyComments="  + replyComments +                 ", parentComment="  + parentComment +                 ", adminComment="  + adminComment +                 '}' ;     } } 
浏览次数模块 BlogRepository.java
package  com.cxkj.blog.dao;import  com.cxkj.blog.pojo.Blog;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  org.springframework.data.jpa.repository.JpaRepository;import  org.springframework.data.jpa.repository.JpaSpecificationExecutor;import  org.springframework.data.jpa.repository.Modifying;import  org.springframework.data.jpa.repository.Query;import  org.springframework.transaction.annotation.Transactional;import  java.util.List;public  interface  BlogRepository  extends  JpaRepository <Blog ,Long >, JpaSpecificationExecutor <Blog >     @Query("select b from Blog b where b.recommend = true")      List<Blog> findTop (Pageable pageable)  ;          @Query("select b from Blog b where b.title like ?1 or b.content like ?1")      Page<Blog> findByQuery (String query,Pageable pageable)  ;          @Transactional      @Modifying      @Query("update Blog b set b.views = b.views+1 where b.id = ?1")      int  updateViews (Long id)  } 
BlogServiceImpl.java
package  com.cxkj.blog.service;import  com.cxkj.blog.NotFoundException;import  com.cxkj.blog.dao.BlogRepository;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.pojo.Type;import  com.cxkj.blog.util.MarkdownUtils;import  com.cxkj.blog.util.MyBeanUtils;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.beans.BeanUtils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.PageRequest;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.data.jpa.domain.Specification;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  javax.persistence.criteria.CriteriaBuilder;import  javax.persistence.criteria.CriteriaQuery;import  javax.persistence.criteria.Predicate;import  javax.persistence.criteria.Root;import  java.util.ArrayList;import  java.util.Date;import  java.util.List;@Service public  class  BlogServiceImpl  implements  BlogService     @Autowired      private  BlogRepository blogRepository;     @Override      public  Blog getBlog (Long id)           return  blogRepository.findById(id).get();     }     @Override      public  Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)           return  blogRepository.findAll(new  Specification<Blog>() {             @Override              public  Predicate toPredicate (Root<Blog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder)                   List<Predicate> predicateList = new  ArrayList<>();                 if  (!"" .equals(blogQuery.getTitle()) && blogQuery.getTitle() != null ){                     predicateList.add(criteriaBuilder.like(root.<String>get("title" ),"%" +blogQuery.getTitle()+"%" ));                 }                 if  (blogQuery.getTypeID() != null ){                     predicateList.add(criteriaBuilder.equal(root.<Type>get("type" ).get("id" ),blogQuery.getTypeID()));                 }                 if  (blogQuery.isRecommend()){                     predicateList.add(criteriaBuilder.equal(root.<Boolean>get("recommend" ),blogQuery.isRecommend()));                 }                 criteriaQuery.where(predicateList.toArray(new  Predicate[predicateList.size()]));                 return  null ;             }         },pageable);     }     @Override      public  Page<Blog> listBlog (Pageable pageable)           return  blogRepository.findAll(pageable);     }     @Override      public  Page<Blog> listBlog (String query, Pageable pageable)           return  blogRepository.findByQuery(query,pageable);     }     @Transactional      @Override      public  Blog getAndConvert (Long id)           Blog blog = blogRepository.findById(id).get();         if  (blog == null ){             throw  new  NotFoundException("博客不存在哦" );         }         Blog b = new  Blog();         BeanUtils.copyProperties(blog,b);         String content = b.getContent();         b.setContent(MarkdownUtils.markdownToHtmlExtensions(content));         blogRepository.updateViews(id);         return  b;     }     @Override      public  List<Blog> listRecommendBlogTop (Integer size)           Sort sort = Sort.by(Sort.Direction.DESC,"updateTime" );         Pageable pageable = PageRequest.of(0 ,size,sort);         return  blogRepository.findTop(pageable);     }     @Transactional      @Override      public  Blog saveBlog (Blog blog)           if  (blog.getId() == null ){             blog.setCreateTime(new  Date());             blog.setUpdateTime(new  Date());             blog.setViews(0 );         }else  {             blog.setUpdateTime(new  Date());         }         return  blogRepository.save(blog);     }     @Transactional      @Override      public  Blog updateBlog (Long id, Blog blog)           Blog b = blogRepository.findById(id).get();         if  (b == null ){             throw  new  NotFoundException("管理员大大,这个博客不存在哦!~( TロT)σ" );         }         BeanUtils.copyProperties(blog,b, MyBeanUtils.getNullPropertyNames(blog));         b.setUpdateTime(new  Date());         return  blogRepository.save(b);     }     @Transactional      @Override      public  void  deleteBlog (Long id)           blogRepository.deleteById(id);     } } 
分类Web模块 TypeShowController.java
package  com.cxkj.blog.web;import  com.cxkj.blog.pojo.Type;import  com.cxkj.blog.service.BlogService;import  com.cxkj.blog.service.TypeService;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.data.web.PageableDefault;import  org.springframework.stereotype.Controller;import  org.springframework.ui.Model;import  org.springframework.web.bind.annotation.GetMapping;import  org.springframework.web.bind.annotation.PathVariable;import  java.util.List;@Controller public  class  TypeShowController      @Autowired      private  TypeService typeService;     @Autowired      private  BlogService blogService;     @GetMapping("/types/{id}")      public  String types (@PageableDefault(size = 10,sort = {"updateTime"},direction = Sort.Direction.DESC) Pageable pageable,@PathVariable  Long id, Model model)          List<Type> types = typeService.listTypeTop(10000 );         if  (id == -1 ){             id = types.get(0 ).getId();         }         BlogQuery blogQuery = new  BlogQuery();         blogQuery.setTypeID(id);         model.addAttribute("types" ,types);         model.addAttribute("page" ,blogService.listBlog(pageable,blogQuery));         model.addAttribute("activeTypeId" ,id);         return  "types" ;     } } 
标签Web模块 TagShowController.java
package  com.cxkj.blog.web;import  com.cxkj.blog.pojo.Tag;import  com.cxkj.blog.pojo.Type;import  com.cxkj.blog.service.BlogService;import  com.cxkj.blog.service.TagService;import  com.cxkj.blog.service.TypeService;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.data.web.PageableDefault;import  org.springframework.stereotype.Controller;import  org.springframework.ui.Model;import  org.springframework.web.bind.annotation.GetMapping;import  org.springframework.web.bind.annotation.PathVariable;import  java.util.List;@Controller public  class  TagShowController      @Autowired      private  TagService tagService;     @Autowired      private  BlogService blogService;     @GetMapping("/tags/{id}")      public  String tags (@PageableDefault(size = 10,sort = {"updateTime"},direction = Sort.Direction.DESC) Pageable pageable,@PathVariable  Long id, Model model)          List<Tag> tags = tagService.listTagTop(10000 );         if  (id == -1 ){             id = tags.get(0 ).getId();         }         model.addAttribute("tags" ,tags);         model.addAttribute("page" ,blogService.listBlog(id,pageable));         model.addAttribute("activeTagId" ,id);         return  "tags" ;     } } 
BlogService.java
package  com.cxkj.blog.service;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  java.util.List;public  interface  BlogService      Blog getBlog (Long id)  ;     Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)  ;     Page<Blog> listBlog (Pageable pageable)  ;          Page<Blog> listBlog (Long tagId,Pageable pageable)  ;     Page<Blog> listBlog (String query,Pageable pageable)  ;     Blog getAndConvert (Long id)  ;     List<Blog> listRecommendBlogTop (Integer size)  ;     Blog saveBlog (Blog blog)  ;     Blog updateBlog (Long id,Blog blog)  ;     void  deleteBlog (Long id)  } 
BlogServiceImpl.java
package  com.cxkj.blog.service;import  com.cxkj.blog.NotFoundException;import  com.cxkj.blog.dao.BlogRepository;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.pojo.Type;import  com.cxkj.blog.util.MarkdownUtils;import  com.cxkj.blog.util.MyBeanUtils;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.beans.BeanUtils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.PageRequest;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.data.jpa.domain.Specification;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  javax.persistence.criteria.*;import  java.util.ArrayList;import  java.util.Date;import  java.util.List;@Service public  class  BlogServiceImpl  implements  BlogService     @Autowired      private  BlogRepository blogRepository;     @Override      public  Blog getBlog (Long id)           return  blogRepository.findById(id).get();     }     @Override      public  Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)           return  blogRepository.findAll(new  Specification<Blog>() {             @Override              public  Predicate toPredicate (Root<Blog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder)                   List<Predicate> predicateList = new  ArrayList<>();                 if  (!"" .equals(blogQuery.getTitle()) && blogQuery.getTitle() != null ){                     predicateList.add(criteriaBuilder.like(root.<String>get("title" ),"%" +blogQuery.getTitle()+"%" ));                 }                 if  (blogQuery.getTypeID() != null ){                     predicateList.add(criteriaBuilder.equal(root.<Type>get("type" ).get("id" ),blogQuery.getTypeID()));                 }                 if  (blogQuery.isRecommend()){                     predicateList.add(criteriaBuilder.equal(root.<Boolean>get("recommend" ),blogQuery.isRecommend()));                 }                 criteriaQuery.where(predicateList.toArray(new  Predicate[predicateList.size()]));                 return  null ;             }         },pageable);     }     @Override      public  Page<Blog> listBlog (Pageable pageable)           return  blogRepository.findAll(pageable);     }     @Override      public  Page<Blog> listBlog (Long tagId, Pageable pageable)           return  blogRepository.findAll(new  Specification<Blog>() {             @Override              public  Predicate toPredicate (Root<Blog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder)                   Join join = root.join("tags" );                 return  criteriaBuilder.equal(join.get("id" ),tagId);             }         },pageable);     }     @Override      public  Page<Blog> listBlog (String query, Pageable pageable)           return  blogRepository.findByQuery(query,pageable);     }     @Transactional      @Override      public  Blog getAndConvert (Long id)           Blog blog = blogRepository.findById(id).get();         if  (blog == null ){             throw  new  NotFoundException("博客不存在哦" );         }         Blog b = new  Blog();         BeanUtils.copyProperties(blog,b);         String content = b.getContent();         b.setContent(MarkdownUtils.markdownToHtmlExtensions(content));         blogRepository.updateViews(id);         return  b;     }     @Override      public  List<Blog> listRecommendBlogTop (Integer size)           Sort sort = Sort.by(Sort.Direction.DESC,"updateTime" );         Pageable pageable = PageRequest.of(0 ,size,sort);         return  blogRepository.findTop(pageable);     }     @Transactional      @Override      public  Blog saveBlog (Blog blog)           if  (blog.getId() == null ){             blog.setCreateTime(new  Date());             blog.setUpdateTime(new  Date());             blog.setViews(0 );         }else  {             blog.setUpdateTime(new  Date());         }         return  blogRepository.save(blog);     }     @Transactional      @Override      public  Blog updateBlog (Long id, Blog blog)           Blog b = blogRepository.findById(id).get();         if  (b == null ){             throw  new  NotFoundException("管理员大大,这个博客不存在哦!~( TロT)σ" );         }         BeanUtils.copyProperties(blog,b, MyBeanUtils.getNullPropertyNames(blog));         b.setUpdateTime(new  Date());         return  blogRepository.save(b);     }     @Transactional      @Override      public  void  deleteBlog (Long id)           blogRepository.deleteById(id);     } } 
归档模块处理 ArchiveShowController.java
package  com.cxkj.blog.web;import  com.cxkj.blog.service.BlogService;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.stereotype.Controller;import  org.springframework.ui.Model;import  org.springframework.web.bind.annotation.GetMapping;@Controller public  class  ArchiveShowController      @Autowired      private  BlogService blogService;     @GetMapping("/archives")      public  String archives (Model model)          model.addAttribute("archiveMap" ,blogService.archiveBlog());         model.addAttribute("blogCouot" ,blogService.countBlog());         return  "archives" ;     } } 
BlogService.java
package  com.cxkj.blog.service;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  java.util.List;import  java.util.Map;public  interface  BlogService      Blog getBlog (Long id)  ;     Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)  ;     Page<Blog> listBlog (Pageable pageable)  ;     Page<Blog> listBlog (Long tagId,Pageable pageable)  ;     Page<Blog> listBlog (String query,Pageable pageable)  ;     Blog getAndConvert (Long id)  ;     List<Blog> listRecommendBlogTop (Integer size)  ;          Map<String,List<Blog>> archiveBlog();          Long countBlog ()  ;     Blog saveBlog (Blog blog)  ;     Blog updateBlog (Long id,Blog blog)  ;     void  deleteBlog (Long id)  } 
BlogServiceImpl.java
package  com.cxkj.blog.service;import  com.cxkj.blog.NotFoundException;import  com.cxkj.blog.dao.BlogRepository;import  com.cxkj.blog.pojo.Blog;import  com.cxkj.blog.pojo.Type;import  com.cxkj.blog.util.MarkdownUtils;import  com.cxkj.blog.util.MyBeanUtils;import  com.cxkj.blog.vo.BlogQuery;import  org.springframework.beans.BeanUtils;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.PageRequest;import  org.springframework.data.domain.Pageable;import  org.springframework.data.domain.Sort;import  org.springframework.data.jpa.domain.Specification;import  org.springframework.stereotype.Service;import  org.springframework.transaction.annotation.Transactional;import  javax.persistence.criteria.*;import  java.util.*;@Service public  class  BlogServiceImpl  implements  BlogService     @Autowired      private  BlogRepository blogRepository;     @Override      public  Blog getBlog (Long id)           return  blogRepository.findById(id).get();     }     @Override      public  Page<Blog> listBlog (Pageable pageable, BlogQuery blogQuery)           return  blogRepository.findAll(new  Specification<Blog>() {             @Override              public  Predicate toPredicate (Root<Blog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder)                   List<Predicate> predicateList = new  ArrayList<>();                 if  (!"" .equals(blogQuery.getTitle()) && blogQuery.getTitle() != null ){                     predicateList.add(criteriaBuilder.like(root.<String>get("title" ),"%" +blogQuery.getTitle()+"%" ));                 }                 if  (blogQuery.getTypeID() != null ){                     predicateList.add(criteriaBuilder.equal(root.<Type>get("type" ).get("id" ),blogQuery.getTypeID()));                 }                 if  (blogQuery.isRecommend()){                     predicateList.add(criteriaBuilder.equal(root.<Boolean>get("recommend" ),blogQuery.isRecommend()));                 }                 criteriaQuery.where(predicateList.toArray(new  Predicate[predicateList.size()]));                 return  null ;             }         },pageable);     }     @Override      public  Page<Blog> listBlog (Pageable pageable)           return  blogRepository.findAll(pageable);     }     @Override      public  Page<Blog> listBlog (Long tagId, Pageable pageable)           return  blogRepository.findAll(new  Specification<Blog>() {             @Override              public  Predicate toPredicate (Root<Blog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder)                   Join join = root.join("tags" );                 return  criteriaBuilder.equal(join.get("id" ),tagId);             }         },pageable);     }     @Override      public  Page<Blog> listBlog (String query, Pageable pageable)           return  blogRepository.findByQuery(query,pageable);     }     @Transactional      @Override      public  Blog getAndConvert (Long id)           Blog blog = blogRepository.findById(id).get();         if  (blog == null ){             throw  new  NotFoundException("博客不存在哦" );         }         Blog b = new  Blog();         BeanUtils.copyProperties(blog,b);         String content = b.getContent();         b.setContent(MarkdownUtils.markdownToHtmlExtensions(content));         blogRepository.updateViews(id);         return  b;     }     @Override      public  List<Blog> listRecommendBlogTop (Integer size)           Sort sort = Sort.by(Sort.Direction.DESC,"updateTime" );         Pageable pageable = PageRequest.of(0 ,size,sort);         return  blogRepository.findTop(pageable);     }     @Override      public  Map<String, List<Blog>> archiveBlog() {                  List<String> years = blogRepository.findGroupYear();         Map<String,List<Blog>> map = new  HashMap<>();         for  (String year : years){             map.put(year,blogRepository.findByYear(year));         }         return  map;     }     @Override      public  Long countBlog ()           return  blogRepository.count();     }     @Transactional      @Override      public  Blog saveBlog (Blog blog)           if  (blog.getId() == null ){             blog.setCreateTime(new  Date());             blog.setUpdateTime(new  Date());             blog.setViews(0 );         }else  {             blog.setUpdateTime(new  Date());         }         return  blogRepository.save(blog);     }     @Transactional      @Override      public  Blog updateBlog (Long id, Blog blog)           Blog b = blogRepository.findById(id).get();         if  (b == null ){             throw  new  NotFoundException("管理员大大,这个博客不存在哦!~( TロT)σ" );         }         BeanUtils.copyProperties(blog,b, MyBeanUtils.getNullPropertyNames(blog));         b.setUpdateTime(new  Date());         return  blogRepository.save(b);     }     @Transactional      @Override      public  void  deleteBlog (Long id)           blogRepository.deleteById(id);     } } 
BlogRepository.java
package  com.cxkj.blog.dao;import  com.cxkj.blog.pojo.Blog;import  org.springframework.data.domain.Page;import  org.springframework.data.domain.Pageable;import  org.springframework.data.jpa.repository.JpaRepository;import  org.springframework.data.jpa.repository.JpaSpecificationExecutor;import  org.springframework.data.jpa.repository.Modifying;import  org.springframework.data.jpa.repository.Query;import  org.springframework.transaction.annotation.Transactional;import  java.util.List;public  interface  BlogRepository  extends  JpaRepository <Blog ,Long >, JpaSpecificationExecutor <Blog >     @Query("select b from Blog b where b.recommend = true")      List<Blog> findTop (Pageable pageable)  ;          @Query("select b from Blog b where b.title like ?1 or b.content like ?1")      Page<Blog> findByQuery (String query,Pageable pageable)  ;     @Transactional      @Modifying      @Query("update Blog b set b.views = b.views+1 where b.id = ?1")      int  updateViews (Long id)           @Query("select function('date_format',b.updateTime,'%Y') as year from Blog b group by function('date_format',b.updateTime,'%Y') order by function('date_format',b.updateTime,'%Y') desc ")      List<String> findGroupYear ()  ;     @Query("select b from Blog b where function('date_format',b.updateTime,'%Y') = ?1")      List<Blog> findByYear (String year)  ; } 
个人模块处理 AboutShowController.java
package  com.cxkj.blog.web;import  org.springframework.stereotype.Controller;import  org.springframework.ui.Model;import  org.springframework.web.bind.annotation.GetMapping;@Controller public  class  AboutShowController      @GetMapping("/about")      public  String about ()          return  "about" ;     } } 
messages.properties
index.email =Email: 2644266656@qq.com index.qq =QQ: 2644266656 index.tagcontext =南有孤岛北有亡梦,南柯一梦终是虚无。 index.titlename =Guest Island index.kor =Copyright © 2020-2021 Guest Island Personal blog blog.serurl =127.0.0.1:8080