基于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优化 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) ; 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