public interface DataService {
List list();
}
@Service
public class DataServiceImpl implements DataService {
@Override
public List list() {
return MyDataHandler.getData();
}
}
国内疫情情况如下
=====================================================================
HTTP
-
“应用层协议”
-
了解HTTP不同版本的演进
-
了解GET和POST请求的区别
// 需要的参数url
// 创建一个远程的连接对象 设置方法类型 GET
// 设置相关参数 发送请求
// 通过io接收数据后返回
public static String doGet(String urlStr) {
HttpURLConnection conn = null;
InputStream is = null;
BufferedReader br = null;
StringBuilder result = new StringBuilder();
try {
// 创建远程url连接对象
URL url = new URL(urlStr);
// 打开一个连接
conn = (HttpURLConnection) url.openConnection();
// 设置为GET请求
conn.setRequestMethod(“GET”);
// 设置重要的参数 连接超时时间 和 读取超时时间
// 超时时间 更多被距离影响 读取时间 更多被数据量影响
conn.setConnectTimeout(15000);
conn.setReadTimeout(60000);
// header参数设置 可以不设置
conn.setRequestProperty(“Accept”, “application/json”);
// 发送请求
conn.connect();
// 状态码 200 302 404 500 ?
// 如果比较时 可能出现空指针 把确定的值放在前面 可以避免
if (200 == conn.getResponseCode()) {
is = conn.getInputStream();
br = new BufferedReader(new InputStreamReader(is, “UTF-8”));
String line;
while ((line = br.readLine()) != null) {
result.append(line);
}
} else {
System.out.println(“error responseCode :”
- conn.getResponseCode());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
if (is != null) {
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
conn.disconnect();
}
return result.toString();
}
=====================================================================
SSM的整合 -> 入门课的整合 -> mybatis-plus的整合
明确数据结构 -> 创建mapper文件夹 -> 调用getData方法 将数据据存储到数据库中 -> 查询时从数据库中读取
a) 引入依赖
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.1
com.baomidou
mybatis-plus-boot-starter
3.2.0
mysql
mysql-connector-java
runtime
b) 配置数据库连接参数
spring.datasource.url=jdbc:mysql://localhost:3306/illness?characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456
c) 创建数据库
CREATE DATABASE /!32312 IF NOT EXISTS/illness
/*!40100 DEFAULT CHARACTER SET utf8 */;
USE illness
;
/*Table structure for table epidemic
*/
DROP TABLE IF EXISTS epidemic
;
CREATE TABLE epidemic
(
id
bigint(20) NOT NULL AUTO_INCREMENT,
area
varchar(100) DEFAULT NULL,
confirm
int(11) DEFAULT NULL,
now_confirm
int(11) DEFAULT NULL,
dead
int(11) DEFAULT NULL,
heal
int(11) DEFAULT NULL,
PRIMARY KEY (id
)
) ENGINE=InnoDB AUTO_INCREMENT=308 DEFAULT CHARSET=utf8;
d) 编写类及文件夹
将实体类对应到数据库的表中 属性和字段也需对应
需注意 属性的命名为驼峰命名法
如 nowConfirm 字段的命名是下划线分隔 如 now_confirm
可以使用@TableName和@TableField等注解指定对应关系
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(“epidemic”)
public class DataBean implements Serializable {
// Alt + Insert 调用 安装插件
private static final long serialVersionUID
= 4938260405189292371L;
// Alt + 7 查看类的方法
// 地区 累计确诊人数 现有确诊人数 死亡人数 治愈人数
private long id;
private String area;
// @TableField(“all_confirm”)
// 如果属性名和表中字段名 不一致 可以通过 TableField注解指定
private int confirm;
private int nowConfirm;
private int dead;
private int heal;
}
在主程序类上 增加@MapperScan注解 指定mapper类所在文件夹
在此文件夹下 创建mapper类 实战中 如表名叫user mapper会命名为UserMapper
@SpringBootApplication
@MapperScan(“com.duing.mapper”)
public class DataHandlerApplication {
public static void main(String[] args) {
SpringApplication.run(DataHandlerApplication.class, args);
}
}
public interface DataMapper extends BaseMapper {
}
创建service接口及其实现类
整合mybatis-plus,用其提供的IService父接口 和 ServiceImpl实现父类
public interface DataService extends IService {
}
@Service
public class DataServiceImpl
extends ServiceImpl<DataMapper,DataBean>
implements DataService {
}
在controller中调用mybatis-plus实现的CRUD方法
@Controller
public class DataController {
@Autowired
private DataService dataService;
@GetMapping(“/”)
public String list(Model model) {
List beanList = dataService.list();
model.addAttribute(“beanList”, beanList);
return “list”;
}
}
在数据查询前,先将数据存储到数据库中,我们称之为数据初始化
可以在项目启动时,先采集一次数据存储到数据库中,然后再进行定期更新
而项目启动时执行且只执行一次的逻辑,可以使用注解 @PostConstruct
// 先将DataHandler托管到spring容器中 使用@Component
// 以便于获取到 dataService对象
@Component
public class DataHandler {
@Autowired
private DataService dataService;
// 数据初始化
// 在服务器加载Servlet时运行 且 只运行一次
@PostConstruct
public void saveData() {
List dataBeans = getData();
// mybatis-plus提供了可用的方法
// 删除全部数据 批量新增数据
dataService.remove(null);
dataService.saveBatch(dataBeans);
}
…
}
定时更新其实也是定时任务
可以通过注解@Scheduled + cron表达式来实现
Scheduled 英文原意是调度的意思 意思是我们将某段逻辑 按照指定的时间间隔 进行调度 即为定时处理
使用方式如下:
首先在入口类上 打开定时任务开关 使用注解 @EnableScheduling
@SpringBootApplication
@MapperScan(“com.duing.mapper”)
@EnableScheduling
public class DataHandlerApplication {
public static void main(String[] args) {
SpringApplication.run(DataHandlerApplication.class, args);
}
}
然后在方法上 使用 @Scheduled 搭配cron表达式 决定方法多久执行一次
// 定时更新
@Scheduled(cron = "0 0 0/1 * * ? ")
public void updateData(){
System.out.println(“要更新数据啦”);
System.out.println(“当前时间:” + dateFormat.format(new Date()));
List dataBeans = getData();
dataService.remove(null);
dataService.saveBatch(dataBeans);
}
其中cron表达式,是由6个表达不同时间单位的字段拼接而成
可以通过在线cron表达式生成器来生成
cron表达式几乎可以满足所有定时执行的需求
可以生成各类需求对应的表达式熟悉一下
除此之外,@Scheduled还支持固定时间间隔的参数设置
分别为 fixedRate 和 fixedDelay
// 固定频率任务 以ms为单位 10000代表每10s执行一次
// 使用时要注意间隔时间 和 任务消耗时间的 大小关系
// 如设置间隔10s 而方法需执行20s 那么方法会等待上一次执行完成才会执行
// 唤起方法真正的时间间隔为20s
@Scheduled(fixedRate = 10000)
public void updateData1(){}
// 固定间隔任务 上一次执行结束后 再隔10s进行下一次执行
// 如设置间隔10s 而方法需执行20s 那么会从上一次执行完成后开始计算 10s后开始下一次执行
// 唤起方法真正的时间间隔为30s
@Scheduled(fixedDelay = 10000)
public void updateData2(){}
========================================================================
我们可以根据国内表格数据的处理方式、以及图形化数据的处理方式,举一反三的去处理海外数据,只要掌握了处理流程,其实是可以模拟腾讯新闻,将全部数据展示出来的,要注意的是,我们的项目是为了练习springboot+mybatis+thymeleaf+echarts的使用,了解http请求+json数据处理+定时任务等等功能是如何实现的,那么对数据采集方面要慎重,尽量只采集需要的少部分数据,并且控制请求次数和请求频率,一定要做到“友好访问”。
=======================================================================
Jsoup(Ji soup 鸡汤)----页面解析器
解析一个HTML文档的方式如下:
String html = “
- “
Parsed HTML into a doc.
”;
Document doc = Jsoup.parse(html);
解析器能够尽最大可能从你提供的HTML文档中创建出一个干净的解析结果,无论HTML的格式是否完整。
比如它可以处理:
1)没有关闭的标签
Lorem
Ipsum
可以解析成
Lorem
Ipsum
2)隐式标签 (补充没有显示的标签)
它可以自动将 Table data 包装成
… |
3)创建可靠的文档结构
html标签包含head 和 body,且在head只出现恰当的元素
文档的对象模型
1)文档由多个Elements和TextNodes组成
2)继承结构如下:Document继承Element继承Node. TextNode继承 Node.
3)一个Element包含一系列的子节点,并拥有一个父Element。他们还唯一提供了一个子元素过滤列表。