首先,我们先看一下微信运动排行榜的页面以及大致的工作原理。
微信排行榜的每天定时刷新就是定时任务最常用的场景,像我们的微信运动每天晚上大约都是在10点多定时刷新数据。
下面,我将写一个模仿这样的定时任务的例子。
目录结构
在Config包下新建QuartzConfig,SporterJob,SportJobFactory类
- QuartzConfig类
public class QuartzConfig {
@Autowired
private SpringJobFactory springJobFactory;
@Bean
public SchedulerFactoryBean schedulerFactoryBean(){
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setJobFactory(springJobFactory);
return schedulerFactoryBean;
}
@Bean
public Scheduler scheduler() {
return schedulerFactoryBean().getScheduler();
}
}
- SporterJob类
@Component
public class SporterJob {
@Resource
private UpdateService updateService;
@Scheduled(cron = "0 26 22 * * ?")
public void updateTodayWalks() throws Exception {
updateService.updateWalks();
}
}
corn里设置刷新时间,corn的用法见我之前的文章。
- SporterJobFactory类
@Component
public class SpringJobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object jobInstance = super.createJobInstance(bundle);
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
实体类
- 运动者(Walker)
@Entity
@Data
public class Walker implements Serializable {
@Id
@GeneratedValue
private Integer id;
private String account;
private String password;
private String nickname;
private String avatar;
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
@JoinColumn(name = "account",referencedColumnName = "account")
private List<SportData> sportDataList;
public Walker(String account, String password, String nickname, String avatar, List<SportData> sportDataList) {
this.account = account;
this.password = password;
this.nickname = nickname;
this.avatar = avatar;
this.sportDataList = sportDataList;
}
}
- 运动数据(SportData)
@Entity
@Data
public class SportData implements Serializable {
@Id
@GeneratedValue
private Integer id;
private Integer steps;
private String evaluate;
private Date date;
public SportData(Integer steps, String evaluate, Date date) {
this.steps = steps;
this.evaluate = evaluate;
this.date = date;
}
}
- UpdateService类
public interface UpdateService {
void updateWalks();
}
- SportDataRepositry接口
public interface SportDataRepositry extends JpaRepository<SportData,Integer> {
}
- 实现类(UpdateServiceImpl)
@Service
public class UpdateServiceImpl implements UpdateService {
@Resource
private SportDataRepositry sportDataRepositry;
@Override
public void updateWalks() {
List<SportData> list = sportDataRepositry.findAll();
Random random = new Random();
for (int i=0;i <list.size();i++) {
SportData sportData = list.get(i);
sportData.setSteps(random.nextInt(2000)+2000);
sportData.setDate(new Date());
sportDataRepositry.saveAndFlush(sportData);
}
}
}
页面代码
- 登录界面
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<!--<link rel="stylesheet" href="/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css"/>-->
<!--<link type="text/css" rel="stylesheet" href="login.css"/>-->
<title>Title</title>
<style>
*{padding: 0;margin: 0;} /* 清除浮动 */
body {
font-family:"Microsoft YaHei";
background:#EBEBEB;
font-weight: 300;
font-size: 15px;
color: #333;
overflow: hidden;
}
a {text-decoration: none; color:#000;}
a:hover{color:#F87982;} /*home*/
#home { /*logint界面*/
padding-top:100px;
}
#login{
padding:20px 30px 30px;
width:300px;
background:#FFF;
margin:auto;
border-radius: 3px;
box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3);
}
#login h3{
font-size:18px;
line-height:25px;
font-weight:300;
letter-spacing:3px;
margin-bottom:20px;
color:#C8C8C8;
text-align:center;}
#login label{
color:#C8C8C8;
display:block;
height:35px;
padding:0 10px;
font-size:12px;
line-height:35px;
background:#EBEBEB;
margin-bottom:10px;
position:relative;}
#login label input{
font:13px/20px "Microsoft YaHei";
background:none; height:20px;
border:none; margin:7px 0 0 10px;
width:245px;outline:none ;
letter-spacing:normal;
z-index:1; position:relative;
}
#login label span{
display:block;
height:35px;
color:#F30;
width:100px;
position:absolute;
top:0;
left:190px;
text-align:right;
padding:0 10px 0 0;
z-index:0;
display:none;
}
#login #button{
font-family:"Microsoft YaHei";
cursor:pointer;
width:300px;
height:35px;
background:#FE4E5B;
border:none;
font-size:14px;
line-height:30px;
letter-spacing:3px;
color:#FFF;
position:relative;
margin-top:10px;
-moz-transition: all 0.2s ease-in;
-webkit-transition: all 0.2s ease-in;
-o-transition: all 0.2s ease-in;
transition: all 0.2s ease-in;}
#login #button:hover{ background:#F87982; color:#000;}
.avator{
display:block;
margin:0 auto 20px;
border-radius:50%;
}
</style>
</head>
<body>
<div id="home">
<form id="login" action="/sporter/list" method="get" class="current1">
<h3>用户登入</h3>
<img class="avator" src="img/avatar.jpg" width="96" height="96"/>
<label>账号<input type="text" name="account" style="width:215px;" />
<span>账号为空</span></label>
<label>密码<input type="password" name="password" />
<span>密码为空</span></label>
<input type="submit" id="button"></input>
</form>
</div>
</body>
</html>
- 运动数据界面
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css"/>
<title>SporterList</title>
<style>
.top-nav {
height: 60px;
}
.top-img {
height: 36px;
}
.top-title {
font-size: 20px;
color: black;
line-height: 60px;
}
p {
margin: 0;
padding: 0;
}
.icon1 {
margin-right: 20px;
line-height: 60px;
}
.icon2 {
margin-right: 20px;
line-height: 60px;
}
.center-nav {
width: 100%;
/*margin-top: 60px;*/
height: 40px;
border-bottom: solid #E0E0E0 2px;
margin-top: -20px;
}
.center-nav .col-md-2 {
border: solid #E0E0E0 1px;
}
.center-container{
margin: 0 180px;
height: 40px;
}
.center-list{
text-align: center;
line-height: 37px;
font-size: 16px;
font-weight: bold;
/*border: solid #E0E0E0 1px;*/
}
.main{
margin-top: 40px;
}
.main .center-img {
width: 200px;
height: 140px;
}
.article-div {
width: 100%;
height: 300px;
padding: 20px;
margin-bottom: 20px;
border: solid #E0E0E0 1px;
}
.article-div .bottom-info {
margin-top: 20px;
}
.article-div .avatar-img{
width: 40px;
height: 40px;
border-radius: 50%;
}
.bottom-info-right {
display: inline-block;
width: 40px;
height: 40px;
float: right;
padding-right: 30px;
}
#person_avatar {
border-radius: 50px;
width: 40px;
height: 40px;
}
</style>
</head>
<body>
<nav class="navbar navbar-default navbar-static-top">
<div class="container top-nav">
<div class="col-md-4">
</div>
<div class="col-md-4">
<p class="top-title text-center ">步数排行榜</p>
</div>
<div class="col-md-4 text-right">
<a><span class="glyphicon glyphicon-pencil icon1"></span></a>
<a><span class="glyphicon glyphicon-search icon2"></span></a>
<a class="navbar-brand navbar-right" href="#">
<img id="person_avatar" th:src="@{${person.avatar}}">
</a>
</div>
</div>
</nav>
<div class="container">
<div class="col-md-4">
</div>
<div class="col-md-4">
<div class="thumbnail" th:each="sport:${list}">
<img th:src="@{${sport.avatar}}">
<div class="caption">
<h3 th:text="${sport.nickname}"></h3>
<div th:each="walk:${sport.sportDataList}">
<h4 th:text="${walk.steps}"></h4>
</div>
</div>
</div>
</div>
<div class="col-md-4">
</div>
</div>
</body>
</html>