从今天开始,通过开发一个“新闻”项目,来深入学习spring boot的相关内容。
文章目录
1.准备工作
(1)新建spring boot 项目
![](https://i-blog.csdnimg.cn/blog_migrate/702bea3155f315e63fa0f665386a6a95.png)
![](https://cdn.jsdelivr.net/gh/ataraxy-zhi/ImgHosting/images/QQ截图20200817104655.png)
(2)新建实体类
由于这里用spring data jpa,所以只要实现建立好数据库,然后相应的配置好实体类,就会自动建表。
主要用到的注解:
- @Entity:表明其是一个实体类
- @Table:指定其相应的表名
- @Id 、@GeneratedValue:指示该属性为相应表的Id值并且是自增的。
- @Temporal(TemporalType.TIMESTAMP);在建表时该字段的类型为数据库中的时间戳类型。
- @ManyToOne:表明各字段之间的关系,多对一。相应的还有一对多、多对多等等。
相应的实体类如下。
- 新闻类:News.java
package com.example.news.entity;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @className: News
* @description:
* @author:
* @date: 18/08/2020 09:48
*/
@Entity
@Table(name = "t_news")
public class News {
@Id
@GeneratedValue
private Long id;
/**
* 新闻标题
*/
private String title;
/**
* 新闻内容
*/
private String content;
/**
* 新闻头图
*/
private String firstPicture;
/**
* 新闻描述
*/
private String description;
/**
* 转载还是原创
*/
private String flag;
/**
* 访问量
*/
private Integer views;
/**
* 是否运行评论
*/
private boolean commentable;
/**
* 是否允许转载
*/
private boolean shareStatement;
/**
* 新闻状态:发布、草稿
*/
private boolean published;
/**
* 是否允许赞赏
*/
private boolean appreciation;
/**
* 是否推荐
*/
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 = "news")
private List<Comment> comments=new ArrayList<>();
public News() {
}
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 getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
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 isCommentable() {
return commentable;
}
public void setCommentable(boolean commentable) {
this.commentable = commentable;
}
public boolean isShareStatement() {
return shareStatement;
}
public void setShareStatement(boolean shareStatement) {
this.shareStatement = shareStatement;
}
public boolean isPublished() {
return published;
}
public void setPublished(boolean published) {
this.published = published;
}
public boolean isAppreciation() {
return appreciation;
}
public void setAppreciation(boolean appreciation) {
this.appreciation = appreciation;
}
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 "News{" +
"id=" + id +
", title='" + title + '\'' +
", content='" + content + '\'' +
", firstPicture='" + firstPicture + '\'' +
", description='" + description + '\'' +
", flag='" + flag + '\'' +
", views=" + views +
", commentable=" + commentable +
", shareStatement=" + shareStatement +
", published=" + published +
", appreciation=" + appreciation +
", recommend=" + recommend +
", createTime=" + createTime +
", updateTime=" + updateTime +
", type=" + type +
", tags=" + tags +
", user=" + user +
", comments=" + comments +
'}';
}
}
- 新闻标签类:Tag.java
package com.example.news.entity;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
/**
* @className: Tag
* @description:
* @author:
* @date: 18/08/2020 09:54
*/
@Entity
@Table(name = "t_tag")
public class Tag {
@Id
@GeneratedValue
private Long id;
/**
* 标签名字
*/
private String name;
/**
* 标签所对应的新闻
*/
@ManyToMany(mappedBy = "tags")
private List<News> newsList = 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<News> getNewsList() {
return newsList;
}
public void setNewsList(List<News> newsList) {
this.newsList = newsList;
}
@Override
public String toString() {
return "Tag{" +
"id=" + id +
", name='" + name + '\'' +
", newsList=" + newsList +
'}';
}
}
- 新闻类型类:Type.java
package com.example.news.entity;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
/**
* @className: Type
* @description:
* @author:
* @date: 18/08/2020 09:54
*/
@Entity
@Table(name = "t_type")
public class Type {
@Id
@GeneratedValue
private Long id;
/**
* 类型名字
*/
private String name;
/**
* 类型对应的新闻
*/
@OneToMany(mappedBy = "type")
private List<News> news = 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<News> getNews() {
return news;
}
public void setNews(List<News> news) {
this.news = news;
}
@Override
public String toString() {
return "Type{" +
"id=" + id +
", name='" + name + '\'' +
", news=" + news +
'}';
}
}
- 用户类:User.java
package com.example.news.entity;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @className: User
* @description:
* @author:
* @date: 18/08/2020 09:55
*/
@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<News> newsList = 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) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public List<News> getNewsList() {
return newsList;
}
public void setNewsList(List<News> newsList) {
this.newsList = newsList;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", nickname='" + nickname + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
", avatar='" + avatar + '\'' +
", type=" + type +
", createTime=" + createTime +
", updateTime=" + updateTime +
", newsList=" + newsList +
'}';
}
}
- 评论类:Comment.java
package com.example.news.entity;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @className: Comment
* @description:
* @author:
* @date: 18/08/2020 09:55
*/
@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 News news;
/**
* 回复的评论
*/
@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 News getNews() {
return news;
}
public void setNews(News news) {
this.news = news;
}
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 +
", news=" + news +
", replyComments=" + replyComments +
", parentComment=" + parentComment +
", adminComment=" + adminComment +
'}';
}
}
2.验证spring 中的AOP
AOP:aspect oriented programming,面向切面编程。
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。z
在这里我们借助AOP来研究前置通知和后置通知。
(1)新建切面类:LogAspect.java
package com.example.news.aspects;
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;
/**
* @className: LogAspect
* @description: 登录切面类
* @author:
* @date: 18/08/2020 08:50
*/
@Component
@Aspect
public class LogAspect {
/**
* 日志记录器
*/
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 定义切入点 在切入点中定义修饰符
*/
@Pointcut("execution(* com.example.news.controller.*.*(..))")
public void log() {
}
/**
* 前置增强方法
*
* @param joinPoint
*/
@Before("log()")
public void doBefore(JoinPoint joinPoint) {
logger.info("====doBefore===");
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() {
logger.info("====doAfter===");
}
/**
* 后置增强方法
*
* @param result
*/
@AfterReturning(returning = "result", pointcut = "log()")
public void doAfterReturning(Object result) {
logger.info("result:{}", result);
}
private static class RequestLog {
private String url;
private String ip;
private String classMethod;
private Object[] args;
public RequestLog() {
}
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 "RequestLog{" +
"url='" + url + '\'' +
", ip='" + ip + '\'' +
", classMethod='" + classMethod + '\'' +
", args=" + Arrays.toString(args) +
'}';
}
}
}
(2)新建控制器类:TestController.java来进行验证
package com.example.news.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @className: TestController
* @description:
* @author:
* @date: 17/08/2020 11:15
*/
@Controller
public class TestController {
@GetMapping("/test")
public String test(){
/*double a=1/0;
System.out.println(a);*/
System.out.println("执行test方法");
return "index";
}
}
(3)执行启动类
启动成功后,输入http://localhost:8090/test
之后,控制台便会有如下语句打印出。验证成功。
![](https://i-blog.csdnimg.cn/blog_migrate/cba4cf2207396747072b0bc578b8c0e5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/1d18b764d901a111d9463ab56892fbf1.jpeg)