diff --git a/blog.sql b/blog.sql
index 7e5c289..f7a49f2 100644
--- a/blog.sql
+++ b/blog.sql
@@ -72,13 +72,15 @@ CREATE TABLE `comment`
CREATE TABLE `links`
(
- `l_id` bigint(20) primary key auto_increment,
- `l_name` varchar(255) COLLATE utf8mb4_unicode_ci not null comment '友站名称',
- `l_is_open` boolean default true comment '是否公开',
- `l_url` varchar(255) not null comment '首页地址',
- `l_icon_path` varchar(255) not null comment '友链的icon地址',
- `l_desc` varchar(255) COLLATE utf8mb4_unicode_ci not null comment '友链的说明描述',
- `is_delete` boolean not null default false comment '该数据是否被删除'
+ `l_id` bigint(20) primary key auto_increment,
+ `l_name` varchar(255) COLLATE utf8mb4_unicode_ci not null comment '友站名称',
+ `l_is_open` boolean default true comment '是否公开',
+ `l_url` varchar(255) unique not null comment '首页地址',
+ `l_icon_path` varchar(255) not null comment '友链的icon地址',
+ `l_desc` varchar(255) COLLATE utf8mb4_unicode_ci not null comment '友链的说明描述',
+ `is_delete` boolean not null default false comment '该数据是否被删除',
+ `l_email` varchar(255) comment '网站管理员的邮箱',
+ `l_notification` boolean default false comment '是否通知了'
) comment '友站表';
CREATE TABLE `visitor`
diff --git a/pom.xml b/pom.xml
index cfa39a2..63643ee 100644
--- a/pom.xml
+++ b/pom.xml
@@ -148,6 +148,29 @@
jjwt
0.9.1
+
+
+
+ com.squareup.okhttp3
+ okhttp
+ 4.8.0
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ 1.3.72
+ compile
+
+
+
+
+ net.sourceforge.htmlunit
+ htmlunit
+ 2.42.0
+
+
+
+
@@ -157,21 +180,15 @@
spring-boot-maven-plugin
- org.jacoco
- jacoco-maven-plugin
- 0.7.9
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+ 1.3.72
- pre-unit-test
+ compile
+ process-sources
- prepare-agent
-
-
-
- post-unit-test
- test
-
- report
+ compile
diff --git a/src/main/java/cn/celess/blog/configuration/CorsConfig.java b/src/main/java/cn/celess/blog/configuration/CorsConfig.java
index f2b1634..d90e4ff 100644
--- a/src/main/java/cn/celess/blog/configuration/CorsConfig.java
+++ b/src/main/java/cn/celess/blog/configuration/CorsConfig.java
@@ -26,7 +26,7 @@ public class CorsConfig {
config.addAllowedOrigin("https://celess.cn");
config.addAllowedOrigin("https://www.celess.cn");
// 本地调试时的跨域
- if ("dev".equals(activeModel)) {
+ if (!"prod".equals(activeModel)) {
config.addAllowedOrigin("http://localhost:4200");
config.addAllowedOrigin("http://127.0.0.1:4200");
}
diff --git a/src/main/java/cn/celess/blog/configuration/SwaggerConfig.java b/src/main/java/cn/celess/blog/configuration/SwaggerConfig.java
index e2d464b..46c2970 100644
--- a/src/main/java/cn/celess/blog/configuration/SwaggerConfig.java
+++ b/src/main/java/cn/celess/blog/configuration/SwaggerConfig.java
@@ -26,7 +26,7 @@ public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
- .enable("dev".equals(environment))
+ .enable(!"prod".equals(environment))
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("cn.celess.blog"))
diff --git a/src/main/java/cn/celess/blog/controller/CommonController.java b/src/main/java/cn/celess/blog/controller/CommonController.java
index 39dca2c..902ffb6 100644
--- a/src/main/java/cn/celess/blog/controller/CommonController.java
+++ b/src/main/java/cn/celess/blog/controller/CommonController.java
@@ -135,8 +135,6 @@ public class CommonController {
* FUCK !!!
*
* @param file 文件
- * @return
- * @throws IOException
*/
@PostMapping("/imgUpload")
public void upload(HttpServletRequest request, HttpServletResponse response, @RequestParam("editormd-image-file") MultipartFile file) throws IOException {
@@ -158,6 +156,7 @@ public class CommonController {
return;
}
String fileName = file.getOriginalFilename();
+ assert fileName != null;
String mime = fileName.substring(fileName.lastIndexOf("."));
if (".png".equals(mime.toLowerCase()) || ".jpg".equals(mime.toLowerCase()) ||
".jpeg".equals(mime.toLowerCase()) || ".bmp".equals(mime.toLowerCase())) {
@@ -178,11 +177,7 @@ public class CommonController {
public Response bingPic() {
JSONObject imageObj;
- try {
- imageObj = JSONObject.fromObject(HttpUtil.get("https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=zh-CN"));
- } catch (IOException e) {
- return Response.failure(null);
- }
+ imageObj = JSONObject.fromObject(HttpUtil.get("https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=zh-CN"));
JSONArray jsonArray = imageObj.getJSONArray("images");
String imageName = jsonArray.getJSONObject(0).getString("url");
return Response.success("https://cn.bing.com" + imageName);
diff --git a/src/main/java/cn/celess/blog/controller/LinksController.java b/src/main/java/cn/celess/blog/controller/LinksController.java
index 943657f..fb5b599 100644
--- a/src/main/java/cn/celess/blog/controller/LinksController.java
+++ b/src/main/java/cn/celess/blog/controller/LinksController.java
@@ -3,6 +3,7 @@ package cn.celess.blog.controller;
import cn.celess.blog.enmu.ResponseEnum;
import cn.celess.blog.entity.PartnerSite;
import cn.celess.blog.entity.Response;
+import cn.celess.blog.entity.request.LinkApplyReq;
import cn.celess.blog.entity.request.LinkReq;
import cn.celess.blog.exception.MyException;
import cn.celess.blog.service.MailService;
@@ -69,29 +70,12 @@ public class LinksController {
}
@PostMapping("/apply")
- public Response apply(@RequestParam("name") String name,
- @RequestParam("url") String url) {
- // TODO :: 弃用发送邮件的方式。
- if (name == null || name.replaceAll(" ", "").isEmpty()) {
- return Response.response(ResponseEnum.PARAMETERS_ERROR, null);
- }
- if (!RegexUtil.urlMatch(url)) {
- return Response.response(ResponseEnum.PARAMETERS_URL_ERROR, null);
- }
- String applyTimeStr = redisUtil.get(request.getRemoteAddr() + "-Apply");
- int applyTime = 0;
- if (applyTimeStr != null) {
- applyTime = Integer.parseInt(applyTimeStr);
- }
- if (applyTime == 10) {
- throw new MyException(ResponseEnum.FAILURE.getCode(), "申请次数已达10次,请2小时后重试");
- }
- SimpleMailMessage message = new SimpleMailMessage();
- message.setSubject("友链申请:" + name);
- message.setTo("a@celess.cn");
- message.setText("name:" + name + "\nurl:" + url + "\n" + DateFormatUtil.getNow());
- Boolean send = mailService.send(message);
- redisUtil.setEx(request.getRemoteAddr() + "-Apply", applyTime + 1 + "", 2, TimeUnit.HOURS);
- return send ? Response.success("") : Response.failure("");
+ public Response apply(@RequestBody() LinkApplyReq linkApplyReq) {
+ return Response.success(partnerSiteService.apply(linkApplyReq));
+ }
+
+ @PostMapping("/reapply")
+ public Response reapply(@RequestParam("key") String key) {
+ return Response.success(partnerSiteService.reapply(key));
}
}
diff --git a/src/main/java/cn/celess/blog/enmu/ResponseEnum.java b/src/main/java/cn/celess/blog/enmu/ResponseEnum.java
index 9cca273..6c98fa5 100644
--- a/src/main/java/cn/celess/blog/enmu/ResponseEnum.java
+++ b/src/main/java/cn/celess/blog/enmu/ResponseEnum.java
@@ -58,6 +58,9 @@ public enum ResponseEnum {
DATA_HAS_EXIST(7020, "数据已存在"),
//其他
+ APPLY_LINK_NO_ADD_THIS_SITE(7200, "暂未在您的网站中抓取到本站链接"),
+ DATA_EXPIRED(7300, "数据过期"),
+ CANNOT_GET_DATA(7400, "暂无法获取到数据"),
//提交更新之前,没有获取数据/,
DID_NOT_GET_THE_DATA(8020, "非法访问"),
diff --git a/src/main/java/cn/celess/blog/entity/PartnerSite.java b/src/main/java/cn/celess/blog/entity/PartnerSite.java
index a45c477..87a26e2 100644
--- a/src/main/java/cn/celess/blog/entity/PartnerSite.java
+++ b/src/main/java/cn/celess/blog/entity/PartnerSite.java
@@ -25,6 +25,10 @@ public class PartnerSite {
private Boolean delete = false;
+ private String email;
+
+ private Boolean notification = true;
+
public PartnerSite() {
}
diff --git a/src/main/java/cn/celess/blog/entity/request/LinkApplyReq.java b/src/main/java/cn/celess/blog/entity/request/LinkApplyReq.java
new file mode 100644
index 0000000..910332b
--- /dev/null
+++ b/src/main/java/cn/celess/blog/entity/request/LinkApplyReq.java
@@ -0,0 +1,17 @@
+package cn.celess.blog.entity.request;
+
+import lombok.Data;
+
+/**
+ * @author : xiaohai
+ * @date : 2020/07/31 20:50
+ */
+@Data
+public class LinkApplyReq {
+ private String name;
+ private String email;
+ private String url;
+ private String linkUrl;
+ private String desc;
+ private String iconPath;
+}
diff --git a/src/main/java/cn/celess/blog/exception/ExceptionHandle.java b/src/main/java/cn/celess/blog/exception/ExceptionHandle.java
index a35ab64..7dc8064 100644
--- a/src/main/java/cn/celess/blog/exception/ExceptionHandle.java
+++ b/src/main/java/cn/celess/blog/exception/ExceptionHandle.java
@@ -39,8 +39,9 @@ public class ExceptionHandle {
public Response handle(Exception e) {
//自定义错误
if (e instanceof MyException) {
- logger.debug("返回了自定义的exception,[code={},msg={}]", ((MyException) e).getCode(), e.getMessage());
- return new Response(((MyException) e).getCode(), e.getMessage(), null);
+ MyException exception = (MyException) e;
+ logger.debug("返回了自定义的exception,[code={},msg={},result={}]", exception.getCode(), e.getMessage(), exception.getResult());
+ return new Response(exception.getCode(), e.getMessage(), exception.getResult());
}
//请求路径不支持该方法
if (e instanceof HttpRequestMethodNotSupportedException) {
diff --git a/src/main/java/cn/celess/blog/exception/MyException.java b/src/main/java/cn/celess/blog/exception/MyException.java
index 7c4d412..6046d4f 100644
--- a/src/main/java/cn/celess/blog/exception/MyException.java
+++ b/src/main/java/cn/celess/blog/exception/MyException.java
@@ -1,13 +1,16 @@
package cn.celess.blog.exception;
import cn.celess.blog.enmu.ResponseEnum;
+import lombok.Data;
/**
* @author : xiaohai
* @date : 2019/03/28 16:56
*/
+@Data
public class MyException extends RuntimeException {
private int code;
+ private Object result;
public MyException(int code, String msg) {
super(msg);
@@ -24,11 +27,9 @@ public class MyException extends RuntimeException {
this.code = e.getCode();
}
- public int getCode() {
- return code;
- }
-
- public void setCode(int code) {
- this.code = code;
+ public MyException(ResponseEnum e, String msg, Object result) {
+ super(e.getMsg());
+ this.code = e.getCode();
+ this.result = result;
}
}
diff --git a/src/main/java/cn/celess/blog/service/PartnerSiteService.java b/src/main/java/cn/celess/blog/service/PartnerSiteService.java
index 6d28b27..e76db4a 100644
--- a/src/main/java/cn/celess/blog/service/PartnerSiteService.java
+++ b/src/main/java/cn/celess/blog/service/PartnerSiteService.java
@@ -2,6 +2,7 @@ package cn.celess.blog.service;
import cn.celess.blog.entity.PartnerSite;
import cn.celess.blog.entity.model.PageData;
+import cn.celess.blog.entity.request.LinkApplyReq;
import cn.celess.blog.entity.request.LinkReq;
import org.springframework.stereotype.Service;
@@ -53,4 +54,19 @@ public interface PartnerSiteService {
*/
List findAll();
+ /**
+ * 申请友链
+ *
+ * @param linkApplyReq linkApplyReq
+ * @return linkApplyReq
+ */
+ PartnerSite apply(LinkApplyReq linkApplyReq);
+
+ /**
+ * 重写申请友链
+ *
+ * @param key key
+ * @return msg
+ */
+ String reapply(String key);
}
diff --git a/src/main/java/cn/celess/blog/service/serviceimpl/PartnerSiteServiceImpl.java b/src/main/java/cn/celess/blog/service/serviceimpl/PartnerSiteServiceImpl.java
index 81302c2..af49b48 100644
--- a/src/main/java/cn/celess/blog/service/serviceimpl/PartnerSiteServiceImpl.java
+++ b/src/main/java/cn/celess/blog/service/serviceimpl/PartnerSiteServiceImpl.java
@@ -3,18 +3,30 @@ package cn.celess.blog.service.serviceimpl;
import cn.celess.blog.enmu.ResponseEnum;
import cn.celess.blog.entity.PartnerSite;
import cn.celess.blog.entity.model.PageData;
+import cn.celess.blog.entity.request.LinkApplyReq;
import cn.celess.blog.entity.request.LinkReq;
import cn.celess.blog.exception.MyException;
import cn.celess.blog.mapper.PartnerMapper;
+import cn.celess.blog.service.MailService;
import cn.celess.blog.service.PartnerSiteService;
+import cn.celess.blog.util.HttpUtil;
+import cn.celess.blog.util.JwtUtil;
+import cn.celess.blog.util.RedisUtil;
import cn.celess.blog.util.RegexUtil;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
+import lombok.SneakyThrows;
+import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Service;
+import java.util.Date;
import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
/**
* @author : xiaohai
@@ -24,6 +36,13 @@ import java.util.List;
public class PartnerSiteServiceImpl implements PartnerSiteService {
@Autowired
PartnerMapper partnerMapper;
+ @Autowired
+ MailService mailService;
+ @Autowired
+ RedisUtil redisUtil;
+ private static final String SITE_NAME = "小海博客";
+ private static final String SITE_URL = "celess.cn";
+ private static final String SITE_EMAIL = "a@celess.cn";
@Override
public PartnerSite create(LinkReq reqBody) {
@@ -86,10 +105,21 @@ public class PartnerSiteServiceImpl implements PartnerSiteService {
if (!reqBody.getUrl().contains("http://") && !reqBody.getUrl().contains("https://")) {
reqBody.setUrl("http://" + reqBody.getUrl());
}
+ if (reqBody.isOpen() != partnerSite.getOpen() && !partnerSite.getNotification() && !StringUtils.isEmpty(partnerSite.getEmail())) {
+ SimpleMailMessage smm = new SimpleMailMessage();
+ smm.setTo(partnerSite.getEmail());
+ smm.setText("您的友链申请,已通过");
+ smm.setSubject("友链申请通过");
+ smm.setSentDate(new Date());
+ mailService.send(smm);
+ partnerSite.setNotification(true);
+ }
+ BeanUtils.copyProperties(reqBody, partnerSite);
+ partnerMapper.update(partnerSite);
partnerSite.setName(reqBody.getName());
partnerSite.setUrl(reqBody.getUrl());
partnerSite.setOpen(reqBody.isOpen());
- partnerMapper.update(partnerSite);
+
return partnerSite;
}
@@ -108,5 +138,92 @@ public class PartnerSiteServiceImpl implements PartnerSiteService {
return all;
}
+ @SneakyThrows
+ @Override
+ public PartnerSite apply(LinkApplyReq linkApplyReq) {
+ // 空值字段
+ if (StringUtils.isEmpty(linkApplyReq.getName())
+ || StringUtils.isEmpty(linkApplyReq.getUrl())
+ || StringUtils.isEmpty(linkApplyReq.getEmail())
+ || StringUtils.isEmpty(linkApplyReq.getLinkUrl())) {
+ throw new MyException(ResponseEnum.PARAMETERS_ERROR);
+ }
+ // 链接不合法
+ if (!RegexUtil.emailMatch(linkApplyReq.getEmail())) {
+ throw new MyException(ResponseEnum.PARAMETERS_EMAIL_ERROR);
+ }
+ if (!RegexUtil.urlMatch(linkApplyReq.getLinkUrl()) || !RegexUtil.urlMatch(linkApplyReq.getUrl())) {
+ throw new MyException(ResponseEnum.PARAMETERS_URL_ERROR);
+ }
+ if (!StringUtils.isEmpty(linkApplyReq.getIconPath()) && !RegexUtil.urlMatch(linkApplyReq.getIconPath())) {
+ throw new MyException(ResponseEnum.PARAMETERS_URL_ERROR);
+ }
+ // 非强制字段 设置空
+ if (StringUtils.isEmpty(linkApplyReq.getIconPath())) {
+ linkApplyReq.setIconPath("");
+ }
+ // 抓取页面
+ String resp = HttpUtil.getAfterRendering(linkApplyReq.getLinkUrl());
+ if (resp == null) {
+ throw new MyException(ResponseEnum.CANNOT_GET_DATA);
+ }
+ PartnerSite ps = new PartnerSite();
+ if (resp.contains(SITE_URL)) {
+ //包含站点
+ BeanUtils.copyProperties(linkApplyReq, ps);
+ ps.setNotification(false);
+ ps.setOpen(false);
+ boolean exists = partnerMapper.existsByUrl(linkApplyReq.getUrl());
+ if (!exists) {
+ partnerMapper.insert(ps);
+ } else {
+ ps.setId(partnerMapper.findByUrl(linkApplyReq.getUrl()).getId());
+ }
+ SimpleMailMessage smm = new SimpleMailMessage();
+ smm.setSubject("友链申请");
+ smm.setText("有一条友链申请" + (exists ? ",已存在的友链链接" : "") + ",[\n" + linkApplyReq.toString() + "\n]");
+ smm.setTo(SITE_EMAIL);
+ smm.setSentDate(new Date());
+ mailService.send(smm);
+ } else {
+ // 不包含站点
+ String uuid;
+ ObjectMapper mapper = new ObjectMapper();
+ if (redisUtil.hasKey(linkApplyReq.getUrl())) {
+ uuid = redisUtil.get(linkApplyReq.getUrl());
+ if (!redisUtil.hasKey(uuid)) {
+ redisUtil.setEx(uuid, mapper.writeValueAsString(linkApplyReq), 10, TimeUnit.MINUTES);
+ }
+ } else {
+ uuid = UUID.randomUUID().toString().replaceAll("-", "");
+ redisUtil.setEx(uuid, mapper.writeValueAsString(linkApplyReq), 10, TimeUnit.MINUTES);
+ redisUtil.setEx(linkApplyReq.getUrl(), uuid, 10, TimeUnit.MINUTES);
+ }
+ throw new MyException(ResponseEnum.APPLY_LINK_NO_ADD_THIS_SITE, null, uuid);
+ }
+ return ps;
+ }
+ @SneakyThrows
+ @Override
+ public String reapply(String key) {
+ if (!redisUtil.hasKey(key)) {
+ throw new MyException(ResponseEnum.DATA_EXPIRED);
+ }
+ String s = redisUtil.get(key);
+ ObjectMapper mapper = new ObjectMapper();
+ LinkApplyReq linkApplyReq = mapper.readValue(s, LinkApplyReq.class);
+ if (linkApplyReq == null) {
+ throw new MyException(ResponseEnum.DATA_NOT_EXIST);
+ }
+ SimpleMailMessage smm = new SimpleMailMessage();
+ smm.setSubject("友链申请");
+ smm.setText("有一条未抓取到信息的友链申请,[\n" + linkApplyReq.toString() + "\n]");
+ smm.setTo(SITE_EMAIL);
+ smm.setSentDate(new Date());
+ mailService.send(smm);
+ redisUtil.delete(key);
+ redisUtil.delete(linkApplyReq.getUrl());
+ return "success";
+ }
}
diff --git a/src/main/java/cn/celess/blog/service/serviceimpl/WebUpdateInfoServiceImpl.java b/src/main/java/cn/celess/blog/service/serviceimpl/WebUpdateInfoServiceImpl.java
index f23665a..17b53f6 100644
--- a/src/main/java/cn/celess/blog/service/serviceimpl/WebUpdateInfoServiceImpl.java
+++ b/src/main/java/cn/celess/blog/service/serviceimpl/WebUpdateInfoServiceImpl.java
@@ -88,19 +88,15 @@ public class WebUpdateInfoServiceImpl implements WebUpdateInfoService {
JSONObject jsonObject = new JSONObject();
jsonObject.put("lastUpdateTime", DateFormatUtil.get(webUpdateInfoMapper.getLastestOne().getUpdateTime()));
jsonObject.put("lastUpdateInfo", webUpdateInfoMapper.getLastestOne().getUpdateInfo());
- try {
- JSONArray array = JSONArray.fromObject(HttpUtil.get("https://api.github.com/repos/xiaohai2271/blog-frontEnd/commits?page=1&per_page=1"));
- JSONObject object = array.getJSONObject(0);
- JSONObject commit = object.getJSONObject("commit");
- jsonObject.put("lastCommit", commit.getString("message"));
- jsonObject.put("committerAuthor", commit.getJSONObject("committer").getString("name"));
- SimpleDateFormat sdf = new SimpleDateFormat();
- Instant parse = Instant.parse(commit.getJSONObject("committer").getString("date"));
- jsonObject.put("committerDate", DateFormatUtil.get(Date.from(parse)));
- jsonObject.put("commitUrl", "https://github.com/xiaohai2271/blog-frontEnd/tree/" + object.getString("sha"));
- } catch (IOException e) {
- log.info("网络请求失败{}", e.getMessage());
- }
+ JSONArray array = JSONArray.fromObject(HttpUtil.get("https://api.github.com/repos/xiaohai2271/blog-frontEnd/commits?page=1&per_page=1"));
+ JSONObject object = array.getJSONObject(0);
+ JSONObject commit = object.getJSONObject("commit");
+ jsonObject.put("lastCommit", commit.getString("message"));
+ jsonObject.put("committerAuthor", commit.getJSONObject("committer").getString("name"));
+ SimpleDateFormat sdf = new SimpleDateFormat();
+ Instant parse = Instant.parse(commit.getJSONObject("committer").getString("date"));
+ jsonObject.put("committerDate", DateFormatUtil.get(Date.from(parse)));
+ jsonObject.put("commitUrl", "https://github.com/xiaohai2271/blog-frontEnd/tree/" + object.getString("sha"));
return jsonObject;
}
diff --git a/src/main/java/cn/celess/blog/util/HttpUtil.java b/src/main/java/cn/celess/blog/util/HttpUtil.java
index 8c37ff0..8dcc7fb 100644
--- a/src/main/java/cn/celess/blog/util/HttpUtil.java
+++ b/src/main/java/cn/celess/blog/util/HttpUtil.java
@@ -1,12 +1,16 @@
package cn.celess.blog.util;
-import java.io.BufferedReader;
+import com.gargoylesoftware.htmlunit.BrowserVersion;
+import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
+import com.gargoylesoftware.htmlunit.WebClient;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
+import java.net.MalformedURLException;
+import java.util.Objects;
/**
* @Author: 小海
@@ -14,8 +18,10 @@ import java.nio.charset.StandardCharsets;
* @Desc:
*/
public class HttpUtil {
+ private static final OkHttpClient CLIENT = new OkHttpClient();
- public static String get(String urlStr) throws IOException {
+
+ /*public static String get(String urlStr) throws IOException {
StringBuffer sb = new StringBuffer();
@@ -48,4 +54,33 @@ public class HttpUtil {
}
return sb.toString();
}
+*/
+ public static String get(String urlStr) {
+ Request request = new Request.Builder()
+ .url(urlStr)
+ .get()
+ .build();
+ try (Response response = CLIENT.newCall(request).execute()) {
+ return Objects.requireNonNull(response.body()).string();
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+
+ public static String getAfterRendering(String url) {
+ try (final WebClient webClient = new WebClient(BrowserVersion.CHROME)) {
+ webClient.getOptions().setCssEnabled(false);
+ webClient.getOptions().setJavaScriptEnabled(true);
+ webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
+ webClient.getOptions().setThrowExceptionOnScriptError(false);
+ webClient.getOptions().setDownloadImages(false);
+ webClient.getOptions().setActiveXNative(false);
+ webClient.setAjaxController(new NicelyResynchronizingAjaxController());
+ final HtmlPage page = webClient.getPage(url);
+ return page.asXml();
+ } catch (IOException e) {
+ return null;
+ }
+ }
}
diff --git a/src/main/resources/mapper/PartnerSiteMapper.xml b/src/main/resources/mapper/PartnerSiteMapper.xml
index d15d7ff..b763e3d 100644
--- a/src/main/resources/mapper/PartnerSiteMapper.xml
+++ b/src/main/resources/mapper/PartnerSiteMapper.xml
@@ -9,20 +9,26 @@
+
+
- insert into links (l_name, l_is_open, l_url, l_icon_path, l_desc, is_delete)
- values (#{name}, #{open}, #{url}, #{iconPath}, #{desc}, false)
+ insert into links (l_name, l_is_open, l_url, l_icon_path, l_desc, l_email, l_notification, is_delete)
+ values (#{name}, #{open}, #{url}, #{iconPath}, #{desc}, #{email}, #{notification}, false)
- update links set
- l_is_open=#{open},
- l_icon_path=#{iconPath},
- l_desc=#{desc},
- l_url=#{url},
- l_name=#{name}
+ update links
+
+ l_is_open=#{open},
+ l_icon_path=#{iconPath},
+ l_desc=#{desc},
+ l_url=#{url},
+ l_name=#{name},
+ l_notification=#{notification},
+ l_email=#{email}
+
where l_id=#{id}
diff --git a/src/test/java/cn/celess/blog/BaseTest.java b/src/test/java/cn/celess/blog/BaseTest.java
index 50bcad4..42c1cc3 100644
--- a/src/test/java/cn/celess/blog/BaseTest.java
+++ b/src/test/java/cn/celess/blog/BaseTest.java
@@ -4,27 +4,37 @@ package cn.celess.blog;
import cn.celess.blog.entity.Response;
import cn.celess.blog.entity.model.UserModel;
import cn.celess.blog.entity.request.LoginReq;
+import cn.celess.blog.service.MailService;
+import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
+import org.springframework.mail.SimpleMailMessage;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
-import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+import java.util.Map;
import java.util.UUID;
import static cn.celess.blog.enmu.ResponseEnum.SUCCESS;
@@ -44,16 +54,24 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@ActiveProfiles("test")
public class BaseTest {
+
+ private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
protected MockMvc mockMvc;
protected final static String Code = "code";
protected final static String Result = "result";
- private static String userToken = null;
- private static String adminToken = null;
/**
* jackson 序列化/反序列化Json
*/
protected final ObjectMapper mapper = new ObjectMapper();
-
+ protected static final TypeReference> BOOLEAN_TYPE = new TypeReference>() {
+ };
+ protected static final TypeReference> STRING_TYPE = new TypeReference>() {
+ };
+ protected static final TypeReference> OBJECT_TYPE = new TypeReference>() {
+ };
+ protected static final TypeReference> MAP_OBJECT_TYPE = new TypeReference>>() {
+ };
@Autowired
private WebApplicationContext wac;
protected MockHttpSession session;
@@ -76,14 +94,13 @@ public class BaseTest {
* @return token
*/
protected String adminLogin() {
- if (adminToken != null) return adminToken;
LoginReq req = new LoginReq();
req.setEmail("a@celess.cn");
req.setPassword("123456789");
- req.setIsRememberMe(false);
- adminToken = login(req);
- assertNotNull(adminToken);
- return adminToken;
+ req.setIsRememberMe(true);
+ String token = login(req);
+ assertNotNull(token);
+ return token;
}
/**
@@ -92,14 +109,13 @@ public class BaseTest {
* @return token
*/
protected String userLogin() {
- if (userToken != null) return userToken;
LoginReq req = new LoginReq();
req.setEmail("zh56462271@qq.com");
req.setPassword("123456789");
- req.setIsRememberMe(false);
- userToken = login(req);
- assertNotNull(userToken);
- return userToken;
+ req.setIsRememberMe(true);
+ String token = login(req);
+ assertNotNull(token);
+ return token;
}
/**
@@ -120,8 +136,10 @@ public class BaseTest {
assertNotNull(token);
return token;
} catch (Exception e) {
+ logger.error("测试登录错误");
e.printStackTrace();
}
+ assertNotNull(str);
return null;
}
@@ -130,9 +148,11 @@ public class BaseTest {
// 测试登录
assertNotNull(userLogin());
assertNotNull(adminLogin());
+ assertNotEquals(userLogin(), adminLogin());
try {
// 测试getMockData方法
assertNotNull(getMockData(get("/headerInfo")));
+ getMockData((get("/headerInfo"))).andDo(result -> assertNotNull(getResponse(result, OBJECT_TYPE)));
} catch (Exception e) {
e.printStackTrace();
}
@@ -141,13 +161,21 @@ public class BaseTest {
/**
* 产生指定长度的随机字符
*
- * @param len
- * @return
+ * @param len len
+ * @return str
*/
protected String randomStr(int len) {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, len);
}
+ /**
+ * 产生指定长度的随机字符
+ *
+ * @return str
+ */
+ protected String randomStr() {
+ return UUID.randomUUID().toString();
+ }
/**
* 抽离的mock请求方法
@@ -191,4 +219,101 @@ public class BaseTest {
}
return mockMvc.perform(builder).andExpect(status().isOk());
}
+
+
+ protected Response getResponse(String json) {
+ return getResponse(json, OBJECT_TYPE);
+ }
+
+ protected Response getResponse(MvcResult result) {
+ return getResponse(result, OBJECT_TYPE);
+ }
+
+ /**
+ * 根据json 信息反序列化成Response对象
+ *
+ * @param json json
+ * @param 泛型
+ * @return Response对象
+ */
+ protected Response getResponse(String json, TypeReference> responseType) {
+ Response response = null;
+ System.out.println(responseType.getType());
+ try {
+ response = mapper.readValue(json, responseType);
+ } catch (IOException e) {
+ logger.error("解析json Response对象错误,json:[{}]", json);
+ e.printStackTrace();
+ }
+ assertNotNull(response);
+ return response;
+ }
+
+ /**
+ * 根据json 信息反序列化成Response对象
+ *
+ * @param result MvcResult
+ * @param 泛型
+ * @return Response对象
+ */
+ protected Response getResponse(MvcResult result, TypeReference> responseType) {
+ try {
+ return getResponse(result.getResponse().getContentAsString(), responseType);
+ } catch (UnsupportedEncodingException e) {
+ logger.error("解析json Response对象错误,result:[{}]", result);
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+
+ /**
+ * 修改 mailService 的实现类
+ *
+ * @param service service 类
+ * @param mailFiledName service 中自动注入的mailService字段名
+ */
+ protected void mockEmailServiceInstance(Object service, String mailFiledName) {
+ Field mailServiceField;
+ try {
+ mailServiceField = service.getClass().getDeclaredField(mailFiledName);
+ mailServiceField.setAccessible(true);
+ mailServiceField.set(service, new TestMailServiceImpl());
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ @Slf4j
+ protected static class TestMailServiceImpl implements MailService {
+
+ @Override
+ public Boolean AsyncSend(SimpleMailMessage message) {
+ log.debug("异步邮件请求,SimpleMailMessage:[{}]", getJson(message));
+ return true;
+ }
+
+ @Override
+ public Boolean send(SimpleMailMessage message) {
+ log.debug("邮件请求,SimpleMailMessage:[{}]", getJson(message));
+ return true;
+ }
+
+ /**
+ * 转json
+ *
+ * @param o
+ * @return
+ */
+ private String getJson(Object o) {
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ return mapper.writeValueAsString(o);
+ } catch (JsonProcessingException e) {
+ return null;
+ }
+ }
+ }
+
}
diff --git a/src/test/java/cn/celess/blog/controller/LinksControllerTest.java b/src/test/java/cn/celess/blog/controller/LinksControllerTest.java
index b96c49b..5dcbb05 100644
--- a/src/test/java/cn/celess/blog/controller/LinksControllerTest.java
+++ b/src/test/java/cn/celess/blog/controller/LinksControllerTest.java
@@ -3,31 +3,43 @@ package cn.celess.blog.controller;
import cn.celess.blog.BaseTest;
import cn.celess.blog.entity.PartnerSite;
import cn.celess.blog.entity.model.PageData;
+import cn.celess.blog.entity.request.LinkApplyReq;
import cn.celess.blog.entity.request.LinkReq;
+import cn.celess.blog.exception.MyException;
import cn.celess.blog.mapper.PartnerMapper;
-import com.github.pagehelper.PageInfo;
+import cn.celess.blog.service.MailService;
+import cn.celess.blog.service.PartnerSiteService;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
+import org.springframework.mail.SimpleMailMessage;
+import java.lang.reflect.Field;
import java.util.UUID;
import static cn.celess.blog.enmu.ResponseEnum.*;
import static org.junit.Assert.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+@Slf4j
public class LinksControllerTest extends BaseTest {
@Autowired
PartnerMapper mapper;
+ @Autowired
+ PartnerSiteService partnerSiteService;
+
@Test
public void create() throws Exception {
LinkReq linkReq = new LinkReq();
linkReq.setName(UUID.randomUUID().toString().substring(0, 4));
linkReq.setOpen(false);
- linkReq.setUrl("https://example.com");
+ linkReq.setUrl("https://" + randomStr(4) + "celess.cn");
String token = adminLogin();
mockMvc.perform(
post("/admin/links/create")
@@ -47,7 +59,8 @@ public class LinksControllerTest extends BaseTest {
// https/http
linkReq.setName(UUID.randomUUID().toString().substring(0, 4));
linkReq.setOpen(false);
- linkReq.setUrl("example.com");
+ String url = randomStr(4) + ".celess.cn";
+ linkReq.setUrl(url);
mockMvc.perform(
post("/admin/links/create")
.content(JSONObject.fromObject(linkReq).toString())
@@ -57,7 +70,7 @@ public class LinksControllerTest extends BaseTest {
JSONObject object = JSONObject.fromObject(result.getResponse().getContentAsString());
assertEquals(SUCCESS.getCode(), object.getInt(Code));
PartnerSite site = (PartnerSite) JSONObject.toBean(object.getJSONObject(Result), PartnerSite.class);
- assertEquals("http://example.com", site.getUrl());
+ assertEquals("http://" + url, site.getUrl());
});
// 测试已存在的数据
@@ -76,7 +89,7 @@ public class LinksControllerTest extends BaseTest {
partnerSite.setOpen(true);
partnerSite.setDesc("");
partnerSite.setIconPath("");
- partnerSite.setUrl("https://www.celess.cn");
+ partnerSite.setUrl("https://" + randomStr(4) + ".celess.cn");
mapper.insert(partnerSite);
PartnerSite lastest = mapper.getLastest();
assertNotNull(lastest.getId());
@@ -105,7 +118,7 @@ public class LinksControllerTest extends BaseTest {
partnerSite.setDesc("");
partnerSite.setIconPath("");
partnerSite.setDelete(false);
- partnerSite.setUrl("https://www.celess.cn");
+ partnerSite.setUrl("https://" + randomStr(4) + ".celess.cn");
mapper.insert(partnerSite);
// 查数据
PartnerSite lastest = mapper.getLastest();
@@ -166,18 +179,83 @@ public class LinksControllerTest extends BaseTest {
}
// 手动测试
- // @Test
- public void apply() throws Exception {
- long l = System.currentTimeMillis();
- String url = "https://www.example.com";
- mockMvc.perform(post("/apply?name=小海博客Api测试,请忽略&url=" + url)).andDo(result -> {
- assertEquals(SUCCESS.getCode(), JSONObject.fromObject(result.getResponse().getContentAsString()).getInt(Code));
- });
- System.out.println("耗时:" + (System.currentTimeMillis() - l) / 1000 + "s");
- url = "xxxxxxxxxm";
- mockMvc.perform(post("/apply?name=小海博客Api测试,请忽略&url=" + url)).andDo(result -> {
- assertEquals(PARAMETERS_URL_ERROR.getCode(), JSONObject.fromObject(result.getResponse().getContentAsString()).getInt(Code));
- });
+ @Test
+ public void apply() {
+ // 做service 层的测试
+ mockEmailServiceInstance(partnerSiteService, "mailService");
+ LinkApplyReq req = new LinkApplyReq();
+ req.setName(randomStr(4));
+ req.setUrl("https://" + randomStr(4) + ".celess.cn");
+ req.setIconPath("https://www.celess.cn/example.png");
+ req.setDesc("desc :" + randomStr());
+ req.setEmail(randomStr(4) + "@celess.cn");
+ req.setLinkUrl(req.getUrl() + "/links");
+ try {
+ // 抓取不到数据的链接
+ partnerSiteService.apply(req);
+ } catch (MyException e) {
+ log.debug("测试抓取不到数据");
+ assertEquals(CANNOT_GET_DATA.getCode(), e.getCode());
+ }
+
+ req.setLinkUrl("https://bing.com");
+ req.setUrl(req.getLinkUrl());
+ try {
+ partnerSiteService.apply(req);
+ } catch (MyException e) {
+ log.debug("测试未添加本站链接的友链申请");
+ assertEquals(APPLY_LINK_NO_ADD_THIS_SITE.getCode(), e.getCode());
+ assertNotNull(e.getResult());
+ try {
+ // 测试uuid一致性
+ log.debug("测试uuid一致性");
+ partnerSiteService.apply(req);
+ } catch (MyException e2) {
+ assertEquals(e.getResult(), e2.getResult());
+ }
+ }
+ log.debug("测试正常申请");
+ req.setLinkUrl("https://www.celess.cn");
+ req.setUrl(req.getLinkUrl());
+ PartnerSite apply = partnerSiteService.apply(req);
+ assertNotNull(apply);
+ assertNotNull(apply.getId());
+ }
+
+ @Test
+ public void reapply() {
+ mockEmailServiceInstance(partnerSiteService, "mailService");
+ try {
+ partnerSiteService.reapply(randomStr());
+ throw new AssertionError();
+ } catch (MyException e) {
+ assertEquals(DATA_EXPIRED.getCode(), e.getCode());
+ }
+
+ LinkApplyReq req = new LinkApplyReq();
+ req.setName(randomStr(4));
+ req.setIconPath("https://www.celess.cn/example.png");
+ req.setDesc("desc :" + randomStr());
+ req.setEmail(randomStr(4) + "@celess.cn");
+ req.setLinkUrl("https://bing.com");
+ req.setUrl(req.getLinkUrl());
+ String uuid = null;
+ try {
+ partnerSiteService.apply(req);
+ // err here
+ throw new AssertionError();
+ } catch (MyException e) {
+ uuid = (String) e.getResult();
+ String reapply = partnerSiteService.reapply(uuid);
+ assertEquals(reapply, "success");
+ }
+
+ try {
+ partnerSiteService.reapply(uuid);
+ throw new AssertionError();
+ } catch (MyException e) {
+ assertEquals(DATA_EXPIRED.getCode(), e.getCode());
+ }
}
}
\ No newline at end of file
diff --git a/src/test/java/cn/celess/blog/mapper/PartnerMapperTest.java b/src/test/java/cn/celess/blog/mapper/PartnerMapperTest.java
index 478cd22..aed93aa 100644
--- a/src/test/java/cn/celess/blog/mapper/PartnerMapperTest.java
+++ b/src/test/java/cn/celess/blog/mapper/PartnerMapperTest.java
@@ -35,7 +35,7 @@ public class PartnerMapperTest extends BaseTest {
partnerSite.setIconPath(randomStr(5));
partnerSite.setDesc(randomStr(5));
partnerSite.setOpen(false);
- partnerSite.setUrl("www.celess.cn?random=" + randomStr(4));
+ partnerSite.setUrl("www.celess.cn/?random=" + randomStr(4));
assertEquals(1, partnerMapper.update(partnerSite));
}
diff --git a/src/test/java/cn/celess/blog/util/HttpUtilTest.java b/src/test/java/cn/celess/blog/util/HttpUtilTest.java
new file mode 100644
index 0000000..9743d69
--- /dev/null
+++ b/src/test/java/cn/celess/blog/util/HttpUtilTest.java
@@ -0,0 +1,22 @@
+package cn.celess.blog.util;
+
+import cn.celess.blog.BaseTest;
+import cn.celess.blog.enmu.ResponseEnum;
+import cn.celess.blog.entity.Response;
+import org.junit.Test;
+
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+public class HttpUtilTest extends BaseTest {
+
+ @Test
+ public void get() {
+ String s = HttpUtil.get("https://api.celess.cn/headerInfo");
+ assertNotNull(s);
+ Response