回顾
上一篇我们实现了文章发布页面布局及发布功能,其中存在一些问题,这一篇我们解决问题并开始着手文章列表展示。
1 效果预览
1.1 编写文章
登录成功后我们点击写文章,进入编写页面
1.2 发布文章
编写完成后点击发布。
1.3 文章列表浏览页面
发布成功后会跳转到首页展示文章列表信息,如下:
2.具体实现过程
2.1 文章列表图片
之前我们忽略了发布者头像显示及其他属性,这次分别在GitHubUser.java和User.java中增加头像字段avatarUrl,同时在数据库中user 表添加avatar_url列,当我们首次登陆时,就会将github中头像路径保存至数据库中,当我们发布文章后,就可以通过当前用户信息获取到头像。
为了方便我们后续开发,并且可以快捷增加字段删除字段,我们引入lombok插件,如下:
2.1.1 IDEA安装lombok插件
我们在IDEA中按住Ctrl+alt+s,可以快速打开设置面板,在里面找到plugins,在搜索框输入lombok,找到后点击Install,安装成功后需要重启IDEA后生效
插件安装成功后,我们需要添加lombok的依赖,如下:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
依赖添加成功后我们将之前所有的实体类进行修改如下:
@Data
public class Article {
private int id;
private String title;
private String description;
private String tag;
private Long authorId;
private int readCount; //阅读数
private int answerCount; //回复数
private int likeCount; //点赞数
private Long createTime;
private Long modifiedTime;
private User user;
}
将getter和setter方法去掉,可以在类上面添加一个@data注解,该注解会在编译的时候,自动将getter、setter方法,toString方法加上,这样会省去大量工作,同时便于我们对实体类进行修改。
2.1.2 在登录时获取用户头像并保存在数据库
AuthorizationController.java
@Controller
public class AuthorizationController {
@Autowired
GitHubProvider gitHubProvider;
@Autowired
UserMapper userMapper;
@Value("${github.client.id}")
private String client_id;
@Value("${github.client.secret}")
private String client_secret;
@Value("${github.redirect.url}")
private String redirect_url;
@GetMapping("/callback")
public String callback(@RequestParam(name = "code") String code,
@RequestParam(name = "state") String state,
HttpServletResponse response){
AccessTokenParam accessTokenParam = new AccessTokenParam();
accessTokenParam.setCode(code);
accessTokenParam.setState(state);
accessTokenParam.setClient_id(client_id);
accessTokenParam.setClient_secret(client_secret);
accessTokenParam.setRedirect_uri(redirect_url);
String Token = gitHubProvider.getAccessToken(accessTokenParam); //获取到access_token
String accessToken = Token.split("&")[0].split("=")[1];
//使用access_token获取用户信息
GitHubUser gitHubUser = gitHubProvider.getGitHubUser(accessToken);
if(gitHubUser!=null){
String token = UUID.randomUUID().toString();
//根据accountid查询是否存在该用户
User selectUser = userMapper.selectUserByAccountId(gitHubUser.getId());
//如果存在更新token,用户名及修改时间
if(selectUser!=null){
if(gitHubUser.getName()==null||gitHubUser.getName()==""){
selectUser.setName("gid_"+gitHubUser.getId());
}else if(gitHubUser.getName()!=null&&selectUser.getName()!=null&&!gitHubUser.getName().equals(selectUser.getName())){
selectUser.setName(gitHubUser.getName());
}
if(!gitHubUser.getAvatarUrl().equals(selectUser.getAvatarUrl())){
selectUser.setAvatarUrl(gitHubUser.getAvatarUrl());
}
selectUser.setToken(token);
selectUser.setModifiedTime(System.currentTimeMillis());
userMapper.updateUser(selectUser);
}else{
//如果不存在添加新的用户信息
User user = new User();
user.setName(gitHubUser.getName());
user.setAccountId(gitHubUser.getId());
user.setToken(token);
//设置用户头像
user.setAvatarUrl(gitHubUser.getAvatarUrl());
user.setCreateTime(System.currentTimeMillis());
user.setModifiedTime(user.getCreateTime());
userMapper.addUser(user);
}
response.addCookie(new Cookie("token",token));
}
return "redirect:/";
}
}
2.2获取所有文章列表信息
持久层获取文章及头像信息操作语句
ArticleMapper.java
@Select("select u.*,a.id as aid,a.title,a.description,a.read_count,a.answer_count,a.like_count,a.create_time from article a,user u where a.author_id = u.id")
@Results(id="ArticleUser",value = {
@Result(id=true,property = "id",column = "id"),
@Result(property = "id",column = "aid"),
@Result(property = "title",column = "title"),
@Result(property = "description",column = "description"),
@Result(property = "authorId",column = "author_id"),
@Result(property = "readCount",column = "read_count"),
@Result(property = "answerCount",column = "answer_count"),
@Result(property = "likeCount",column = "like_count"),
@Result(property = "user.name",column = "name"),
@Result(property = "user.avatarUrl",column = "avatar_url")
})
List<Article> list();
当用户进入到首页是,就会将获取到的信息传递到前台页面用于展示。
IndexController.java
@GetMapping("/")
public String index(HttpServletRequest request, Model model){
Cookie[] cookies = request.getCookies();
if(cookies!=null && cookies.length>0){
for (Cookie cookie:cookies){
if("token".equals(cookie.getName())){
String token = cookie.getValue();
User user = userMapper.selectUserByToken(token);
if(user!=null){
request.getSession().setAttribute("user",user);
}
}
}
}
//文章列表展示
List<Article> articleList = articleMapper.list();
model.addAttribute("articleList",articleList);
return "index";
}
主页index.html页面布局及thymeleaf模板语句使用
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<!-- 踩过的坑,springboot引入静态资源路径不要加/static/,否则会报404-->
<title>个人博客</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="/bootstrap-3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/community.css">
<link rel="stylesheet" href="//at.alicdn.com/t/font_1643567_rm1fqucxtan.css">
<link rel="stylesheet" href="/bootstrap-3.3.7/css/bootstrap-theme.min.css">
<script src="/jquery-1.12.4/jquery-1.12.4.min.js"></script>
<script src="/bootstrap-3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<!--顶部导航栏-->
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">个人博客</span>
</button>
<a class="navbar-brand" href="/">个人博客</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="请搜索问题">
</div>
<button type="submit" class="btn btn-default">搜索</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li th:if="${session.user!=null}">
<a href="/publish"><i class="iconfont icon-fabu2"></i> 写文章</a>
</li>
<li th:if="${session.user==null}">
<a href="/login">登录</a>
</li>
<li class="dropdown" th:if="${session.user!=null}">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" th:text="${session.user.name}"><span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">消息中心</a></li>
<li><a href="#">基础设置</a></li>
<li role="separator" class="divider"></li>
<li><a href="/logout">退出登录</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<div class="row main">
<div class="col-lg-9 col-md-12 col-sm-12 col-xs-12 col-left">
<div class="row">
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3"><h4><i class="iconfont icon-liebiao"></i> 列表</h4></div>
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-9 alertMsg">
<div class="alert alert-danger alert-dismissible alert-error" role="alert" th:if="${error != null}">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<span th:text="${error}"></span>
</div>
</div>
<div class="col-lg-3 col-md-3 col-sm-3"></div>
</div>
<div class="media media_list" th:each="article : ${articleList}">
<div class="media-left">
<a href="#">
<img class="media-object img-rounded" th:src="${article.user.getAvatarUrl()}" >
</a>
</div>
<div class="media-body">
<h4 class="media-heading" th:text="${article.title}">标题标题</h4>
<span th:text="${article.answerCount}"></span> 个回复 • <span th:text="${article.readCount}"></span> 次浏览 • 发布时间<span th:text="${#dates.format(article.createTime,'yyyy-MM-dd HH:mm:ss')}"></span>
</div>
</div>
</div>
<div class="col-lg-3 col-md-12 col-sm-12 col-xs-12">
<h4>热门话题、广告栏、热门标签栏等</h4>
</div>
</div>
</body>
</html>
以上就是文章列表展示操作,更多源码信息可以访问我的github下载,下一篇将带大家手把手写数据分页功能。