评论模块comment
实体类
- 记录评论的各类信息,如用户、用户邮箱、评论回复、评论时间等等,这些数据会放到数据库的comment表里
package com.zr.po;
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 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 +
'}';
}
}
界面(在new.html里)
<div id="comment-form" class="ui form">
<input type="hidden" name="news.id" th:value="${news.id}">
<input type="hidden" name="parentComment.id" value="-1">
<div class="field">
<textarea name="content" placeholder="请输入评论信息..."></textarea>
</div>
<div class="fields">
<div class="field m-mobile-wide m-margin-bottom-small">
<div class="ui left icon input">
<i class="user icon"></i>
<input type="text" name="nickname" placeholder="姓名" th:value="${session.user}!=null ? ${session.user.nickname}">
</div>
</div>
<div class="field m-mobile-wide m-margin-bottom-small">
<div class="ui left icon input">
<i class="mail icon"></i>
<input type="text" name="email" placeholder="邮箱" th:value="${session.user}!=null ? ${session.user.email}">
</div>
</div>
<div class="field m-margin-bottom-small m-mobile-wide">
<button id="commentpost-btn" type="button" class="ui teal button m-mobile-wide"><i class="edit icon"></i>发布</button>
</div>
</div>
</div>
control层CommentController
- save()方法中,AdminComment记录是否是管理员的评论,管理员登录后的评论中AdminComment会置1。然后调用service层的方法进行保存,保存之后根据新闻的评论,并重定向执行下面的查询方法
- 另一个方法就是根据新闻的id查找评论的方法
@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";
}
}
service层实现CommentServiceImpl
- 保存(界面的父评论会将ParentComment记录为-1,保存时会出错,需要将其置为空)
- 根据新闻id查找评论,并根据评论时间进行排序
@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;
}
}
dao层
package com.zr.dao;
import com.zr.po.Comment;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface CommentDao extends JpaRepository<Comment,Long> {
List<Comment> findByNewsIdAndParentCommentNull(Long newsId, Sort sort);
}
结果展示
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/fbf600cbbe50f21a4b6b79f3538ad893.png)
搜索search模块
control层
- 在indexController中添加search()方法,需要分页条件、排序,query用于取到页面的输入的搜索项,再用model展示到页面上。调用service层方法根据query和分页信息查询新闻。
@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";
}
service层
- 在newsService添加方法findNewsByQuery(),查询条件加个百分号用于模糊查询
@Override
public Page<News> findNewsByQuery(String query, Pageable pageable) {
return newsDao.findByquery("%"+query+"%",pageable);
}
dao层
- newsDao添加新方法,就能根据query和分页进行查找新闻了
@Query("select n from News n where n.title like ?1 or n.content like ?1")
Page<News> findByquery(String s, Pageable pageable);
搜索界面search.html
<div class="column">
<a href="#" th:href="@{/search/(page=${page.number}-1)}" th:unless="${page.first}" class="ui mini teal basic button">上一页</a>
</div>
<div class="right aligned column">
<a href="#" th:href="@{/search/(page=${page.number}+1,query=${query})}" th:unless="${page.last}" class="ui mini teal basic button">下一页</a>
</div>
结果展示
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/6b94490e0f63fae7614577ec1cde2dda.png)
主页最新新闻模块
界面模块(_fragments.html中)
<h4 class="ui inverted header m-text-thin m-text-spaced " >最新新闻</h4>
<div id="newnews-container">
<div class="ui inverted link list" th:fragment="lastestNewsList1">
<a href="#" th:href="@{/news/{id}(id=${news.id})}" target="_blank" class="item m-text-thin" th:each="news : ${newnewss}" th:text="${news.title}">用户故事(User Story)</a>
<!---->
</div>
</div>
control层
- 调用newsService内findTop()找到最新的三个新闻,遍历lastestNewsList并替换到lastestNewsList1里。
@RequestMapping("/footer/lastestNews")
public String lastestNews(Model model){
List<News> lastestNewsList=newsService.findTop(3);
model.addAttribute("lastestNewsList",lastestNewsList);
return "_fragments :: lastestNewsList1";
}
service层
- newsService中新建方法findTop(),根据分页排序进行查找
@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);
}
结果展示
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/171ab368c67c7b6033f9e5836aced3b8.png)
拦截器
- zr路径下新建包interceptor,包含以下两个类,用于拦截admin/之后的路径,不包括admin/和admin/login/,直接输入拦截的路径会直接跳转到admin/
LoginInterceptor.java
package com.zr.interceptor;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.java
package com.zr.interceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/admin/**")
.excludePathPatterns("/admin")
.excludePathPatterns("/admin/login");
}
}