基于springboot及爬虫数据实现的疫情统计项目

基于springboot及爬虫数据实现的疫情统计项目 1,项目简介 1,1 项目技术要求 spring boot的常见应用 业务功能的开发思路 爬虫的底层原理 对技术的应用有一定思考 1

本文包含相关资料包-----> 点击直达获取<-------

基于springboot及爬虫数据实现的疫情统计项目

1.项目简介

1.1 项目技术要求

  • spring boot的常见应用

  • 业务功能的开发思路

  • 爬虫的底层原理

  • 对技术的应用有一定思考

1.2 爬虫的基础知识

1.2.1 搜索引擎

“搜索引擎”是一种帮助用户搜索他们需要内容的计算机程序,本质是连接人与内容。

存储数据的处理方式

如:一篇文章 -> 语义分析 -> 关键字提取 -> 根据关键字及出现次数等 -> 倒排存储

关键字搜索

关键字相关的近义词、反义词、关联信息(ip、地址、用户信息)

1.2.2 爬虫分类

通用型爬虫(搜索引擎使用)

采集的数据是整个网站的数据,不论数据是何种形态、格式,使用通用的方法来存储和处理。

垂直型爬虫(对特定内容的采集)

采集的数据是指定的,格式是指定的,使用个性化的方法来处理。

网站的首页作为种子, 爬虫去采集能够分解出多少不重复的子链接,及其数据。

采集/下载页面 -> 分解为数据本身(存储) 、新的链接(依次向下爬取,类似树的深度遍历)-> 直到没有新链接代表采集完成 (链接使用队列来存储)。

1.2.3 爬虫数据的分析

浏览器开发者工具

分析数据源

腾讯新闻出品:https://news.qq.com/zt2020/page/feiyan.htm#/?nojump=1

工具的打开方式:F12 / Ctrl+Shift+I / 更多工具 -> 开发者工具 / 右键 -> 检查 -> 选中Network -> Preserve log(保存持续的日志), 重新刷新页面,可以看到网页所有的请求连接和返回数据。

想拿到表格中国内疫情的数据情况:

分析的方式

通过搜索框,搜索想要获得数据的具体数值,如:944/758等等。

分析后的请求地址

https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5

返回数据的格式是json

丁香医生出品

https://ncov.dxy.cn/ncovh5/view/pneumonia?scene=2&clicktime=1579579384&enterid=1579579384&from=singlemessage&isappinstalled=0

分析的方式同上。

分析后的请求地址

https://ncov.dxy.cn/ncovh5/view/pneumonia?scene=2&from=singlemessage&isappinstalled=0

返回数据的格式是html。

postman(模拟http请求的工具)

验证分析出来的请求地址,在排除上下文环境后,是否依然能够拿到数据。比如有的请求,依赖cookie、依赖动态的参数等等。

爬虫破解问题

拿到数据是核心的一步

  • 公开数据只要是非恶意就允许采集的,非恶意是指模仿人的行为采集的行为,不会高并发或者恶意攻击

  • 隐私数据都是有强大的加密处理的,防爬虫的手段是安全领域内的一大问题

2.解析数据

2.1 认识JSON

JSON = JavaScript Object Notation(JavaScript对象表示法)

本质上,是存储和交换文本信息的语法。是一种轻量级的文本数据格式。

java领域内解析json的工具:gson、fastjson、jackson

JSON 和 Java实体类

JSON JAVA实体类
string java.lang.String
number java.lang.Number (Double)
true\false java.lang.Boolean
null null
array java.util.List (ArrayList)
object java.util.Map (LinkedTreeMap)

2.2 Gson

是google推出的,用来在json数据和java对象之间进行转换的类库。

```java Gson gson = new Gson(); Gson gson1 = new GsonBuilder().create();

// 将对象obj转化为json字符串 String jsonStr = gson.toJson(Obj); // 将json字符串转化为java对象 T obj = gson.fromJson(jsonStr,class) ```

2.2.1 引入gson依赖

```xml

    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.6</version>
    </dependency>

```

2.2.2 确认要转化的数据格式

