后台管理爬虫加入事物,解决部分用户章节和内容不匹配的问题

This commit is contained in:
xiongxiaoyang 2019-12-14 09:36:24 +08:00
parent 371eefd6a9
commit cca73526fb
4 changed files with 66 additions and 177 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/novel-front/novel-front.iml

View File

@ -22,8 +22,11 @@ import java.util.regex.Pattern;
import com.java2nb.books.dao.BookCrawlDao;
import com.java2nb.books.domain.BookCrawlDO;
import com.java2nb.books.service.BookCrawlService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import static java.util.regex.Pattern.*;
@Service
public class BookCrawlServiceImpl implements BookCrawlService {
@ -181,7 +184,7 @@ public class BookCrawlServiceImpl implements BookCrawlService {
String bookListUrl = "http://book.sfacg.com/List/default.aspx?&tid=" + catId + "&if=1&PageIndex=" + page;
String forObject = getByHttpClient(bookListUrl);
String forObject = getByTemplate(bookListUrl);
if (forObject != null) {
Pattern bookPatten = Pattern.compile("href=\"/Novel/(\\d+)/\"");
@ -195,7 +198,7 @@ public class BookCrawlServiceImpl implements BookCrawlService {
}
long bookNum = Long.parseLong(bookMatcher.group(1));
String bookUrl = "http://book.sfacg.com/Novel/" + bookNum;
String forObject1 = getByHttpClient(bookUrl);
String forObject1 = getByTemplate(bookUrl);
if (forObject1 != null) {
Pattern updateTimePatten = Pattern.compile("更新:(\\d+/\\d+/\\d+ \\d+:\\d+:\\d+)");
Matcher updateTimeMatch = updateTimePatten.matcher(forObject1);
@ -329,7 +332,7 @@ public class BookCrawlServiceImpl implements BookCrawlService {
//读取目录
String indexUrl = "http://book.sfacg.com/Novel/" + bookNum + "/MainIndex/";
String forObject2 = getByHttpClient(indexUrl);
String forObject2 = getByTemplate(indexUrl);
if (forObject2 != null) {
Pattern indexListPatten = Pattern.compile("href=\"(/Novel/\\d+/\\d+/\\d+/)\"\\s+title=\"([^\"]+)\\s*");
Matcher indexListMatch = indexListPatten.matcher(forObject2);
@ -352,7 +355,7 @@ public class BookCrawlServiceImpl implements BookCrawlService {
//查询章节内容
String forObject3 = getByHttpClient(contentUrl);
String forObject3 = getByTemplate(contentUrl);
if (forObject3 != null && !forObject3.contains("内容整改中,请等待")) {
String content = forObject3.substring(forObject3.indexOf("<div class=\"article-content"));
content = content.substring(0, content.indexOf("</div>") + 6);
@ -413,13 +416,13 @@ public class BookCrawlServiceImpl implements BookCrawlService {
catBookListUrlBase = baseUrl + "/lhb/";
}
//拼接分类URL
int page = 1;//起始页码
int page = 1;
int totalPage = page;
String catBookListUrl = catBookListUrlBase + i + "/" + page + ".html";
String forObject = getByHttpClient(catBookListUrl);
String forObject = getByTemplate(catBookListUrl);
if (forObject != null) {
//匹配分页数<input type="text" class="page_txt" value="1/3019" size="5" name="txtPage" id="txtPage" />
Pattern pattern = Pattern.compile("value=\"(\\d+)/(\\d+)\"");
Pattern pattern = compile("value=\"(\\d+)/(\\d+)\"");
Matcher matcher = pattern.matcher(forObject);
boolean isFind = matcher.find();
System.out.println("匹配分页数" + isFind);
@ -427,7 +430,7 @@ public class BookCrawlServiceImpl implements BookCrawlService {
int currentPage = Integer.parseInt(matcher.group(1));
totalPage = Integer.parseInt(matcher.group(2));
//解析第一页书籍的数据
Pattern bookPatten = Pattern.compile("href=\"/(\\d+_\\d+)/\"");
Pattern bookPatten = compile("href=\"/(\\d+_\\d+)/\"");
parseBiquTaBook(bookPatten, forObject, i, baseUrl);
while (currentPage < totalPage) {
if (isInteruptBiquTaCrawl) {
@ -435,7 +438,7 @@ public class BookCrawlServiceImpl implements BookCrawlService {
}
catBookListUrl = catBookListUrlBase + i + "/" + (currentPage + 1) + ".html";
forObject = getByHttpClient(catBookListUrl);
forObject = getByTemplate(catBookListUrl);
if (forObject != null) {
//匹配分页数
matcher = pattern.matcher(forObject);
@ -457,15 +460,15 @@ public class BookCrawlServiceImpl implements BookCrawlService {
private void parseBiquTaBook(Pattern bookPatten, String forObject, int catNum, String baseUrl) {
Matcher matcher2 = bookPatten.matcher(forObject);
boolean isFind = matcher2.find();
Pattern scorePatten = Pattern.compile("<div\\s+class=\"score\">(\\d+\\.\\d+)分</div>");
Pattern scorePatten = compile("<div\\s+class=\"score\">(\\d+\\.\\d+)分</div>");
Matcher scoreMatch = scorePatten.matcher(forObject);
boolean scoreFind = scoreMatch.find();
Pattern bookNamePatten = Pattern.compile("<p class=\"title\">([^/]+)</p>");
Pattern bookNamePatten = compile("<p class=\"title\">([^/]+)</p>");
Matcher bookNameMatch = bookNamePatten.matcher(forObject);
boolean isBookNameMatch = bookNameMatch.find();
Pattern authorPatten = Pattern.compile(">作者:([^/]+)<");
Pattern authorPatten = compile(">作者:([^/]+)<");
Matcher authoreMatch = authorPatten.matcher(forObject);
boolean isFindAuthor = authoreMatch.find();
@ -498,13 +501,13 @@ public class BookCrawlServiceImpl implements BookCrawlService {
String bokNum = matcher2.group(1);
String bookUrl = baseUrl + "/" + bokNum + "/";
String body = getByHttpClient(bookUrl);
String body = getByTemplate(bookUrl);
if (body != null) {
Pattern statusPatten = Pattern.compile("状态:([^/]+)</li>");
Pattern statusPatten = compile("状态:([^/]+)</li>");
Matcher statusMatch = statusPatten.matcher(body);
if (statusMatch.find()) {
String status = statusMatch.group(1);
Pattern updateTimePatten = Pattern.compile("更新:(\\d+-\\d+-\\d+\\s\\d+:\\d+:\\d+)</a>");
Pattern updateTimePatten = compile("更新:(\\d+-\\d+-\\d+\\s\\d+:\\d+:\\d+)</a>");
Matcher updateTimeMatch = updateTimePatten.matcher(body);
if (updateTimeMatch.find()) {
String updateTimeStr = updateTimeMatch.group(1);
@ -513,12 +516,12 @@ public class BookCrawlServiceImpl implements BookCrawlService {
if (updateTime.getTime() < new SimpleDateFormat("yyyy-MM-dd").parse(crawlConfig.getMinUptTime()).getTime()) {
continue;
}
Pattern picPatten = Pattern.compile("<img src=\"([^>]+)\"\\s+onerror=\"this.src=");
Pattern picPatten = compile("<img src=\"([^>]+)\"\\s+onerror=\"this.src=");
Matcher picMather = picPatten.matcher(body);
if (picMather.find()) {
String picSrc = picMather.group(1);
Pattern descPatten = Pattern.compile("class=\"review\">([^<]+)</p>");
Pattern descPatten = compile("class=\"review\">([^<]+)</p>");
Matcher descMatch = descPatten.matcher(body);
if (descMatch.find()) {
String desc = descMatch.group(1);
@ -538,13 +541,13 @@ public class BookCrawlServiceImpl implements BookCrawlService {
List<BookContentDO> contentList = new ArrayList<>();
//读取目录
Pattern indexPatten = Pattern.compile("<a\\s+href=\"(/du/\\d+_\\d+/)\">查看完整目录</a>");
Pattern indexPatten = compile("<a\\s+href=\"(/du/\\d+_\\d+/)\">查看完整目录</a>");
Matcher indexMatch = indexPatten.matcher(body);
if (indexMatch.find()) {
String indexUrl = baseUrl + indexMatch.group(1);
String body2 = getByHttpClient(indexUrl);
String body2 = getByTemplate(indexUrl);
if (body2 != null) {
Pattern indexListPatten = Pattern.compile("<a\\s+style=\"\"\\s+href=\"(/\\d+_\\d+/\\d+\\.html)\">([^/]+)</a>");
Pattern indexListPatten = compile("<a\\s+style=\"\"\\s+href=\"(/\\d+_\\d+/\\d+\\.html)\">([^/]+)</a>");
Matcher indexListMatch = indexListPatten.matcher(body2);
boolean isFindIndex = indexListMatch.find();
@ -565,7 +568,7 @@ public class BookCrawlServiceImpl implements BookCrawlService {
//查询章节内容
String body3 = getByHttpClient(contentUrl.replace("//m.","//www."));
String body3 = getByTemplate(contentUrl.replace("//m.","//www."));
if (body3 != null) {
String start = "id=\"content\">";
String end = "<script>";
@ -637,10 +640,10 @@ public class BookCrawlServiceImpl implements BookCrawlService {
int page = 1;//起始页码
int totalPage = page;
String catBookListUrl = catBookListUrlBase + i + "/" + page + ".html";
String forObject = getByHttpClient(catBookListUrl);
String forObject = getByTemplate(catBookListUrl);
if (forObject != null) {
//匹配分页数<input type="text" class="page_txt" value="1/3019" size="5" name="txtPage" id="txtPage" />
Pattern pattern = Pattern.compile("value=\"(\\d+)/(\\d+)\"");
Pattern pattern = compile("value=\"(\\d+)/(\\d+)\"");
Matcher matcher = pattern.matcher(forObject);
boolean isFind = matcher.find();
System.out.println("匹配分页数" + isFind);
@ -648,7 +651,7 @@ public class BookCrawlServiceImpl implements BookCrawlService {
int currentPage = Integer.parseInt(matcher.group(1));
totalPage = Integer.parseInt(matcher.group(2));
//解析第一页书籍的数据
Pattern bookPatten = Pattern.compile("href=\"/(bqge\\d+)/\"");
Pattern bookPatten = compile("href=\"/(bqge\\d+)/\"");
parseBiqudaoBook(bookPatten, forObject, i, baseUrl);
while (currentPage < totalPage) {
@ -657,7 +660,7 @@ public class BookCrawlServiceImpl implements BookCrawlService {
}
catBookListUrl = catBookListUrlBase + i + "/" + (currentPage + 1) + ".html";
forObject = getByHttpClient(catBookListUrl);
forObject = getByTemplate(catBookListUrl);
if (forObject != null) {
//匹配分页数
matcher = pattern.matcher(forObject);
@ -681,15 +684,15 @@ public class BookCrawlServiceImpl implements BookCrawlService {
Matcher matcher2 = bookPatten.matcher(forObject);
boolean isFind = matcher2.find();
Pattern scorePatten = Pattern.compile("<div\\s+class=\"score\">(\\d+\\.\\d+)分</div>");
Pattern scorePatten = compile("<div\\s+class=\"score\">(\\d+\\.\\d+)分</div>");
Matcher scoreMatch = scorePatten.matcher(forObject);
boolean scoreFind = scoreMatch.find();
Pattern bookNamePatten = Pattern.compile("<p class=\"title\">([^/]+)</p>");
Pattern bookNamePatten = compile("<p class=\"title\">([^/]+)</p>");
Matcher bookNameMatch = bookNamePatten.matcher(forObject);
boolean isBookNameMatch = bookNameMatch.find();
Pattern authorPatten = Pattern.compile(">作者:([^<]+)<");
Pattern authorPatten = compile(">作者:([^<]+)<");
Matcher authoreMatch = authorPatten.matcher(forObject);
boolean isFindAuthor = authoreMatch.find();
@ -707,7 +710,7 @@ public class BookCrawlServiceImpl implements BookCrawlService {
Float score = Float.parseFloat(scoreMatch.group(1));
if (score < crawlConfig.getLowestScore()) {//数据库空间有限暂时爬取8.0分以上的小说
if (score < crawlConfig.getLowestScore()) {
continue;
}
@ -724,13 +727,13 @@ public class BookCrawlServiceImpl implements BookCrawlService {
String bokNum = matcher2.group(1);
String bookUrl = baseUrl + "/" + bokNum + "/";
String body = getByHttpClient(bookUrl);
String body = getByTemplate(bookUrl);
if (body != null) {
Pattern statusPatten = Pattern.compile("状态:([^/]+)</li>");
Pattern statusPatten = compile("状态:([^/]+)</li>");
Matcher statusMatch = statusPatten.matcher(body);
if (statusMatch.find()) {
String status = statusMatch.group(1);
Pattern updateTimePatten = Pattern.compile("更新:(\\d+-\\d+-\\d+\\s\\d+:\\d+:\\d+)</a>");
Pattern updateTimePatten = compile("更新:(\\d+-\\d+-\\d+\\s\\d+:\\d+:\\d+)</a>");
Matcher updateTimeMatch = updateTimePatten.matcher(body);
if (updateTimeMatch.find()) {
String updateTimeStr = updateTimeMatch.group(1);
@ -739,12 +742,12 @@ public class BookCrawlServiceImpl implements BookCrawlService {
if (updateTime.getTime() < new SimpleDateFormat("yyyy-MM-dd").parse(crawlConfig.getMinUptTime()).getTime()) {
continue;
}
Pattern picPatten = Pattern.compile("<img src=\"([^>]+)\"\\s+onerror=\"this.src=");
Pattern picPatten = compile("<img src=\"([^>]+)\"\\s+onerror=\"this.src=");
Matcher picMather = picPatten.matcher(body);
if (picMather.find()) {
String picSrc = picMather.group(1);
Pattern descPatten = Pattern.compile("class=\"review\">([^<]+)</p>");
Pattern descPatten = compile("class=\"review\">([^<]+)</p>");
Matcher descMatch = descPatten.matcher(body);
if (descMatch.find()) {
String desc = descMatch.group(1);
@ -764,13 +767,13 @@ public class BookCrawlServiceImpl implements BookCrawlService {
List<BookContentDO> contentList = new ArrayList<>();
//读取目录
Pattern indexPatten = Pattern.compile("<a\\s+href=\"(/bqge\\d+/all\\.html)\">查看完整目录</a>");
Pattern indexPatten = compile("<a\\s+href=\"(/bqge\\d+/all\\.html)\">查看完整目录</a>");
Matcher indexMatch = indexPatten.matcher(body);
if (indexMatch.find()) {
String indexUrl = baseUrl + indexMatch.group(1);
String body2 = getByHttpClient(indexUrl);
String body2 = getByTemplate(indexUrl);
if (body2 != null) {
Pattern indexListPatten = Pattern.compile("<a[^/]+style[^/]+href=\"(/bqge\\d+/\\d+\\.html)\">([^/]+)</a>");
Pattern indexListPatten = compile("<a[^/]+style[^/]+href=\"(/bqge\\d+/\\d+\\.html)\">([^/]+)</a>");
Matcher indexListMatch = indexListPatten.matcher(body2);
boolean isFindIndex = indexListMatch.find();
@ -790,9 +793,9 @@ public class BookCrawlServiceImpl implements BookCrawlService {
//查询章节内容
String body3 = getByHttpClient(contentUrl);
String body3 = getByTemplate(contentUrl);
if (body3 != null) {
Pattern contentPattten = Pattern.compile("章节错误,点此举报(.*)加入书签,方便阅读");
Pattern contentPattten = compile("章节错误,点此举报(.*)加入书签,方便阅读");
String start = "『章节错误,点此举报』";
String end = "『加入书签,方便阅读』";
String content = body3.substring(body3.indexOf(start) + start.length(), body3.indexOf(end));
@ -841,7 +844,7 @@ public class BookCrawlServiceImpl implements BookCrawlService {
} finally {
matcher2.find();
isFind = matcher2.find();//需要找两次应为有两个一样的路径匹配
isFind = matcher2.find();
scoreFind = scoreMatch.find();
isBookNameMatch = bookNameMatch.find();
isFindAuthor = authoreMatch.find();
@ -852,9 +855,9 @@ public class BookCrawlServiceImpl implements BookCrawlService {
}
@Transactional(rollbackFor = Exception.class)
public void saveBookAndIndexAndContent(BookDO book, List<BookIndexDO> bookIndex, List<BookContentDO> bookContent) {
boolean isUpdate = false;
Long bookId = -1l;
Long bookId = -1L;
book.setBookName(book.getBookName().trim());
book.setAuthor(book.getAuthor().trim());
Map<String, Object> bookExample = new HashMap<>();
@ -866,7 +869,6 @@ public class BookCrawlServiceImpl implements BookCrawlService {
bookId = books.get(0).getId();
book.setId(bookId);
bookDao.update(book);
isUpdate = true;
} else {
if (book.getVisitCount() == null) {
@ -883,10 +885,6 @@ public class BookCrawlServiceImpl implements BookCrawlService {
}
if (bookId >= 0) {
//查询目录已存在数量
/* BookIndexExample bookIndexExample = new BookIndexExample();
bookIndexExample.createCriteria().andBookIdEqualTo(bookId);
int indexCount = bookIndexMapper.countByExample(bookIndexExample);*/
List<BookIndexDO> newBookIndexList = new ArrayList<>();
@ -899,7 +897,6 @@ public class BookCrawlServiceImpl implements BookCrawlService {
BookIndexDO bookIndexItem = bookIndex.get(i);
bookIndexItem.setBookId(bookId);
bookContentItem.setBookId(bookId);
//bookContentItem.setIndexId(bookIndexItem.getId());暂时使用bookId和IndexNum查询content
bookContentItem.setIndexNum(bookIndexItem.getIndexNum());
newBookIndexList.add(bookIndexItem);
@ -923,24 +920,8 @@ public class BookCrawlServiceImpl implements BookCrawlService {
return Long.parseLong((int)(score*10000) + new Random().nextInt(1000) + "");
}
private String getByHttpClient(String catBookListUrl) {
private String getByTemplate(String catBookListUrl) {
try {
/*HttpClient httpClient = new DefaultHttpClient();
// 设置请求和传输超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(30000).setConnectTimeout(30000)
.setRedirectsEnabled(false) // 不自动重定向
.build();
HttpGet getReq = new HttpGet(catBookListUrl);
getReq.setConfig(requestConfig);
getReq.setHeader("user-agent", "Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1");
HttpResponse execute = httpClient.execute(getReq);
if (execute.getStatusLine().getStatusCode() == HttpStatus.OK.value()) {
HttpEntity entity = execute.getEntity();
return EntityUtils.toString(entity, "utf-8");
} else {
return null;
}*/
//经测试restTemplate比httpClient效率高出很多倍所有选择restTemplate
ResponseEntity<String> forEntity = restTemplate.getForEntity(catBookListUrl, String.class);
if (forEntity.getStatusCode() == HttpStatus.OK) {
return forEntity.getBody();

View File

@ -1,10 +1,15 @@
package com.java2nb.books.util;
import lombok.SneakyThrows;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
@ -29,9 +34,21 @@ public class RestTemplateUtil {
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(csf)
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", csf)
.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
//连接池的最大连接数0代表不限如果取0需要考虑连接泄露导致系统崩溃的后果
connectionManager.setMaxTotal(1000);
//每个路由的最大连接数,如果只调用一个地址,可以将其设置为最大连接数
connectionManager.setDefaultMaxPerRoute(300);
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.build();
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory();

View File

@ -1,110 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.0.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.0.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.0.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.0.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.0.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.10.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.10.0" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.25" level="project" />
<orderEntry type="library" name="Maven: javax.annotation:javax.annotation-api:1.3.2" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.19" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.0.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.9.5" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.9.0" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.9.5" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.5" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.5" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.5" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.0.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:8.5.29" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:8.5.29" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:8.5.29" level="project" />
<orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:6.0.9.Final" level="project" />
<orderEntry type="library" name="Maven: javax.validation:validation-api:2.0.1.Final" level="project" />
<orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.3.2.Final" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.3.4" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-web:5.0.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.0.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.0.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.0.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.0.5.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:2.0.1.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:2.0.1.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:2.0.1.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.4.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.4" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.9.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:2.15.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy:1.7.11" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.7.11" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.6" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.5.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.0.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.0.5.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:5.0.5.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.xmlunit:xmlunit-core:2.5.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-cache:2.0.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.0.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context-support:5.0.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: net.sf.ehcache:ehcache:2.10.4" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-thymeleaf:2.0.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.thymeleaf:thymeleaf-spring5:3.0.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.thymeleaf:thymeleaf:3.0.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.attoparser:attoparser:2.0.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.unbescape:unbescape:1.1.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.thymeleaf.extras:thymeleaf-extras-java8time:3.0.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-starter:1.2.5" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-autoconfigure:1.2.5" level="project" />
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper:5.1.4" level="project" />
<orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:1.0" level="project" />
<orderEntry type="library" name="Maven: com.cuisongliu:orderbyhelper-spring-boot-starter:1.0.2" level="project" />
<orderEntry type="library" name="Maven: com.cuisongliu:orderbyhelper-spring-boot-autoconfigure:1.0" level="project" />
<orderEntry type="library" name="Maven: tk.mybatis:orderby-helper:0.0.2" level="project" />
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:8.0.11" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: com.google.protobuf:protobuf-java:2.6.0" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.0.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.zaxxer:HikariCP:2.7.8" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.0.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-tx:5.0.5.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:1.3.2" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.4.6" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:1.3.2" level="project" />
<orderEntry type="library" name="Maven: org.projectlombok:lombok:1.16.20" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.10" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.6" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.11" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-mail:2.0.1.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.sun.mail:javax.mail:1.6.1" level="project" />
<orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.4" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.7" level="project" />
</component>
</module>