Compare commits

..

19 Commits

Author SHA1 Message Date
禾几海
7ac3d69da4 单元测试 2020-08-01 12:21:25 +08:00
禾几海
657a200d81 ... 2020-08-01 12:21:03 +08:00
禾几海
85c3541445 修改emailService的bean 2020-08-01 12:20:44 +08:00
禾几海
c6877c2b4a 添加unique约束 2020-08-01 12:19:55 +08:00
禾几海
9e98134003 空值异常 2020-08-01 09:23:48 +08:00
禾几海
7a81d8e4ce 友链申请通过通知,数据防重 2020-08-01 01:41:17 +08:00
禾几海
1b52e27b72 reapply接口 2020-08-01 01:13:15 +08:00
禾几海
cd9d9ff0e6 ... 2020-08-01 01:00:47 +08:00
禾几海
dcf44cefb6 调整,非成功响应情况下返回数据 2020-08-01 01:00:07 +08:00
禾几海
d83e4de9a3 ... 2020-07-31 23:26:30 +08:00
禾几海
9c949576aa 抓取网页信息,进行数据处理 2020-07-31 23:18:05 +08:00
禾几海
85b24891be 使用htmlunit获取js渲染后的数据 2020-07-31 23:16:56 +08:00
禾几海
da95470993 修改异常 2020-07-31 21:49:05 +08:00
禾几海
3b368c92cb 修改数据库字段 2020-07-31 21:19:48 +08:00
禾几海
ad5271f740 添加请求实体,修改请求 2020-07-31 21:19:33 +08:00
禾几海
d2cf640133 调整 2020-07-31 21:19:10 +08:00
禾几海
4a2abc47cc 修改HttpUtil 2020-07-31 21:17:35 +08:00
禾几海
6b29cd39d4 修改getResponse的类型参数 2020-07-31 20:34:00 +08:00
禾几海
69da168fc1 抽离json -> Response 对象的方法 2020-07-31 20:28:37 +08:00
18 changed files with 549 additions and 110 deletions

View File

@@ -75,10 +75,12 @@ 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_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 '该数据是否被删除'
`is_delete` boolean not null default false comment '该数据是否被删除',
`l_email` varchar(255) comment '网站管理员的邮箱',
`l_notification` boolean default false comment '是否通知了'
) comment '友站表';
CREATE TABLE `visitor`

37
pom.xml
View File

@@ -148,6 +148,29 @@
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- OkHttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.8.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.3.72</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.42.0</version>
</dependency>
</dependencies>
<build>
@@ -176,6 +199,20 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>1.3.72</version>
<executions>
<execution>
<id>compile</id>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

View File

@@ -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);
}
JSONArray jsonArray = imageObj.getJSONArray("images");
String imageName = jsonArray.getJSONObject(0).getString("url");
return Response.success("https://cn.bing.com" + imageName);

View File

@@ -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);
public Response apply(@RequestBody() LinkApplyReq linkApplyReq) {
return Response.success(partnerSiteService.apply(linkApplyReq));
}
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("");
@PostMapping("/reapply")
public Response reapply(@RequestParam("key") String key) {
return Response.success(partnerSiteService.reapply(key));
}
}

View File

@@ -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, "非法访问"),

View File

@@ -25,6 +25,10 @@ public class PartnerSite {
private Boolean delete = false;
private String email;
private Boolean notification = true;
public PartnerSite() {
}

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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;
}
}

View File

@@ -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<PartnerSite> findAll();
/**
* 申请友链
*
* @param linkApplyReq linkApplyReq
* @return linkApplyReq
*/
PartnerSite apply(LinkApplyReq linkApplyReq);
/**
* 重写申请友链
*
* @param key key
* @return msg
*/
String reapply(String key);
}

View File

@@ -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";
}
}

View File

@@ -88,7 +88,6 @@ 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");
@@ -98,9 +97,6 @@ public class WebUpdateInfoServiceImpl implements WebUpdateInfoService {
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());
}
return jsonObject;
}

View File

@@ -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;
}
}
}

View File

@@ -9,20 +9,26 @@
<result column="l_icon_path" property="iconPath"/>
<result column="l_desc" property="desc"/>
<result column="is_delete" property="delete"/>
<result column="l_email" property="email"/>
<result column="l_notification" property="notification"/>
</resultMap>
<insert id="insert" parameterType="cn.celess.blog.entity.PartnerSite" useGeneratedKeys="true" keyProperty="id">
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)
</insert>
<update id="update" parameterType="cn.celess.blog.entity.PartnerSite">
update links set
update links
<trim prefix="set" suffixOverrides=",">
<if test="open!=null">l_is_open=#{open},</if>
<if test="iconPath!=null">l_icon_path=#{iconPath},</if>
<if test="desc!=null">l_desc=#{desc},</if>
<if test="url!=null">l_url=#{url},</if>
<if test="name!=null">l_name=#{name}</if>
<if test="name!=null">l_name=#{name},</if>
<if test="notification!=null">l_notification=#{notification},</if>
<if test="email!=null">l_email=#{email}</if>
</trim>
where l_id=#{id}
</update>

View File

@@ -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<Response<Boolean>>() {
};
protected static final TypeReference<?> STRING_TYPE = new TypeReference<Response<String>>() {
};
protected static final TypeReference<?> OBJECT_TYPE = new TypeReference<Response<Object>>() {
};
protected static final TypeReference<?> MAP_OBJECT_TYPE = new TypeReference<Response<Map<String, Object>>>() {
};
@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 <T> Response<T> getResponse(String json) {
return getResponse(json, OBJECT_TYPE);
}
protected <T> Response<T> getResponse(MvcResult result) {
return getResponse(result, OBJECT_TYPE);
}
/**
* 根据json 信息反序列化成Response对象
*
* @param json json
* @param <T> 泛型
* @return Response对象
*/
protected <T> Response<T> getResponse(String json, TypeReference<?> responseType) {
Response<T> 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 <T> 泛型
* @return Response对象
*/
protected <T> Response<T> 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;
}
}
}
}

View File

@@ -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());
}
}
}

View File

@@ -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));
}

View File

@@ -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<Map<String, Object>> response = getResponse(s, MAP_OBJECT_TYPE);
assertEquals(ResponseEnum.SUCCESS.getCode(), response.getCode());
assertNotEquals(0, response.getResult().size());
}
}