评论
实体类Comment
一条新闻可有多条评论
可对评论进行评论,parentComment为某条评论的上一级评论
@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 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;
}
public News getNews() {
return news;
}
public void setNews(News news) {
this.news = news;
}
@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 +
'}';
}
}
dao层
在dao中,创建继承JpaRepository类的CommentDao接口
在CommentDao接口中,声明findByNewsIdAndParentCommentNull方法
public interface CommentDao extends JpaRepository<Comment,Long> {
List<Comment> findByNewsIdAndParentCommentNull(Long newsId, Sort sort);
}
service层
(1)在service下,创建CommentService接口,声明save方法、findCommentByNewsId方法
public interface CommentService {
void save(Comment comment);
List<Comment> findCommentByNewsId(Long newsId);
}
(2)在service下的impl中,创建CommentServiceImpl类实现CommentService接口中声明的方法
save方法:判断评论有无上一级评论,若无,将comment的parentComment属性置为空;
调用commentDao的save方法,保存评论
findCommentByNewsId方法:根据创建时间排序,根据传入的newsId查找对应的comment,得到评论列表
@Service
public class CommentServiceImpl implements CommentService {
@Autowired
private CommentDao commentDao;
@Override
public void save(Comment comment) {
if(comment.getParentComment().getId()==-1){
comment.setParentComment(null);
}
commentDao.save(comment);
}
@Override
public List<Comment> findCommentByNewsId(Long newsId) {
Sort sort = Sort.by("createTime");
List<Comment> comments=commentDao.findByNewsIdAndParentCommentNull(newsId,sort);
return comments;
}
}
controller层
(1)在controller下的IndexController类中,创建news方法,实现到详情页面的跳转
@RequestMapping("/news/{id}")
public String news(@PathVariable Long id,Model model){
News news = newsServcie.findNewsById(id);
model.addAttribute("news",news);
return "news";
}
(2)在controller下,创建CommentController类,在CommentController类中
创建save方法:
1.从session中取user:若user为空,则为普通用户登录后评论;否则为管理员登录后评论
2.调用 commentService的save方法,保存评论
3.先调用comment的getNews()方法,得到当前评论对应的news
再调用news的getId方法,得到对应news的id
4.重定向,执行comment查询,刷新界面
创建comment方法:
1.根据传入的newsId,调用commentService的findCommentByNewsId方法,得到newsId对应的评论列表
2.将相关信息通过model传到前台
@Controller
public class CommentController {
@Autowired
private CommentService commentService;
@PostMapping("/comments")
public String save(Comment comment, HttpSession session){
User user = (User) session.getAttribute("user");
if(user==null){
comment.setAdminComment(false);
}else {
comment.setAdminComment(true);
}
commentService.save(comment);
Long newsId=comment.getNews().getId();
return "redirect:/comments/"+newsId;
}
@RequestMapping("/comments/{newsId}")
public String comments(@PathVariable Long newsId, Model model){
List<Comment> comments=commentService.findCommentByNewsId(newsId);
model.addAttribute("comments",comments);
return "news :: commentList";
}
}
运行结果
管理员登录后评论
评论成功
关于我
在controller下的IndexController类中,创建about方法,实现到about页面的跳转
@RequestMapping("/about")
public String about(){
return "about";
}
搜索
dao层
(1)在dao下的NewsDao接口中,创建findByquery方法,根据传入的参数,对标题、内容字段进行模糊查询
@Query("select n from News n where n.title like ?1 or n.content like ?1")
Page<News> findByquery(String s, Pageable pageable);
service层
(1)在service下的NewsService接口,声明findNewsByQuery方法
Page<News> findNewsByQuery(String query, Pageable pageable);
(2)在service下的impl中,实现NewsService接口中声明的findNewsByQuery方法:
根据传入的query字符串、pageable参数,调用newsDao的findByquery方法,进行模糊查询
@Override
public Page<News> findNewsByQuery(String query, Pageable pageable) {
return newsDao.findByquery("%"+query+"%",pageable);
}
controller层
在controller下的IndexController类中,创建search方法,实现到搜索页面的跳转:
使用内置的Pageable来实现分页,将news,按news的更新时间进行降序排列,再取前3条news;
调用newsServcie的findNewsByQuery方法,进行模糊查询,得到对应新闻页面
将相关信息通过model传到前台
@RequestMapping("/search")
public String search(@PageableDefault(size = 3,sort = {"updateTime"},direction = Sort.Direction.DESC)Pageable pageable,String query,Model model){
Page<News> page=newsServcie.findNewsByQuery(query,pageable);
model.addAttribute("page",page);
model.addAttribute("query",query);
return "search";
}
运行结果
搜索标题或内容含有2的新闻
下一页
推荐新闻
dao层
(1)在dao下的NewsDao接口中,创建findTop方法,查找前n条推荐新闻
@Query("select n from News n where n.recommend=true")
List<News> findTop(Pageable pageable);
service层
(1)在service下的NewsService接口,声明findTop方法
List<News> findTop(int i);
(2)在service下的impl中,实现NewsService接口中声明的findTop方法:
将新闻按更新时间进行降序排列,再调用newsDao的findTop方法取前n条推荐新闻
@Override
public List<News> findTop(int i) {
Sort sort= Sort.by(Sort.Direction.DESC,"updateTime");
Pageable pageable = PageRequest.of(0, i, sort);
return newsDao.findTop(pageable);
}
controller层
在controller下的IndexController类中,创建lastestNews方法,得到最新推荐新闻,实现界面跳转:
调用newsServcie的findTop方法,显示推荐新闻前三条
将相关信息通过model传到前台
@RequestMapping("/footer/lastestNews")
public String lastestNews(Model model){
List<News> lastestNewsList=newsServcie.findTop(3);
model.addAttribute("lastestNewsList",lastestNewsList);
return "_fragments :: lastestNewsList1";
}
运行结果
拦截器
创建interceptor包,然后在其中创建LoginInterceptor类、WebConfig类
LoginInterceptor
从session中取user:若user为空,则说明没有登录,跳转到登录界面
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(request.getSession().getAttribute("user") == null){
response.sendRedirect("/admin");
return false;
}
return true;
}
}
WebConfig
配置文件:配置拦截器
拦截admin下所有请求
除了用于登录的/admin与/admin/login请求
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/admin/**")
.excludePathPatterns("/admin")
.excludePathPatterns("/admin/login");
}
}
权限管理
实体类Role
@Entity
@Table(name = "t_role")
public class Role implements Serializable {
private static final long serialVersionUID = 594829320797158219L;
@Id
private String id;
private String name;
private String description;
//角色与用户 多对多
@ManyToMany(mappedBy="roles")
private Set<User> users = new HashSet<User>(0);
//角色与权限 多对多
@ManyToMany(fetch = FetchType.EAGER)
private Set<Permission> permissions = new HashSet<Permission>(0);
public static long getSerialVersionUID() {
return serialVersionUID;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
public Set<Permission> getPermissions() {
return permissions;
}
public void setPermissions(Set<Permission> permissions) {
this.permissions = permissions;
}
}
实体类Permission
@Entity
@Table(name = "t_permission")
public class Permission implements Serializable {
private static final long serialVersionUID = -4990810027542971546L;
/**
* 主键
*/
@Id
private String id;
private String name;
private String code;
private String description;
public static long getSerialVersionUID() {
return serialVersionUID;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
数据库设计
t_permission
t_role
t_role_permissions
t_user_roles