java import lombok.AllArgsConstructor; import lombok.Data; @Data @AllArgsConstructor public class DataBean { private String area; private int nowConfirm; private int confirm; private int heal; private int dead; }

2.2.3 解析文本数据

java public class DataHandler { public static void main(String[] args) throws Exception{ getData(); } public static List<DataBean> getData() throws Exception { // Gson gson = new Gson(); // Gson gson1 = new GsonBuilder().create(); // Map map = gson.fromJson(testStr,Map.class); // System.out.println(map); // 读取文件中的文本内容 然后再转化为java对象 // File file = new File("tmp.txt"); FileReader fr = new FileReader("tmp.txt"); char[] cBuf = new char[1024]; int cRead = 0; StringBuilder builder = new StringBuilder(); while ((cRead = fr.read(cBuf)) > 0) { builder.append(new String(cBuf, 0, cRead)); } fr.close(); // System.out.println(builder.toString()); Gson gson = new Gson(); Map map = gson.fromJson(builder.toString(), Map.class); System.out.println(map); ArrayList areaList = (ArrayList) map.get("areaTree"); Map dataMap = (Map) areaList.get(0); ArrayList childrenList = (ArrayList) dataMap.get("children"); // 遍历然后转化 List<DataBean> result = new ArrayList<>(); for (int i = 0; i < childrenList.size(); i++) { Map tmp = (Map) childrenList.get(i); String name = (String)tmp.get("name"); Map totalMap = (Map) tmp.get("total"); double nowConfirm = (Double)totalMap.get("nowConfirm"); double confirm = (Double)totalMap.get("confirm"); double heal = (Double)totalMap.get("heal"); double dead = (Double)totalMap.get("dead"); DataBean dataBean = new DataBean(name,(int)nowConfirm,(int)confirm, (int)heal,(int)dead); result.add(dataBean); } System.out.println(result); return result; } }

2.3 将数据展示在页面中

2.3.1 编写service和controller

java import com.duing.bean.DataBean; import java.util.List; public interface DataService { List<DataBean> list(); }

java import com.duing.bean.DataBean; import com.duing.handler.DataHandler; import org.springframework.stereotype.Service; import java.util.List; @Service public class DataServiceImpl implements DataService { @Override public List<DataBean> list() { List<DataBean> result = null; try { result = DataHandler.getData(); } catch (Exception e) { e.printStackTrace(); } return result; } }

java import com.duing.bean.DataBean; import com.duing.service.DataService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import java.util.List; @Controller public class DataController { @Autowired private DataService dataService; @GetMapping("/") public String list(Model model){ List<DataBean> list = dataService.list(); model.addAttribute("dataList",list); return "list"; } }

2.3.2 编写页面(注意已引入thymeleaf的maven依赖)

```html

Title

国内疫情情况如下


地区 现有确诊 累计确诊 治愈 死亡
name nowConfirm confirm heal dead

```

2.4 转为实时数据

复习get和post请求,分别在使用场景、参数传递方式、数据大小限制、安全性等方面的异同。

连接时间和读取时间

  • 连接时间 : 发送请求端连接到url目标地址端的时间,受到距离长短和网络速度的影响

  • 读取时间 : 指连接成功后获取数据的时间,受到数据量和服务器处理速度的影响

用java代码模拟http请求

  • 通过创建url打开远程链接 (HttpURLConnection)

  • 设置相关参数(超时时间和请求头等等)

  • 发送请求

  • 接收结果(使用InputStream和BufferedReader)

```java public static String doGet(String urlStr) { HttpURLConnection conn = null; InputStream is = null; BufferedReader br = null; StringBuilder result = new StringBuilder(); try { URL url = new URL(urlStr); // 通过url打开一个远程连接 强转类型 conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); // 连接时间和读取时间 conn.setConnectTimeout(15000); conn.setReadTimeout(60000); // 设定请求头参数的方式:如指定接收json数据 服务端的key值为content-type // conn.setRequestProperty("Accept", "application/json"); // 发送请求 conn.connect(); if (conn.getResponseCode() != 200) { // TODO 此处应该增加异常处理 return "error code"; } is = conn.getInputStream(); br = new BufferedReader(new InputStreamReader(is, "UTF-8")); String line; // 逐行读取 不为空就继续 while ((line = br.readLine()) != null) { result.append(line); System.out.print(line); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (br != null) br.close(); if (is != null) is.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return result.toString();
}

```

2.5 使用Jsoup解析html格式数据

Jsoup是html的解析器,可以解析html文本和直接解析URL地址。本质上是通过DOM、CSS以及类似jQuery的方法来取出和操作数据。

java Document document = Jsoup.parse(htmlStr); System.out.println(document); //通过标签名找到元素 Elements elements = document.getElementsByTag("p"); System.out.println(elements); document.getElementsById //通过id找到元素 Element element = document.select("a[href]");//还支持使用正则表达式查找元素

2.5.1 增加了controller方法

java @GetMapping("/list/{id}") public String listById(Model model, @PathVariable String id) { List<DataBean> list = dataService.listById(Integer.parseInt(id)); model.addAttribute("dataList", list); return "list"; }

@PathVariavle 将接收到的地址数据,映射到方法的参数中

2.5.2 完善service

java @Override public List<DataBean> listById(int id) { if (id == 2) { return JsoupHandler.getData(); } return list(); }

2.5.3 处理数据的方法

java public static String urlStr = "https://ncov.dxy.cn/ncovh5/view/pneumonia?" + "scene=2&from=singlemessage&isappinstalled=0"; public static ArrayList<DataBean> getData() { ArrayList<DataBean> result = new ArrayList<>(); try { Document doc = Jsoup.connect(urlStr).get(); // Elements scripts = doc.select("script"); // 找到指定的标签数据 Element oneScript = doc.getElementById("getAreaStat"); String data = oneScript.data(); // 字符串截取出json格式的数据 String subData = data.substring(data.indexOf("["), data.lastIndexOf("]") + 1); // System.out.println(subData); Gson gson = new Gson(); ArrayList list = gson.fromJson(subData, ArrayList.class); for (int i = 0; i < list.size(); i++) { Map map = (Map) list.get(i); String name = (String) map.get("provinceName"); double nowConfirm = (Double) map.get("currentConfirmedCount"); double confirm = (Double) map.get("confirmedCount"); double heal = (Double) map.get("curedCount"); double dead = (Double) map.get("deadCount"); DataBean dataBean = new DataBean(name, (int) nowConfirm, (int) confirm, (int) heal, (int) dead); result.add(dataBean); } } catch (Exception e) { e.printStackTrace(); } return result; }

2.5.4 验证

分别访问 http://localhost:8080/list/1 和 http://localhost:8080/list/2 ,通过省份的名称来区分不同渠道的数据结果。

2.6 增加数据存储逻辑

2.6.1 引入相关的依赖

```xml org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.0

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.2.0</version>
    </dependency>

```

2.6.2 配置数据库

xml spring.datasource.url=jdbc:mysql://localhost:3306/epidemic?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.username=root spring.datasource.password=123456

2.6.3 使用mybatis-plus进行增删改查的操作

创建mapper

java import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.duing.bean.DataBean; public interface DataMapper extends BaseMapper<DataBean> { }

扫描mapper的注解

在主程序入口类中添加

java @MapperScan("com.duing.mapper")

创建service及其实现类

注意泛型是要处理的实体类

java import com.baomidou.mybatisplus.extension.service.IService; import com.duing.bean.DataBean; import java.util.List; public interface DataService extends IService<DataBean> {}

java // 泛型 分别是mapper 以及 实体类 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.duing.bean.DataBean; import com.duing.mapper.DataMapper; import org.springframework.stereotype.Service; import java.util.List; @Service public class DataServiceImpl extends ServiceImpl<DataMapper,DataBean> implements DataService { }

改造实体类databean

此时要满足,存在无参构造器以及可被序列化,同时指定具体映射的表名,通过@TableName

java import com.baomidou.mybatisplus.annotation.TableName; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; @Data @AllArgsConstructor @NoArgsConstructor @TableName("illness") public class DataBean implements Serializable { private String area; private int nowConfirm; private int confirm; private int heal; private int dead; }

初始化数据存储的逻辑

@PostConstruct 修饰的方法,在服务器加载Servlet时运行,而且只执行一次

改造逻辑:首先将DataHandler声明为组件 @Component

java @Autowired private DataService dataService; @PostConstruct public void saveData() { try { List<DataBean> dataBeans = getData(); // 先将数据清空 然后存储数据 dataService.remove(null); dataService.saveBatch(dataBeans); } catch (Exception e) { e.printStackTrace(); } }

@Scheduled 使用前需要在主程序入口类上打开开关

java @EnableScheduling

在方法上使用注解的参数

  • @Scheduled(fixedRate = 10000) 指定频率的执行任务,从方法执行开始就计时
  • 假设方法执行5s,那么第一次执行开始过了10s后,开始第二次执行

  • @Scheduled(fixedDelay = 10000) 指定间隔的执行任务,从方法执行完成开始计时

  • 假设方法执行5s,那么第一次执行完成过了10s后,开始第二次执行

  • cron表达式,计划执行的表达式,把六个位置用空格分隔,指代不同单位的时间,执行的规律

  • 秒、分钟、小时、日期、月份、星期、(年,可选)

java // 配置定时执行的注解 支持cron表达式 // 每分钟执行一次 更改可参考cron表达式生成网站 @Scheduled(cron = "0 0/1 * * * ?") public void updateData() { System.out.println("更新数据"); saveData(); }

3.展示数据Echarts

是由百度前端技术部开发,基于js的数据可视化图表库。

https://echarts.apache.org/examples/zh/index.html#chart-type-line

分析图形展示的数据来源,然后请求数据后转化成我们需要的格式,传递给页面,通过Echarts渲染出来。

3.1 折线图

3.1.1 分析的请求地址

https://view.inews.qq.com/g2/getOnsInfo?name=disease_other

可以获得json格式的数据,数据的key是chinaDayList

3.1.2 模拟请求

HttpClient使用,应用最广泛的处理http请求的工具。

```xml

org.apache.httpcomponents httpclient 4.5.12 ```

java public static String doGet(String urlStr) { // 提供了 闭合的httpclient对象 CloseableHttpClient httpClient = null; // 也提供了 闭合的响应对象 CloseableHttpResponse response = null; String result = null; try { // 使用默认创建方式 httpClient = HttpClients.createDefault(); // 创建一个get请求 传入url HttpGet httpGet = new HttpGet(urlStr); // 设置请求头的方式 httpGet.addHeader("Accept", "application/json"); // 设置请求参数 连接时间、数据读取时间(socketTimeOut)等 单位是ms // ConnectionRequestTimeout 指从共享连接池中取出连接的超时时间 RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(35000) .setConnectionRequestTimeout(35000) .setSocketTimeout(60000) .build(); // 设置配置参数 httpGet.setConfig(requestConfig); // 执行请求 response = httpClient.execute(httpGet); // 从返回对象中获取返回数据 HttpEntity entity = response.getEntity(); result = EntityUtils.toString(entity); }catch (Exception e){ e.printStackTrace(); } return result; }

3.1.3 解析出数据

java import com.duing.bean.GraphBean; import com.duing.util.HttpClientUtil; import com.google.gson.Gson; import java.util.ArrayList; import java.util.List; import java.util.Map; public class GraphHandler { public static String urlStr = "https://view.inews.qq.com/g2/getOnsInfo?name=disease_other"; public static List<GraphBean> getGraphData() { List<GraphBean> result = new ArrayList<>(); String str = HttpClientUtil.doGet(urlStr); Gson gson = new Gson(); Map map = gson.fromJson(str, Map.class); String subStr = (String) map.get("data"); Map subMap = gson.fromJson(subStr, Map.class); ArrayList list = (ArrayList) subMap.get("chinaDayList"); for (int i = 0; i < list.size(); i++) { Map tmp = (Map)list.get(i); String date = (String)tmp.get("date"); double nowConfirm = (Double)tmp.get("nowConfirm"); GraphBean graphBean = new GraphBean(date,(int)nowConfirm); result.add(graphBean); } return result; } }

3.1.4 数据结构

java @Data @AllArgsConstructor public class GraphBean { private String date; private int nowConfirm; }

3.1.5 返回给页面渲染、

java @GetMapping("/graph") public String graph(Model model) { List<GraphBean> list = GraphHandler.getGraphData(); // 进一步改造数据格式 // 因为前端需要的数据是 x轴所有数据的数组和y轴所有数据的数组 ArrayList<String> dateList = new ArrayList<>(); ArrayList<Integer> nowConfirmList = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { GraphBean graphBean = list.get(i); dateList.add(graphBean.getDate()); nowConfirmList.add(graphBean.getNowConfirm()); } model.addAttribute("dateList", new Gson().toJson(dateList)); model.addAttribute("nowConfirmList", new Gson().toJson(nowConfirmList)); return "graph"; }

```html

Title

```

Echars教程地址: 教程地址

准备dom -> 通过js渲染数据 -> 使用[[${ sth }]] 接收服务端数据 -> 使用JSON.parse()解析json字符串 -> 获得渲染结果

3.2 折线图2

相关逻辑在 GraphAddBean 对应的代码中:处理数据 -> 转化格式 -> 返回数据给echarts渲染

3.2.1 GraphHandler

java public static List<GraphAddBean> getGraphAddData(String str) { List<GraphAddBean> result = new ArrayList<>(); Gson gson = new Gson(); Map map = gson.fromJson(str, Map.class); String subStr = (String) map.get("data"); Map subMap = gson.fromJson(subStr, Map.class); ArrayList list = (ArrayList) subMap.get("chinaDayAddList"); for (int i = 0; i < list.size(); i++) { Map tmp = (Map) list.get(i); String date = (String) tmp.get("date"); double addConfirm = (Double) tmp.get("confirm"); double addSuspect = (Double) tmp.get("suspect"); GraphAddBean graphAddBean = new GraphAddBean(date, (int) addConfirm, (int) addSuspect); result.add(graphAddBean); } return result; }

3.2.2 DataController

java @GetMapping("/graphAdd") public String graphAdd(Model model) { List<GraphAddBean> list = GraphHandler.getGraphAddData(); ArrayList<String> dateList = new ArrayList<>(); ArrayList<Integer> addConfirmList = new ArrayList<>(); ArrayList<Integer> addSuspectList = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { GraphAddBean graphAddBean = list.get(i); dateList.add(graphAddBean.getDate()); addConfirmList.add(graphAddBean.getAddConfirm()); addSuspectList.add(graphAddBean.getAddSuspect()); } model.addAttribute("dateList", new Gson().toJson(dateList)); model.addAttribute("addConfirmList", new Gson().toJson(addConfirmList)); model.addAttribute("addSuspectList", new Gson().toJson(addSuspectList)); return "graphAdd"; }

3.2.3 HTML

增加折线时,主要在legend和series中增加对应元素。

```html

Title

```

3.3 柱状图

先分析数据的来源 -> 经过对数据的处理和计算 -> 发送给前端组件进行渲染

对应在GraphColumnarBean相关的逻辑中,特别之处在于拿到数据之后需要排序。

java @Data @AllArgsConstructor public class GraphColumnarBean implements Comparable<GraphColumnarBean> { private String area; private int fromAbroad; @Override public int compareTo(GraphColumnarBean o) { return o.getFromAbroad() - this.getFromAbroad(); } }

排序之后将前十的数据返回:

java @GetMapping("/graphColumnar") public String graphColumnar(Model model) { List<GraphColumnarBean> list = GraphHandler.getGraphColumnarData(); Collections.sort(list); ArrayList<String> nameList = new ArrayList<>(); ArrayList<Integer> fromAbroadList = new ArrayList<>(); for (int i = 0; i < 10; i++) { GraphColumnarBean bean = list.get(i); nameList.add(bean.getArea()); fromAbroadList.add(bean.getFromAbroad()); } model.addAttribute("nameList", new Gson().toJson(nameList)); model.addAttribute("fromAbroadList", new Gson().toJson(fromAbroadList)); return "graphColumnar"; }

柱状图的数据示例:

java // 指定图表的配置项和数据 var option = { title: { // 标题组件 text: '境外输入省市TOP10' }, tooltip: { // 提示框组件 trigger: 'axis' }, xAxis: { // 转化为json对象 data: JSON.parse(nameStr) }, yAxis: { type: 'value' }, series: [ { name: '境外输入', type: 'bar', barWidth: '60%', data: JSON.parse(fromAbroadStr) } ] };

3.4 饼状图

对应在GraphPieBean相关的逻辑中

graphPie.html

javascript // 指定图表的配置项和数据 var option = { title: { // 标题组件 text: '全国现有确诊构成' }, tooltip: { // 提示框组件 trigger: 'axis' }, series: [ { type: 'pie', radius: '55%', center: ['50%', '60%'], data: JSON.parse(str) } ] };

3.5 中国地图

引入新的js【china.js】,数据来源已存储到表格中。

map.html

```html

Title

```

4.国际化

是对thymeleaf中消息表达式的一种应用, #{} , 提供的是对配置文件中信息的读取。

4.1 使用浏览器识别语种

在resources目录下,创建i18n文件夹,再继续创建 *.properties文件。

设置其中的key和value(注意:此时的编码格式需要在idea的设置中确认)

c++ list.title=渡一出品:疫情最新动态-D list.h2=国内疫情情况如下-D list.table.name1=地区-D list.table.name2=现有确诊-D list.table.name3=累计确诊-D list.table.name4=治愈-D list.table.name5=死亡-D

创建其他语种对应的配置文件,如 *_en_US.properties 和 *_zh_CN.properties

在html中更改对key值的引用方式,使用消息表达式:

```html 渡一出品:疫情最新动态

.... ```

让spring找到国际化文件对应的位置,在application.properties中:

java spring.messages.basename=i18n.list

验证方式:通过更改浏览器中 【设置】 -> 【高级】 -> 【语言】 -> 【找到英语(美国)】,可以通过置顶,切换中英文显示。

本质原因是,因为请求的请求头中,会设置不同的Accept-Language的值。

4.2 自定义切换语种

使用spring提供的国际化使用类 LocaleResolver

页面中增加按钮

html <label> <a th:href="@{/(lan='zh_CN')}">中文</a> <a th:href="@{/(lan='en_US')}">英文</a> </label>

自定义LocaleResolver类的实现

java import org.springframework.util.StringUtils; import org.springframework.web.servlet.LocaleResolver; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Locale; public class MyLocaleResolver implements LocaleResolver { @Override public Locale resolveLocale(HttpServletRequest httpServletRequest) { String lan = httpServletRequest.getParameter("lan"); Locale locale = Locale.getDefault(); if (!StringUtils.isEmpty(lan)) { String[] split = lan.split("_"); locale = new Locale(split[0], split[1]); } return locale; } @Override public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) { } }

注入spring

java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.LocaleResolver; @Configuration public class MyConfig { @Bean public LocaleResolver localeResolver() { return new MyLocaleResolver(); } }

验证

此时切换按钮时,可以看到不同语种的显示

5.订阅数据

5.1 邮件

java提供的原生的工具,设定的邮件发送和接收流程:

【协议】 SMTP = Simple Mail Transfer Protocol 简单邮件传输协议

在邮件发送时主要会使用到的协议,服务器地址形如:smtp.xxxx.com

如果从qq邮箱,发送邮件到126邮箱, 使用的前提是,确认qq邮箱中【设置】 ->【账户】 -> 【SMTP服务】是开启的状态 ->【获取授权码】

xml <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.7</version> </dependency>

java // 从qq邮箱 发送邮件 到126邮箱 public static void send() throws Exception{ // 1) 通过配置构成邮件的会话 Properties prop = new Properties(); // 配置协议和服务器地址 prop.setProperty("mail.transport.protocol","smtp"); prop.setProperty("mail.smtp.host","smtp.qq.com"); prop.setProperty("mail.smtp.auth","true"); String port = "465"; prop.setProperty("mail.smtp.port",port); prop.setProperty("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory"); prop.setProperty("mail.smtp.socketFactory.fallback","false"); prop.setProperty("mail.smtp.socketFactory.port",port); // 2) 创建会话 Session session = Session.getInstance(prop); // 3) 创建一封邮件 MimeMessage message = new MimeMessage(session); String sendMail = "2491638831@qq.com"; String Recipients = "lanluo_bingzi@126.com"; message.setFrom(new InternetAddress(sendMail,"语晴","UTF-8")); // MimeMessage.RecipientType.CC 抄送 MimeMessage.RecipientType.BCC 密送 message.setRecipient(MimeMessage.RecipientType.TO , new InternetAddress(Recipients,"语晴","UTF-8")); // 标题 正文 发件时间 message.setSubject("来自语晴的问候","UTF-8"); message.setContent("不要给我发邮件哦","text/html;charset=UTF-8"); message.setSentDate(new Date()); // 可以保存为 *.eml的文件格式 message.saveChanges(); // 4) 获取邮件传输对象 建立连接 并发送 Transport transport = session.getTransport(); String accout = "2491638831@qq.com"; String password = "*************"; transport.connect(accout,password); transport.sendMessage(message,message.getAllRecipients()); transport.close(); }

springboot中整合

1) 引入依赖

xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency>

2) 参数配置 application.properties

java spring.mail.username=2491638831@qq.com spring.mail.password=********* spring.mail.host=smtp.qq.com spring.mail.properties.mail.smtp.ssl.enable=true

3) 编写逻辑

java @Component public class MailHandler { @Autowired private JavaMailSender mailSender; public void send() { System.out.println("执行邮件发送逻辑"); SimpleMailMessage mailMessage = new SimpleMailMessage(); mailMessage.setSubject("来自渡一的问候"); mailMessage.setText("不要不给阿拓老师发邮件"); mailMessage.setTo("lanluo_bingzi@126.com"); mailMessage.setFrom("2491638831@qq.com"); mailSender.send(mailMessage); } }

4) 改造成模板引擎渲染的html效果

注意: 要更改为自己的邮箱和密码

5.2 异步任务

如果部署多台服务器,如何保障邮件只发送一次?

消息中间件 ,可以做到发送一条消息让所有服务器都接收,也可以做到发送一条消息,只交给某一台服务器接收(重要特性)。

为了符合消息中间件的等待时间,需要先返回消息处理的结果,再进行具体的逻辑,此时使用异步任务。

使用方式

  • 先在主程序入口类上,打开相应的开关 @EnableAsync

  • 在需要异步执行的方法上添加注解 @Async

6.常用功能

6.1 登录

登录页面编写 login.html,登录的校验逻辑

```java @Controller public class LoginControlle

参考文献

  • 微博疫情专题文本的情感分析及可视化(厦门大学·吴萍)
  • 新冠疫情舆情信息分析系统的设计与实现(华中科技大学·胡永辉)
  • 新冠疫情舆情信息分析系统的设计与实现(华中科技大学·胡永辉)
  • 分布式智能网络爬虫的设计与实现(中国科学院大学(工程管理与信息技术学院)·何国正)
  • 基于J2EE的网络舆情分析系统的设计与实现(南京大学·李伟)
  • 基于新浪微博数据的处理与用户行为分析(北京交通大学·王鲁飞)
  • 网络流量统计分析系统(吉林大学·石景龙)
  • 社交网络数据提取与分析(北京邮电大学·任毅)
  • 基于网络爬虫的排行榜系统设计与实现(北京邮电大学·刘全伟)
  • 基于深度学习的微博短文本情感倾向分析(湘潭大学·李维森)
  • 基于网络爬虫的信息采集分类系统设计与实现(厦门大学·周茜)
  • 基于hadoop的生猪行业网络舆情监控分析系统的设计与实现(华南农业大学·徐富健)
  • 社交网络数据提取与分析(北京邮电大学·任毅)
  • 互联网舆情监控系统的设计与实现(湖南师范大学·夏岩)
  • 数据可视化技术及其在疫情防控中的应用研究(武汉轻工大学·蒋迎香)

本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:毕业设计客栈 ,原文地址:https://m.bishedaima.com/yuanma/35510.html

相关推荐

发表回复

登录后才能评论