切换到jackson #10

Merged
xiaohai2271 merged 33 commits from feature-trans2jackson into dev 2020-08-15 16:05:40 +08:00
42 changed files with 5950 additions and 1145 deletions
Showing only changes of commit 7ff44fd73e - Show all commits

26
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created
# For more information see: https://github.com/actions/setup-java#apache-maven-with-a-settings-path
name: Build
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
env:
KEY: ${{ secrets.WEB_HOOK_ACCESS_KEY }}
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Deploy
run: mvn -B test --file pom.xml && curl http://106.15.205.190:2271/hook?access_key=$KEY

View File

@@ -1,47 +0,0 @@
# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created
# For more information see: https://github.com/actions/setup-java#apache-maven-with-a-settings-path
name: Deplay
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
env:
APPLICATION_PROPERTIES_TEST: ${{ secrets.APPLICATION_PROPERTIES_TEST }}
APPLICATION_PROPERTIES_PROD: ${{ secrets.APPLICATION_PROPERTIES_PROD }}
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build jar file
run: echo $APPLICATION_PROPERTIES_PROD|base64 -d> src/main/resources/application-prod.properties && mvn -B package --file pom.xml
- name: SCP
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
password: ${{ secrets.SSH_PASSWORD }}
port: ${{ secrets.SSH_PORT }}
source: "target/blog-0.0.1-SNAPSHOT.jar"
target: "/www/wwwroot/api.celess.cn"
- name: Run SSH command
uses: garygrossgarten/github-action-ssh@v0.5.0
with:
command: cd /www/wwwroot/api.celess.cn && bash build.sh
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
password: ${{ secrets.SSH_PASSWORD }}
port: ${{ secrets.SSH_PORT }}

View File

@@ -1,7 +1,7 @@
# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created # This workflow will build a package using Maven and then publish it to GitHub packages when a release is created
# For more information see: https://github.com/actions/setup-java#apache-maven-with-a-settings-path # For more information see: https://github.com/actions/setup-java#apache-maven-with-a-settings-path
name: pr Test name: Test
on: on:
push: push:
@@ -12,18 +12,18 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: # env:
APPLICATION_PROPERTIES_TEST: ${{ secrets.APPLICATION_PROPERTIES_TEST }} # APPLICATION_PROPERTIES_TEST: ${{ secrets.APPLICATION_PROPERTIES_TEST }}
APPLICATION_PROPERTIES_PROD: ${{ secrets.APPLICATION_PROPERTIES_PROD }} # APPLICATION_PROPERTIES_PROD: ${{ secrets.APPLICATION_PROPERTIES_PROD }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Set up JDK 1.8 - name: Set up JDK 1.8
uses: actions/setup-java@v1 uses: actions/setup-java@v1
with: with:
java-version: 1.8 java-version: 1.8
- name: Test - name: Test
run: echo $APPLICATION_PROPERTIES_TEST|base64 -d > src/main/resources/application-test.properties && mvn -B test --file pom.xml run: mvn -B test --file pom.xml

2
.gitignore vendored
View File

@@ -4,7 +4,5 @@
target/ target/
# 本地项目的私有文件 # 本地项目的私有文件
back-end/blog-dev.sql
src/main/resources/application-dev.properties src/main/resources/application-dev.properties
src/main/resources/application-prod.properties src/main/resources/application-prod.properties
src/main/resources/application-test.properties

View File

@@ -1,11 +1,11 @@
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2007-present the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* https://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import java.net.*; import java.net.*;
import java.io.*; import java.io.*;
import java.nio.channels.*; import java.nio.channels.*;
@@ -21,12 +20,12 @@ import java.util.Properties;
public class MavenWrapperDownloader { public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.5"; private static final String WRAPPER_VERSION = "0.5.6";
/** /**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/ */
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/** /**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
@@ -55,7 +54,7 @@ public class MavenWrapperDownloader {
// wrapperUrl parameter. // wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL; String url = DEFAULT_DOWNLOAD_URL;
if (mavenWrapperPropertyFile.exists()) { if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null; FileInputStream mavenWrapperPropertyFileInputStream = null;
try { try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
@@ -66,7 +65,7 @@ public class MavenWrapperDownloader {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally { } finally {
try { try {
if (mavenWrapperPropertyFileInputStream != null) { if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close(); mavenWrapperPropertyFileInputStream.close();
} }
} catch (IOException e) { } catch (IOException e) {
@@ -77,8 +76,8 @@ public class MavenWrapperDownloader {
System.out.println("- Downloading from: " + url); System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if (!outputFile.getParentFile().exists()) { if(!outputFile.getParentFile().exists()) {
if (!outputFile.getParentFile().mkdirs()) { if(!outputFile.getParentFile().mkdirs()) {
System.out.println( System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
} }

Binary file not shown.

View File

@@ -1,2 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.2/apache-maven-3.6.2-bin.zip distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

View File

@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2019 小 Copyright (c) 2020 禾几
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,11 +1,19 @@
# 小海博客后端管理系统 <h1 align="center">
![Build Staus](https://github.com/xiaohai2271/blog-backEnd/workflows/Blog%20backEnd%20CI/badge.svg?branch=master&event=push) ![coverage report](https://gitlab.com/xiaohai2271/blog-backEnd/badges/master/coverage.svg) ![GitHub](https://img.shields.io/github/license/xiaohai2271/blog-backEnd) [![Website](https://img.shields.io/website?up_message=%E5%B0%8F%E6%B5%B7%E5%8D%9A%E5%AE%A2&url=https%3A%2F%2Fwww.celess.cn)](https://www.celess.cn) 小海博客后端管理系统
## 基于Springboot的后端博客管理系统 </h1>
<div align="center">
基于Springboot的后端博客管理系统
[![Build](https://github.com/xiaohai2271/blog-backEnd/workflows/Build/badge.svg)](https://github.com/xiaohai2271/blog-backEnd)
[![Test](https://github.com/xiaohai2271/blog-backEnd/workflows/Test/badge.svg)](https://github.com/xiaohai2271/blog-backEnd)
[![GitHub](https://img.shields.io/github/license/xiaohai2271/blog-backEnd)](https://github.com/xiaohai2271/blog-backEnd)
[![Website](https://img.shields.io/website?up_message=%E5%B0%8F%E6%B5%B7%E5%8D%9A%E5%AE%A2&url=https%3A%2F%2Fwww.celess.cn)](https://www.celess.cn)
### 主要使用的技术 </div>
## 🎈主要使用的技术
| 使用的技术 | 名称 | 版本 | | 使用的技术 | 名称 | 版本 |
| :--------------: | :--------: | :-----------: | | :--------------: | :--------: | :-----------: |
@@ -18,18 +26,16 @@
| 接口文档 | Swagger | 2.6.1 | | 接口文档 | Swagger | 2.6.1 |
| 数据库连接池 | druid | 1.1.14 | | 数据库连接池 | druid | 1.1.14 |
| 缓存(线上环境) | redis | 3.0.6 | | 缓存(线上环境) | redis | 3.0.6 |
|数据库|mysql|5.7| | 数据库 |mysql |5.7 |
### 接口文档 ## 🔨如何构建
详情参照[Build](./doc/Build.md)文档
项目采用swagger2接口文档自动生成具体为 http://ip:端口/swagger-ui.html
### 📝TODO ## 📒接口文档
项目采用swagger2接口文档自动生成具体为 http://ip:port/doc.html
- [x] 密码重置 或者参照[离线API文档](./doc/API.md)
- [x] 信息修改
- [ ] 接入qq登录
### 📌FIXME ## ☀授权协议
[MIT](./LICENSE)
- [ ] `/write` 图片上传的跨域问题

4077
doc/API.md Normal file

File diff suppressed because it is too large Load Diff

32
doc/Build.md Normal file
View File

@@ -0,0 +1,32 @@
# 如何构建
### 1. 构建前准备
- 安装jdk
- 安装maven(也可使使用项目中的maven wrapper)
- 安装mysql
- 安装redis
- 获取七牛云的AccessKey/SecretKey (个人中心-密钥管理) [七牛云官网](https://www.qiniu.com/)
### 2. 拉取项目到本地
``` shell script
git clone https://github.com/xiaohai2271/blog-backEnd.git
或 git clone git@github.com:xiaohai2271/blog-backEnd.git
```
### 3. maven构建
```shell script
mvn package
```
### 4. 运行
```shell script
java -jar target/blog-0.0.1-SNAPSHOT.jar
```
### 5. 其他命令
```shell script
mvn clean # 清理项目资源
mvn clean package # 清理项目资源并重新打包
mvn clean package -DskipTest # 清理项目资源,重新打包并跳过测试
mvn test # 运行测试
..... #待添加
```

256
mvnw vendored
View File

@@ -8,7 +8,7 @@
# "License"); you may not use this file except in compliance # "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at # with the License. You may obtain a copy of the License at
# #
# https://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, # Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an # software distributed under the License is distributed on an
@@ -19,7 +19,7 @@
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# Maven2 Start Up Batch script # Maven Start Up Batch script
# #
# Required ENV vars: # Required ENV vars:
# ------------------ # ------------------
@@ -34,135 +34,128 @@
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ]; then if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ]; then if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc . /etc/mavenrc
fi fi
if [ -f "$HOME/.mavenrc" ]; then if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc" . "$HOME/.mavenrc"
fi fi
fi fi
# OS specific support. $var _must_ be set to either true or false. # OS specific support. $var _must_ be set to either true or false.
cygwin=false cygwin=false;
darwin=false darwin=false;
mingw=false mingw=false
case "$(uname)" in case "`uname`" in
CYGWIN*) cygwin=true ;; CYGWIN*) cygwin=true ;;
MINGW*) mingw=true ;; MINGW*) mingw=true;;
Darwin*) Darwin*) darwin=true
darwin=true # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html if [ -z "$JAVA_HOME" ]; then
if [ -z "$JAVA_HOME" ]; then if [ -x "/usr/libexec/java_home" ]; then
if [ -x "/usr/libexec/java_home" ]; then export JAVA_HOME="`/usr/libexec/java_home`"
export JAVA_HOME="$(/usr/libexec/java_home)" else
else export JAVA_HOME="/Library/Java/Home"
export JAVA_HOME="/Library/Java/Home" fi
fi fi
fi ;;
;;
esac esac
if [ -z "$JAVA_HOME" ]; then if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ]; then if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=$(java-config --jre-home) JAVA_HOME=`java-config --jre-home`
fi fi
fi fi
if [ -z "$M2_HOME" ]; then if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home ## resolve links - $0 may be a link to maven's home
PRG="$0" PRG="$0"
# need this for relative symlinks # need this for relative symlinks
while [ -h "$PRG" ]; do while [ -h "$PRG" ] ; do
ls=$(ls -ld "$PRG") ls=`ls -ld "$PRG"`
link=$(expr "$ls" : '.*-> \(.*\)$') link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' >/dev/null; then if expr "$link" : '/.*' > /dev/null; then
PRG="$link" PRG="$link"
else else
PRG="$(dirname "$PRG")/$link" PRG="`dirname "$PRG"`/$link"
fi fi
done done
saveddir=$(pwd) saveddir=`pwd`
M2_HOME=$(dirname "$PRG")/.. M2_HOME=`dirname "$PRG"`/..
# make it fully qualified # make it fully qualified
M2_HOME=$(cd "$M2_HOME" && pwd) M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir" cd "$saveddir"
# echo Using m2 at $M2_HOME # echo Using m2 at $M2_HOME
fi fi
# For Cygwin, ensure paths are in UNIX format before anything is touched # For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin; then if $cygwin ; then
[ -n "$M2_HOME" ] && [ -n "$M2_HOME" ] &&
M2_HOME=$(cygpath --unix "$M2_HOME") M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] && [ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME") JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] && [ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH") CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi fi
# For Mingw, ensure paths are in UNIX format before anything is touched # For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw; then if $mingw ; then
[ -n "$M2_HOME" ] && [ -n "$M2_HOME" ] &&
M2_HOME="$( ( M2_HOME="`(cd "$M2_HOME"; pwd)`"
cd "$M2_HOME"
pwd
))"
[ -n "$JAVA_HOME" ] && [ -n "$JAVA_HOME" ] &&
JAVA_HOME="$( ( JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
cd "$JAVA_HOME"
pwd
))"
fi fi
if [ -z "$JAVA_HOME" ]; then if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)" javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "$(expr \"$javaExecutable\" : '\([^ ]*\)')" = "no" ]; then if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10. # readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink) readLink=`which readlink`
if [ ! $(expr "$readLink" : '\([^ ]*\)') = "no" ]; then if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin; then if $darwin ; then
javaHome="$(dirname \"$javaExecutable\")" javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="$(cd \"$javaHome\" && pwd -P)/javac" javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else else
javaExecutable="$(readlink -f \"$javaExecutable\")" javaExecutable="`readlink -f \"$javaExecutable\"`"
fi fi
javaHome="$(dirname \"$javaExecutable\")" javaHome="`dirname \"$javaExecutable\"`"
javaHome=$(expr "$javaHome" : '\(.*\)/bin') javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome" JAVA_HOME="$javaHome"
export JAVA_HOME export JAVA_HOME
fi fi
fi fi
fi fi
if [ -z "$JAVACMD" ]; then if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ]; then if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables # IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java" JAVACMD="$JAVA_HOME/jre/sh/java"
else else
JAVACMD="$JAVA_HOME/bin/java" JAVACMD="$JAVA_HOME/bin/java"
fi fi
else else
JAVACMD="$(which java)" JAVACMD="`which java`"
fi fi
fi fi
if [ ! -x "$JAVACMD" ]; then if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2 echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2 echo " We cannot execute $JAVACMD" >&2
exit 1 exit 1
fi fi
if [ -z "$JAVA_HOME" ]; then if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set." echo "Warning: JAVA_HOME environment variable is not set."
fi fi
@@ -172,24 +165,22 @@ CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# first directory with .mvn subdirectory is considered project base directory # first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() { find_maven_basedir() {
if [ -z "$1" ]; then if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir" echo "Path not specified to find_maven_basedir"
return 1 return 1
fi fi
basedir="$1" basedir="$1"
wdir="$1" wdir="$1"
while [ "$wdir" != '/' ]; do while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ]; then if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir basedir=$wdir
break break
fi fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc) # workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then if [ -d "${wdir}" ]; then
wdir=$( wdir=`cd "$wdir/.."; pwd`
cd "$wdir/.."
pwd
)
fi fi
# end of workaround # end of workaround
done done
@@ -199,13 +190,13 @@ find_maven_basedir() {
# concatenates all lines of a file # concatenates all lines of a file
concat_lines() { concat_lines() {
if [ -f "$1" ]; then if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' <"$1")" echo "$(tr -s '\n' ' ' < "$1")"
fi fi
} }
BASE_DIR=$(find_maven_basedir "$(pwd)") BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then if [ -z "$BASE_DIR" ]; then
exit 1 exit 1;
fi fi
########################################################################################## ##########################################################################################
@@ -213,78 +204,75 @@ fi
# This allows using the maven wrapper in projects that prohibit checking in binary data. # This allows using the maven wrapper in projects that prohibit checking in binary data.
########################################################################################## ##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar" echo "Found .mvn/wrapper/maven-wrapper.jar"
fi fi
else else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
fi
while IFS="=" read key value; do
case "$key" in wrapperUrl)
jarUrl="$value"
break
;;
esac
done <"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget >/dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget" echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then if [ -n "$MVNW_REPOURL" ]; then
wget "$jarUrl" -O "$wrapperJarPath" jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi fi
elif command -v curl >/dev/null; then while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl" echo "Downloading from: $jarUrl"
fi fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then if $cygwin; then
javaClass=$(cygpath --path --windows "$javaClass") wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..." echo "Found wget ... using wget"
fi fi
# Compiling the Java class if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
("$JAVA_HOME/bin/javac" "$javaClass") wget "$jarUrl" -O "$wrapperJarPath"
fi else
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
# Running the downloader fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..." echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi fi
fi
fi fi
########################################################################################## ##########################################################################################
# End of extension # End of extension
@@ -299,13 +287,13 @@ MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java # For Cygwin, switch paths to Windows format before running java
if $cygwin; then if $cygwin; then
[ -n "$M2_HOME" ] && [ -n "$M2_HOME" ] &&
M2_HOME=$(cygpath --path --windows "$M2_HOME") M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] && [ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] && [ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH") CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] && [ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi fi
# Provide a "standardized" way to retrieve the CLI args that will # Provide a "standardized" way to retrieve the CLI args that will

10
mvnw.cmd vendored
View File

@@ -7,7 +7,7 @@
@REM "License"); you may not use this file except in compliance @REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at @REM with the License. You may obtain a copy of the License at
@REM @REM
@REM https://www.apache.org/licenses/LICENSE-2.0 @REM http://www.apache.org/licenses/LICENSE-2.0
@REM @REM
@REM Unless required by applicable law or agreed to in writing, @REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an @REM software distributed under the License is distributed on an
@@ -18,7 +18,7 @@
@REM ---------------------------------------------------------------------------- @REM ----------------------------------------------------------------------------
@REM ---------------------------------------------------------------------------- @REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script @REM Maven Start Up Batch script
@REM @REM
@REM Required ENV vars: @REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir @REM JAVA_HOME - location of a JDK home dir
@@ -26,7 +26,7 @@
@REM Optional ENV vars @REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir @REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use @REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@@ -120,7 +120,7 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
@@ -134,7 +134,7 @@ if exist %WRAPPER_JAR% (
) )
) else ( ) else (
if not "%MVNW_REPOURL%" == "" ( if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
) )
if "%MVNW_VERBOSE%" == "true" ( if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ... echo Couldn't find %WRAPPER_JAR%, downloading it ...

53
pom.xml
View File

@@ -148,6 +148,41 @@
<artifactId>jjwt</artifactId> <artifactId>jjwt</artifactId>
<version>0.9.1</version> <version>0.9.1</version>
</dependency> </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>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
<dependency>
<groupId>com.github.kstyrc</groupId>
<artifactId>embedded-redis</artifactId>
<version>0.6</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
@@ -157,21 +192,15 @@
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jetbrains.kotlin</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>kotlin-maven-plugin</artifactId>
<version>0.7.9</version> <version>1.3.72</version>
<executions> <executions>
<execution> <execution>
<id>pre-unit-test</id> <id>compile</id>
<phase>process-sources</phase>
<goals> <goals>
<goal>prepare-agent</goal> <goal>compile</goal>
</goals>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>

View File

@@ -26,7 +26,7 @@ public class CorsConfig {
config.addAllowedOrigin("https://celess.cn"); config.addAllowedOrigin("https://celess.cn");
config.addAllowedOrigin("https://www.celess.cn"); config.addAllowedOrigin("https://www.celess.cn");
// 本地调试时的跨域 // 本地调试时的跨域
if ("dev".equals(activeModel)) { if (!"prod".equals(activeModel)) {
config.addAllowedOrigin("http://localhost:4200"); config.addAllowedOrigin("http://localhost:4200");
config.addAllowedOrigin("http://127.0.0.1:4200"); config.addAllowedOrigin("http://127.0.0.1:4200");
} }

View File

@@ -26,7 +26,7 @@ public class DruidConfig {
@Bean @Bean
public DruidDataSource druidDataSource() { public DruidDataSource druidDataSource() {
DruidDataSource dataSource = new DruidDataSource(); DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setDriverClassName(driverClassName);
// 数据库基本信息 // 数据库基本信息
dataSource.setUrl(dbUrl); dataSource.setUrl(dbUrl);
dataSource.setUsername(username); dataSource.setUsername(username);

View File

@@ -26,7 +26,7 @@ public class SwaggerConfig {
@Bean @Bean
public Docket createRestApi() { public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2) return new Docket(DocumentationType.SWAGGER_2)
.enable("dev".equals(environment)) .enable(!"prod".equals(environment))
.apiInfo(apiInfo()) .apiInfo(apiInfo())
.select() .select()
.apis(RequestHandlerSelectors.basePackage("cn.celess.blog")) .apis(RequestHandlerSelectors.basePackage("cn.celess.blog"))

View File

@@ -56,10 +56,13 @@ public class AuthenticationFilter implements HandlerInterceptor {
return writeResponse(ResponseEnum.LOGIN_EXPIRED, response, request); return writeResponse(ResponseEnum.LOGIN_EXPIRED, response, request);
} }
String email = jwtUtil.getUsernameFromToken(jwtStr); String email = jwtUtil.getUsernameFromToken(jwtStr);
if (!redisUtil.hasKey(email + "-login") || jwtUtil.isTokenExpired(jwtStr)) { if (jwtUtil.isTokenExpired(jwtStr)) {
// 登陆过期 // 登陆过期
return writeResponse(ResponseEnum.LOGIN_EXPIRED, response, request); return writeResponse(ResponseEnum.LOGIN_EXPIRED, response, request);
} }
if (!redisUtil.hasKey(email + "-login")) {
return writeResponse(ResponseEnum.LOGOUT, response, request);
}
String role = userService.getUserRoleByEmail(email); String role = userService.getUserRoleByEmail(email);
if (role.equals(ROLE_USER) || role.equals(ROLE_ADMIN)) { if (role.equals(ROLE_USER) || role.equals(ROLE_ADMIN)) {
// 更新token // 更新token

View File

@@ -135,8 +135,6 @@ public class CommonController {
* FUCK !!! * FUCK !!!
* *
* @param file 文件 * @param file 文件
* @return
* @throws IOException
*/ */
@PostMapping("/imgUpload") @PostMapping("/imgUpload")
public void upload(HttpServletRequest request, HttpServletResponse response, @RequestParam("editormd-image-file") MultipartFile file) throws IOException { public void upload(HttpServletRequest request, HttpServletResponse response, @RequestParam("editormd-image-file") MultipartFile file) throws IOException {
@@ -159,6 +157,7 @@ public class CommonController {
return; return;
} }
String fileName = file.getOriginalFilename(); String fileName = file.getOriginalFilename();
assert fileName != null;
String mime = fileName.substring(fileName.lastIndexOf(".")); String mime = fileName.substring(fileName.lastIndexOf("."));
if (".png".equals(mime.toLowerCase()) || ".jpg".equals(mime.toLowerCase()) || if (".png".equals(mime.toLowerCase()) || ".jpg".equals(mime.toLowerCase()) ||
".jpeg".equals(mime.toLowerCase()) || ".bmp".equals(mime.toLowerCase())) { ".jpeg".equals(mime.toLowerCase()) || ".bmp".equals(mime.toLowerCase())) {

View File

@@ -3,6 +3,7 @@ package cn.celess.blog.controller;
import cn.celess.blog.enmu.ResponseEnum; import cn.celess.blog.enmu.ResponseEnum;
import cn.celess.blog.entity.PartnerSite; import cn.celess.blog.entity.PartnerSite;
import cn.celess.blog.entity.Response; import cn.celess.blog.entity.Response;
import cn.celess.blog.entity.request.LinkApplyReq;
import cn.celess.blog.entity.request.LinkReq; import cn.celess.blog.entity.request.LinkReq;
import cn.celess.blog.exception.MyException; import cn.celess.blog.exception.MyException;
import cn.celess.blog.service.MailService; import cn.celess.blog.service.MailService;
@@ -69,29 +70,12 @@ public class LinksController {
} }
@PostMapping("/apply") @PostMapping("/apply")
public Response apply(@RequestParam("name") String name, public Response apply(@RequestBody() LinkApplyReq linkApplyReq) {
@RequestParam("url") String url) { return Response.success(partnerSiteService.apply(linkApplyReq));
// TODO :: 弃用发送邮件的方式。 }
if (name == null || name.replaceAll(" ", "").isEmpty()) {
return Response.response(ResponseEnum.PARAMETERS_ERROR, null); @PostMapping("/reapply")
} public Response reapply(@RequestParam("key") String key) {
if (!RegexUtil.urlMatch(url)) { return Response.success(partnerSiteService.reapply(key));
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("");
} }
} }

View File

@@ -33,6 +33,7 @@ public enum ResponseEnum {
PWD_SAME(3601, "新密码与原密码相同"), PWD_SAME(3601, "新密码与原密码相同"),
PWD_NOT_SAME(3602, "新密码与原密码不相同"), PWD_NOT_SAME(3602, "新密码与原密码不相同"),
LOGIN_EXPIRED(3700, "登陆过期"), LOGIN_EXPIRED(3700, "登陆过期"),
LOGOUT(3710, "账户已注销"),
PWD_WRONG(3800, "密码不正确"), PWD_WRONG(3800, "密码不正确"),
JWT_EXPIRED(3810, "Token过期"), JWT_EXPIRED(3810, "Token过期"),
@@ -57,6 +58,9 @@ public enum ResponseEnum {
DATA_HAS_EXIST(7020, "数据已存在"), DATA_HAS_EXIST(7020, "数据已存在"),
//其他 //其他
APPLY_LINK_NO_ADD_THIS_SITE(7200, "暂未在您的网站中抓取到本站链接"),
DATA_EXPIRED(7300, "数据过期"),
CANNOT_GET_DATA(7400, "暂无法获取到数据"),
//提交更新之前,没有获取数据/, //提交更新之前,没有获取数据/,
DID_NOT_GET_THE_DATA(8020, "非法访问"), DID_NOT_GET_THE_DATA(8020, "非法访问"),

View File

@@ -25,6 +25,10 @@ public class PartnerSite {
private Boolean delete = false; private Boolean delete = false;
private String email;
private Boolean notification = true;
public PartnerSite() { 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) { public Response handle(Exception e) {
//自定义错误 //自定义错误
if (e instanceof MyException) { if (e instanceof MyException) {
logger.debug("返回了自定义的exception,[code={},msg={}]", ((MyException) e).getCode(), e.getMessage()); MyException exception = (MyException) e;
return new Response(((MyException) e).getCode(), e.getMessage(), null); 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) { if (e instanceof HttpRequestMethodNotSupportedException) {

View File

@@ -1,13 +1,16 @@
package cn.celess.blog.exception; package cn.celess.blog.exception;
import cn.celess.blog.enmu.ResponseEnum; import cn.celess.blog.enmu.ResponseEnum;
import lombok.Data;
/** /**
* @author : xiaohai * @author : xiaohai
* @date : 2019/03/28 16:56 * @date : 2019/03/28 16:56
*/ */
@Data
public class MyException extends RuntimeException { public class MyException extends RuntimeException {
private int code; private int code;
private Object result;
public MyException(int code, String msg) { public MyException(int code, String msg) {
super(msg); super(msg);
@@ -24,11 +27,9 @@ public class MyException extends RuntimeException {
this.code = e.getCode(); this.code = e.getCode();
} }
public int getCode() { public MyException(ResponseEnum e, String msg, Object result) {
return code; super(e.getMsg());
} this.code = e.getCode();
this.result = result;
public void setCode(int code) {
this.code = code;
} }
} }

View File

@@ -2,6 +2,7 @@ package cn.celess.blog.service;
import cn.celess.blog.entity.PartnerSite; import cn.celess.blog.entity.PartnerSite;
import cn.celess.blog.entity.model.PageData; 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.entity.request.LinkReq;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -53,4 +54,19 @@ public interface PartnerSiteService {
*/ */
List<PartnerSite> findAll(); List<PartnerSite> findAll();
/**
* 申请友链
*
* @param linkApplyReq linkApplyReq
* @return linkApplyReq
*/
PartnerSite apply(LinkApplyReq linkApplyReq);
/**
* 重写申请友链
*
* @param key key
* @return msg
*/
String reapply(String key);
} }

View File

@@ -59,7 +59,7 @@ public class CommentServiceImpl implements CommentService {
Comment comment = new Comment(); Comment comment = new Comment();
comment.setFromUser(user); comment.setFromUser(user);
User userTo = new User(); User userTo = new User();
userTo.setId(-1L); userTo.setId(null);
if (reqBody.getToUserId() != -1) { if (reqBody.getToUserId() != -1) {
userTo = userMapper.findById(reqBody.getToUserId()); userTo = userMapper.findById(reqBody.getToUserId());
comment.setToUser(userTo); comment.setToUser(userTo);

View File

@@ -3,18 +3,30 @@ package cn.celess.blog.service.serviceimpl;
import cn.celess.blog.enmu.ResponseEnum; import cn.celess.blog.enmu.ResponseEnum;
import cn.celess.blog.entity.PartnerSite; import cn.celess.blog.entity.PartnerSite;
import cn.celess.blog.entity.model.PageData; 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.entity.request.LinkReq;
import cn.celess.blog.exception.MyException; import cn.celess.blog.exception.MyException;
import cn.celess.blog.mapper.PartnerMapper; import cn.celess.blog.mapper.PartnerMapper;
import cn.celess.blog.service.MailService;
import cn.celess.blog.service.PartnerSiteService; 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 cn.celess.blog.util.RegexUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import lombok.SneakyThrows;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/** /**
* @author : xiaohai * @author : xiaohai
@@ -24,6 +36,13 @@ import java.util.List;
public class PartnerSiteServiceImpl implements PartnerSiteService { public class PartnerSiteServiceImpl implements PartnerSiteService {
@Autowired @Autowired
PartnerMapper partnerMapper; 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 @Override
public PartnerSite create(LinkReq reqBody) { public PartnerSite create(LinkReq reqBody) {
@@ -86,10 +105,21 @@ public class PartnerSiteServiceImpl implements PartnerSiteService {
if (!reqBody.getUrl().contains("http://") && !reqBody.getUrl().contains("https://")) { if (!reqBody.getUrl().contains("http://") && !reqBody.getUrl().contains("https://")) {
reqBody.setUrl("http://" + reqBody.getUrl()); 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.setName(reqBody.getName());
partnerSite.setUrl(reqBody.getUrl()); partnerSite.setUrl(reqBody.getUrl());
partnerSite.setOpen(reqBody.isOpen()); partnerSite.setOpen(reqBody.isOpen());
partnerMapper.update(partnerSite);
return partnerSite; return partnerSite;
} }
@@ -108,5 +138,92 @@ public class PartnerSiteServiceImpl implements PartnerSiteService {
return all; 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

@@ -1,110 +1,111 @@
package cn.celess.blog.service.serviceimpl; package cn.celess.blog.service.serviceimpl;
import cn.celess.blog.enmu.ResponseEnum; import cn.celess.blog.enmu.ResponseEnum;
import cn.celess.blog.entity.WebUpdate; import cn.celess.blog.entity.WebUpdate;
import cn.celess.blog.entity.model.PageData; import cn.celess.blog.entity.model.PageData;
import cn.celess.blog.entity.model.WebUpdateModel; import cn.celess.blog.entity.model.WebUpdateModel;
import cn.celess.blog.exception.MyException; import cn.celess.blog.exception.MyException;
import cn.celess.blog.mapper.WebUpdateInfoMapper; import cn.celess.blog.mapper.WebUpdateInfoMapper;
import cn.celess.blog.service.WebUpdateInfoService; import cn.celess.blog.service.WebUpdateInfoService;
import cn.celess.blog.util.DateFormatUtil; import cn.celess.blog.util.DateFormatUtil;
import cn.celess.blog.util.HttpUtil; import cn.celess.blog.util.HttpUtil;
import cn.celess.blog.util.ModalTrans; import cn.celess.blog.util.ModalTrans;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.io.IOException; import java.io.IOException;
import java.time.Instant; import java.time.Instant;
import java.util.*; import java.util.*;
/** /**
* @author : xiaohai * @author : xiaohai
* @date : 2019/05/12 11:43 * @date : 2019/05/12 11:43
*/ */
@Service @Service
@Slf4j @Slf4j
public class WebUpdateInfoServiceImpl implements WebUpdateInfoService { public class WebUpdateInfoServiceImpl implements WebUpdateInfoService {
@Autowired @Autowired
WebUpdateInfoMapper webUpdateInfoMapper; WebUpdateInfoMapper webUpdateInfoMapper;
@Override @Override
public WebUpdateModel create(String info) { public WebUpdateModel create(String info) {
if (info == null || info.replaceAll(" ", "").isEmpty()) { if (info == null || info.replaceAll(" ", "").isEmpty()) {
throw new MyException(ResponseEnum.PARAMETERS_ERROR); throw new MyException(ResponseEnum.PARAMETERS_ERROR);
} }
WebUpdate webUpdate = new WebUpdate(info); WebUpdate webUpdate = new WebUpdate(info);
if (webUpdateInfoMapper.insert(webUpdate) == 0) { if (webUpdateInfoMapper.insert(webUpdate) == 0) {
throw new MyException(ResponseEnum.FAILURE); throw new MyException(ResponseEnum.FAILURE);
} }
return ModalTrans.webUpdate(webUpdateInfoMapper.findById(webUpdate.getId())); return ModalTrans.webUpdate(webUpdateInfoMapper.findById(webUpdate.getId()));
} }
@Override @Override
public Boolean del(long id) { public Boolean del(long id) {
if (!webUpdateInfoMapper.existsById(id)) { if (!webUpdateInfoMapper.existsById(id)) {
throw new MyException(ResponseEnum.DATA_NOT_EXIST); throw new MyException(ResponseEnum.DATA_NOT_EXIST);
} }
return webUpdateInfoMapper.delete(id) == 1; return webUpdateInfoMapper.delete(id) == 1;
} }
@Override @Override
public WebUpdateModel update(long id, String info) { public WebUpdateModel update(long id, String info) {
WebUpdate webUpdate = webUpdateInfoMapper.findById(id); WebUpdate webUpdate = webUpdateInfoMapper.findById(id);
if (webUpdate == null) { if (webUpdate == null) {
throw new MyException(ResponseEnum.DATA_NOT_EXIST); throw new MyException(ResponseEnum.DATA_NOT_EXIST);
} }
if (info == null || info.replaceAll(" ", "").isEmpty()) { if (info == null || info.replaceAll(" ", "").isEmpty()) {
throw new MyException(ResponseEnum.PARAMETERS_ERROR); throw new MyException(ResponseEnum.PARAMETERS_ERROR);
} }
webUpdate.setUpdateInfo(info); webUpdate.setUpdateInfo(info);
webUpdateInfoMapper.update(id, info); webUpdateInfoMapper.update(id, info);
return ModalTrans.webUpdate(webUpdate); return ModalTrans.webUpdate(webUpdate);
} }
@Override @Override
public PageData<WebUpdateModel> pages(int count, int page) { public PageData<WebUpdateModel> pages(int count, int page) {
PageHelper.startPage(page, count); PageHelper.startPage(page, count);
List<WebUpdate> updateList = webUpdateInfoMapper.findAll(); List<WebUpdate> updateList = webUpdateInfoMapper.findAll();
return new PageData<WebUpdateModel>(new PageInfo<WebUpdate>(updateList), list2List(updateList)); return new PageData<WebUpdateModel>(new PageInfo<WebUpdate>(updateList), list2List(updateList));
} }
@Override @Override
public List<WebUpdateModel> findAll() { public List<WebUpdateModel> findAll() {
List<WebUpdate> all = webUpdateInfoMapper.findAll(); List<WebUpdate> all = webUpdateInfoMapper.findAll();
return list2List(all); return list2List(all);
} }
@Override @Override
public Map<String, Object> getLastestUpdateTime() {
Map<String, Object> map = new HashMap<>(); public Map<String, Object> getLastestUpdateTime() {
map.put("lastUpdateTime", DateFormatUtil.get(webUpdateInfoMapper.getLastestOne().getUpdateTime())); Map<String, Object> map = new HashMap<>();
map.put("lastUpdateInfo", webUpdateInfoMapper.getLastestOne().getUpdateInfo()); map.put("lastUpdateTime", DateFormatUtil.get(webUpdateInfoMapper.getLastestOne().getUpdateTime()));
try { map.put("lastUpdateInfo", webUpdateInfoMapper.getLastestOne().getUpdateInfo());
ObjectMapper mapper = new ObjectMapper(); try {
JsonNode root = mapper.readTree(HttpUtil.get("https://api.github.com/repos/xiaohai2271/blog-frontEnd/commits?page=1&per_page=1")); ObjectMapper mapper = new ObjectMapper();
Iterator<JsonNode> elements = root.elements(); JsonNode root = mapper.readTree(HttpUtil.get("https://api.github.com/repos/xiaohai2271/blog-frontEnd/commits?page=1&per_page=1"));
JsonNode next = elements.next(); Iterator<JsonNode> elements = root.elements();
JsonNode commit = next.get("commit"); JsonNode next = elements.next();
map.put("lastCommit", commit.get("message")); JsonNode commit = next.get("commit");
map.put("committerAuthor", commit.get("committer").get("name")); map.put("lastCommit", commit.get("message"));
Instant parse = Instant.parse(commit.get("committer").get("date").asText()); map.put("committerAuthor", commit.get("committer").get("name"));
map.put("committerDate", DateFormatUtil.get(Date.from(parse))); Instant parse = Instant.parse(commit.get("committer").get("date").asText());
map.put("commitUrl", "https://github.com/xiaohai2271/blog-frontEnd/tree/" + next.get("sha").asText()); map.put("committerDate", DateFormatUtil.get(Date.from(parse)));
} catch (IOException e) { map.put("commitUrl", "https://github.com/xiaohai2271/blog-frontEnd/tree/" + next.get("sha").asText());
log.info("网络请求失败{}", e.getMessage()); } catch (IOException e) {
} log.info("网络请求失败{}", e.getMessage());
return map; }
} return map;
}
private List<WebUpdateModel> list2List(List<WebUpdate> webUpdates) {
List<WebUpdateModel> webUpdateModels = new ArrayList<>(); private List<WebUpdateModel> list2List(List<WebUpdate> webUpdates) {
webUpdates.forEach(update -> webUpdateModels.add(ModalTrans.webUpdate(update))); List<WebUpdateModel> webUpdateModels = new ArrayList<>();
return webUpdateModels; webUpdates.forEach(update -> webUpdateModels.add(ModalTrans.webUpdate(update)));
} return webUpdateModels;
} }
}

View File

@@ -1,12 +1,15 @@
package cn.celess.blog.util; 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.IOException;
import java.io.InputStream; import java.util.Objects;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
/** /**
* @Author: 小海 * @Author: 小海
@@ -14,38 +17,34 @@ import java.nio.charset.StandardCharsets;
* @Desc: * @Desc:
*/ */
public class HttpUtil { public class HttpUtil {
private static final OkHttpClient CLIENT = new OkHttpClient();
public static String get(String urlStr) throws IOException { public static String get(String urlStr) {
Request request = new Request.Builder()
StringBuffer sb = new StringBuffer(); .url(urlStr)
.get()
HttpURLConnection urlConnection = null; .build();
try { try (Response response = CLIENT.newCall(request).execute()) {
URL url = new URL(urlStr); return Objects.requireNonNull(response.body()).string();
} catch (IOException e) {
//打开http return null;
urlConnection = (HttpURLConnection) url.openConnection(); }
urlConnection.setDoInput(true); }
urlConnection.setRequestMethod("GET");
urlConnection.connect();
public static String getAfterRendering(String url) {
try ( try (final WebClient webClient = new WebClient(BrowserVersion.CHROME)) {
InputStream inputStream = urlConnection.getInputStream(); webClient.getOptions().setCssEnabled(false);
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); webClient.getOptions().setJavaScriptEnabled(true);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader) webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
) { webClient.getOptions().setThrowExceptionOnScriptError(false);
//将bufferReader的值给放到buffer里 webClient.getOptions().setDownloadImages(false);
String str = null; webClient.getOptions().setActiveXNative(false);
while ((str = bufferedReader.readLine()) != null) { webClient.setAjaxController(new NicelyResynchronizingAjaxController());
sb.append(str); final HtmlPage page = webClient.getPage(url);
} return page.asXml();
} } catch (IOException e) {
} finally { return null;
//断开连接
if (urlConnection != null) {
urlConnection.disconnect();
}
} }
return sb.toString();
} }
} }

View File

@@ -26,6 +26,12 @@ spring.datasource.url=
spring.datasource.username= spring.datasource.username=
spring.datasource.password= spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.platform=mysql
# never / always / embedded
spring.datasource.initialization-mode=never
spring.datasource.sql-script-encoding=utf-8
spring.datasource.schema=classpath:sql/schema.sql
spring.datasource.data=classpath:sql/data.sql
################## mybatis ################## ################## mybatis ##################

View File

@@ -0,0 +1,96 @@
server.port=8081
# 七牛的密钥配置
qiniu.accessKey=
qiniu.secretKey=
qiniu.bucket=
# sitemap 存放地址
sitemap.path=
# 生成JWT时候的密钥
jwt.secret=sdaniod213k123123ipoeqowekqwe
##spring.jpa.show-sql=false
##spring.jpa.hibernate.ddl-auto=update
mybatis.type-handlers-package=cn.celess.blog.mapper.typehandler
logging.level.cn.celess.blog.mapper=debug
# 上传单个文件的大小
spring.servlet.multipart.max-file-size=10MB
# 上传文件的总大小
spring.servlet.multipart.max-request-size=10MB
spring.jackson.default-property-inclusion=non_null
################# 数据库 ##################
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#h2
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:testdb;mode=mysql;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.platform=h2
spring.datasource.sql-script-encoding=utf-8
spring.datasource.initialization-mode=ALWAYS
spring.datasource.schema=classpath:sql/schema_h2.sql
spring.datasource.data=classpath:sql/data.sql
################## mybatis ##################
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=cn.celess.blog.entity
pagehelper.helper-dialect=mysql
pagehelper.reasonable=true
pagehelper.support-methods-arguments=true
pagehelper.params=count=countSql
#### 用于nginx的代理 获取真实ip
server.use-forward-headers = true
server.tomcat.remote-ip-header = X-Real-IP
server.tomcat.protocol-header = X-Forwarded-Proto
############### email ##############
spring.mail.host=smtp.163.com
spring.mail.username=
spring.mail.password=
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.default-encoding=UTF-8
spring.mail.port=465
spring.mail.properties.mail.smtp.socketFactory.port=465
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
spring.mail.properties.mail.smtp.socketFactory.fallback=false
############### redis ##############
# REDIS (RedisProperties)
# Redis数据库索引默认为0
spring.redis.database=1
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口 解决端口冲突 防止使用本地的redis
spring.redis.port=6380
# Redis服务器连接密码默认为空
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=-1
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=5000

View File

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

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,14 @@
CREATE DATABASE if not exists `blog`; drop view if exists articleView;
drop view if exists commentView;
drop table if exists article_tag;
drop table if exists comment;
drop table if exists article;
drop table if exists user;
drop table if exists tag_category;
drop table if exists links;
drop table if exists visitor;
drop table if exists web_update;
USE blog;
CREATE TABLE `user` CREATE TABLE `user`
( (
@@ -66,19 +74,23 @@ CREATE TABLE `comment`
`co_status` tinyint not null default 0 comment '评论的状态', `co_status` tinyint not null default 0 comment '评论的状态',
`co_pid` bigint not null default -1 comment '评论/留言的父id', `co_pid` bigint not null default -1 comment '评论/留言的父id',
`co_from_author_id` int not null comment '留言者id', `co_from_author_id` int not null comment '留言者id',
`co_to_author_id` int default null comment '父评论的作者id' `co_to_author_id` int default null comment '父评论的作者id',
foreign key (co_from_author_id) references user (u_id),
foreign key (co_to_author_id) references user (u_id)
) DEFAULT CHARSET = utf8mb4 ) DEFAULT CHARSET = utf8mb4
COLLATE utf8mb4_general_ci,comment '评论/留言表'; COLLATE utf8mb4_general_ci,comment '评论/留言表';
CREATE TABLE `links` CREATE TABLE `links`
( (
`l_id` bigint(20) primary key auto_increment, `l_id` bigint(20) primary key auto_increment,
`l_name` varchar(255) COLLATE utf8mb4_unicode_ci not null comment '友站名称', `l_name` varchar(255) COLLATE utf8mb4_unicode_ci not null comment '友站名称',
`l_is_open` boolean default true 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_icon_path` varchar(255) not null comment '友链的icon地址',
`l_desc` varchar(255) COLLATE utf8mb4_unicode_ci not null comment '友链的说明描述', `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 '友站表'; ) comment '友站表';
CREATE TABLE `visitor` CREATE TABLE `visitor`

View File

@@ -0,0 +1,193 @@
drop view if exists articleView;
drop view if exists commentView;
drop table if exists article_tag;
drop table if exists comment;
drop table if exists article;
drop table if exists user;
drop table if exists tag_category;
drop table if exists links;
drop table if exists visitor;
drop table if exists web_update;
-- 用户表
CREATE TABLE `user`
(
`u_id` int not null primary key auto_increment,
`u_email` varchar(50) not null,
`u_pwd` varchar(40) not null comment '密码',
`u_email_status` boolean default false comment '邮箱验证状态',
`u_avatar` varchar(255) default null comment '用户头像',
`u_desc` tinytext default null comment '用户的描述',
`u_recently_landed_time` datetime default null comment '最近的登录时间',
`u_display_name` varchar(30) default null comment '展示的昵称',
`u_role` varchar(40) not null default 'user' comment '权限组',
`status` tinyint(1) not null default 0 comment '账户状态',
unique key `uni_user_id` (`u_id`),
unique key `uni_user_email` (`u_email`)
);
-- 标签和分类表
CREATE TABLE `tag_category`
(
`t_id` bigint(20) primary key auto_increment,
`t_name` varchar(255) not null,
`is_category` boolean not null default true,
`is_delete` boolean not null default false comment '该数据是否被删除'
);
-- 文章表
CREATE TABLE `article`
(
`a_id` bigint(20) primary key auto_increment,
`a_title` varchar(255) not null unique comment '文章标题',
`a_summary` varchar(255) not null comment '文章摘要',
`a_md_content` longtext not null comment '文章Markdown内容',
`a_url` tinytext default null comment '转载文章的原文链接',
`a_author_id` int not null comment '作者id',
`a_is_original` boolean default true comment '文章是否原创',
`a_reading_number` int default 0 comment '文章阅读数',
`a_like` int default 0 comment '文章点赞数',
`a_dislike` int default 0 comment '文章不喜欢数',
`a_category_id` bigint not null comment '文章分类id',
`a_publish_date` datetime default CURRENT_TIMESTAMP comment '文章发布时间',
`a_update_date` datetime default null comment '文章的更新时间',
`a_is_open` boolean default true comment '文章是否可见',
`is_delete` boolean not null default false comment '该数据是否被删除',
foreign key (a_category_id) references tag_category (t_id),
foreign key (a_author_id) references user (u_id)
);
-- 文章标签表
CREATE TABLE `article_tag`
(
`at_id` bigint(20) primary key auto_increment,
`a_id` bigint(20) not null comment '文章id',
`t_id` bigint not null comment 'tag/category 的id',
foreign key (a_id) references article (a_id),
foreign key (t_id) references tag_category (t_id)
);
-- 评论/留言表
CREATE TABLE `comment`
(
`co_id` bigint(20) primary key auto_increment,
`co_page_path` varchar(255) not null comment '评论/留言的页面',
`co_content` text not null comment '评论/留言内容',
`co_date` datetime not null comment '评论/留言的日期',
`co_status` tinyint not null default 0 comment '评论的状态',
`co_pid` bigint not null default -1 comment '评论/留言的父id',
`co_from_author_id` int not null comment '留言者id',
`co_to_author_id` int default null comment '父评论的作者id',
foreign key (co_from_author_id) references user (u_id),
foreign key (co_to_author_id) references user (u_id)
);
-- 友站表
CREATE TABLE `links`
(
`l_id` bigint(20) primary key auto_increment,
`l_name` varchar(255) 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) not null comment '友链的说明描述',
`is_delete` boolean not null default false comment '该数据是否被删除',
`l_email` varchar(255) comment '网站管理员的邮箱',
`l_notification` boolean default false comment '是否通知了'
);
-- 访客表
CREATE TABLE `visitor`
(
`v_id` bigint(20) primary key auto_increment,
`v_date` datetime not null comment '访问时间',
`v_ip` varchar(255) not null comment '访客ip',
`v_user_agent` text comment '访客ua',
`is_delete` boolean not null default false comment '该数据是否被删除'
);
-- 更新内容表
CREATE TABLE `web_update`
(
`wu_id` int primary key auto_increment,
`wu_info` varchar(255) not null comment '更新内容',
`wu_time` datetime not null comment '更新时间',
`is_delete` boolean not null default false comment '该数据是否被删除'
);
CREATE VIEW articleView
(articleId, title, summary, mdContent, url, isOriginal, readingCount, likeCount, dislikeCount,
publishDate, updateDate, isOpen,
categoryId, categoryName, tagId, tagName,
authorId, userEmail, userAvatar, userDisplayName, isDelete)
as
select article.a_id as articleId,
article.a_title as title,
article.a_summary as summary,
article.a_md_content as mdContent,
article.a_url as url,
article.a_is_original as isOriginal,
article.a_reading_number as readingCount,
article.a_like as likeCount,
article.a_dislike as dislikeCount,
article.a_publish_date as publishDate,
article.a_update_date as updateDate,
article.a_is_open as isOpen,
category.t_id as categoryId,
category.t_name as categoryName,
tag.t_id as tagId,
tag.t_name as tagName,
user.u_id as authorId,
user.u_email as userEmail,
user.u_avatar as userAvatar,
user.u_display_name as userDisplayName,
article.is_delete as isDelete
from article,
tag_category as tag,
tag_category as category,
article_tag,
user
where article.a_id = article_tag.a_id
and article_tag.t_id = tag.t_id
and tag.is_category = false
and article.a_category_id = category.t_id
and category.is_category = true
and article.a_author_id = user.u_id;
CREATE VIEW commentView
(commentId, pagePath, content, date, status, pid, toAuthorId, toAuthorEmail, toAuthorDisplayName,
toAuthorAvatar, fromAuthorId, fromAuthorEmail, fromAuthorDisplayName,
fromAuthorAvatar)
as
select cuT.co_id as commentId,
cuT.co_page_path as pagePath,
cuT.co_content as content,
cuT.co_date as date,
cuT.co_status as status,
cuT.co_pid as pid,
cuT.co_to_author_id as toAuthorId,
cuT.toEmail as toAuthorEmail,
cuT.toDisplayName as toAuthorDisplayName,
cuT.toAvatar as toAuthorAvatar,
userFrom.u_id as fromAuthorId,
userFrom.u_email as fromAuthorEmail,
userFrom.u_display_name as fromAuthorDisplayName,
userFrom.u_avatar as fromAuthorAvatar
from (select comment.co_id,
comment.co_page_path,
comment.co_content,
comment.co_date,
comment.co_status,
comment.co_pid,
comment.co_from_author_id,
comment.co_to_author_id,
userTo.u_email as toEmail,
userTo.u_display_name as toDisplayName,
userTo.u_avatar as toAvatar
from comment
left join user userTo on (comment.co_to_author_id = userTo.u_id)
) as cuT,
user as userFrom
where cuT.co_from_author_id = userFrom.u_id;

View File

@@ -1,263 +1,345 @@
package cn.celess.blog; package cn.celess.blog;
import cn.celess.blog.entity.Response; import cn.celess.blog.entity.Response;
import cn.celess.blog.entity.model.UserModel; import cn.celess.blog.entity.model.QiniuResponse;
import cn.celess.blog.entity.request.LoginReq; import cn.celess.blog.entity.model.UserModel;
import com.fasterxml.jackson.core.type.TypeReference; import cn.celess.blog.entity.request.LoginReq;
import com.fasterxml.jackson.databind.ObjectMapper; import cn.celess.blog.service.MailService;
import org.junit.After; import cn.celess.blog.service.QiniuService;
import org.junit.Before; import com.fasterxml.jackson.core.JsonProcessingException;
import org.junit.Test; import com.fasterxml.jackson.core.type.TypeReference;
import org.junit.runner.RunWith; import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger; import com.qiniu.storage.model.FileInfo;
import org.slf4j.LoggerFactory; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.junit.After;
import org.springframework.boot.test.context.SpringBootTest; import org.junit.Before;
import org.springframework.http.MediaType; import org.junit.Test;
import org.springframework.mock.web.MockHttpSession; import org.junit.runner.RunWith;
import org.springframework.test.context.ActiveProfiles; import org.slf4j.Logger;
import org.springframework.test.context.junit4.SpringRunner; import org.slf4j.LoggerFactory;
import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.ResultActions; import org.springframework.mail.SimpleMailMessage;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.mock.web.MockHttpSession;
import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.test.context.ActiveProfiles;
import org.springframework.web.context.WebApplicationContext; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import java.io.IOException; import org.springframework.test.web.servlet.MvcResult;
import java.io.UnsupportedEncodingException; import org.springframework.test.web.servlet.ResultActions;
import java.util.UUID; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static cn.celess.blog.enmu.ResponseEnum.SUCCESS; import org.springframework.web.context.WebApplicationContext;
import static org.junit.Assert.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import java.io.IOException;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.io.InputStream;
import java.io.UnsupportedEncodingException;
/** import java.lang.reflect.Field;
* @Author: 小海 import java.util.Map;
* @Date: 2019/08/22 12:46 import java.util.UUID;
* @Description: 测试基类
*/ import static cn.celess.blog.enmu.ResponseEnum.SUCCESS;
@SpringBootTest import static org.junit.Assert.*;
@RunWith(SpringRunner.class) import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@WebAppConfiguration import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
@ActiveProfiles("test") import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
public class BaseTest {
/**
* @Author: 小海
private final Logger logger = LoggerFactory.getLogger(this.getClass()); * @Date: 2019/08/22 12:46
* @Description: 测试基类
protected MockMvc mockMvc; */
protected final static String Code = "code"; @SpringBootTest
protected final static String Result = "result"; @RunWith(SpringRunner.class)
protected final static String USERE_MAIL = "zh56462271@qq.com"; @WebAppConfiguration
protected final static String ADMIN_EMAIL = "a@celess.cn"; @ActiveProfiles("test")
/** public class BaseTest {
* jackson 序列化/反序列化Json
*/
protected final ObjectMapper mapper = new ObjectMapper(); private final Logger logger = LoggerFactory.getLogger(this.getClass());
protected static final TypeReference<?> BOOLEAN_TYPE = new TypeReference<Response<Boolean>>() {
}; protected MockMvc mockMvc;
protected static final TypeReference<?> STRING_TYPE = new TypeReference<Response<String>>() { protected final static String Code = "code";
}; protected final static String Result = "result";
protected static final TypeReference<?> OBJECT_TYPE = new TypeReference<Response<Object>>() {
}; /**
@Autowired * jackson 序列化/反序列化Json
private WebApplicationContext wac; */
protected MockHttpSession session; protected final ObjectMapper mapper = new ObjectMapper();
protected static final TypeReference<?> BOOLEAN_TYPE = new TypeReference<Response<Boolean>>() {
@Before };
public void before() { protected static final TypeReference<?> STRING_TYPE = new TypeReference<Response<String>>() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); };
session = new MockHttpSession(); protected static final TypeReference<?> OBJECT_TYPE = new TypeReference<Response<Object>>() {
System.out.println("==========> 开始测试 <========="); };
} protected static final TypeReference<?> MAP_OBJECT_TYPE = new TypeReference<Response<Map<String, Object>>>() {
};
@After
public void after() { @Autowired
System.out.println("==========> 测试结束 <========="); private WebApplicationContext wac;
} protected MockHttpSession session;
/** @Before
*  admin 权限用户登录 public void before() {
* this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
* @return token session = new MockHttpSession();
*/ System.out.println("==========> 开始测试 <=========");
protected String adminLogin() { }
LoginReq req = new LoginReq();
req.setEmail(ADMIN_EMAIL); @After
req.setPassword("123456789"); public void after() {
req.setIsRememberMe(true); System.out.println("==========> 测试结束 <=========");
String token = login(req); }
assertNotNull(token);
return token; /**
} *  admin 权限用户登录
*
/** * @return token
* user 权限用户登录 */
* protected String adminLogin() {
* @return token LoginReq req = new LoginReq();
*/ req.setEmail(ADMIN_EMAIL);
protected String userLogin() { req.setPassword("123456789");
LoginReq req = new LoginReq(); req.setIsRememberMe(true);
req.setEmail(USERE_MAIL); String token = login(req);
req.setPassword("123456789"); assertNotNull(token);
req.setIsRememberMe(true); return token;
String token = login(req); }
assertNotNull(token);
return token; /**
} * user 权限用户登录
*
/** * @return token
* 登录逻辑 */
* protected String userLogin() {
* @param req 用户信息 LoginReq req = new LoginReq();
* @return token | null req.setEmail(USERE_MAIL);
*/ req.setPassword("123456789");
protected String login(LoginReq req) { req.setIsRememberMe(true);
String str = null; String token = login(req);
try { assertNotNull(token);
str = getMockData(post("/login"), null, req) return token;
.andReturn().getResponse().getContentAsString(); }
Response<UserModel> response = mapper.readValue(str, new TypeReference<Response<UserModel>>() {
}); /**
assertEquals(SUCCESS.getCode(), response.getCode()); * 登录逻辑
String token = response.getResult().getToken(); *
assertNotNull(token); * @param req 用户信息
return token; * @return token | null
} catch (Exception e) { */
logger.error("测试登录错误"); protected String login(LoginReq req) {
e.printStackTrace(); String str = null;
} try {
assertNotNull(str); str = getMockData(post("/login"), null, req)
return null; .andReturn().getResponse().getContentAsString();
} Response<UserModel> response = mapper.readValue(str, new TypeReference<Response<UserModel>>() {
});
@Test assertEquals(SUCCESS.getCode(), response.getCode());
public void test() { String token = response.getResult().getToken();
// 测试登录 assertNotNull(token);
assertNotNull(userLogin()); return token;
assertNotNull(adminLogin()); } catch (Exception e) {
assertNotEquals(userLogin(), adminLogin()); logger.error("测试登录错误");
try { e.printStackTrace();
// 测试getMockData方法 }
assertNotNull(getMockData(get("/headerInfo"))); assertNotNull(str);
getMockData((get("/headerInfo"))).andDo(result -> assertNotNull(getResponse(result, OBJECT_TYPE))); return null;
} catch (Exception e) { }
e.printStackTrace();
} @Test
} public void test() {
// 测试登录
/** assertNotNull(userLogin());
* 产生指定长度的随机字符 assertNotNull(adminLogin());
* assertNotEquals(userLogin(), adminLogin());
* @param len len try {
* @return str // 测试getMockData方法
*/ assertNotNull(getMockData(get("/headerInfo")));
protected String randomStr(int len) { getMockData((get("/headerInfo"))).andDo(result -> assertNotNull(getResponse(result, OBJECT_TYPE)));
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, len); } catch (Exception e) {
} e.printStackTrace();
}
/** }
* 产生指定长度的随机字符
* /**
* @return str * 产生指定长度的随机字符
*/ *
protected String randomStr() { * @param len len
return UUID.randomUUID().toString(); * @return str
} */
protected String randomStr(int len) {
/** return UUID.randomUUID().toString().replaceAll("-", "").substring(0, len);
* 抽离的mock请求方法 }
*
* @param builder MockHttpServletRequestBuilder get(...) post(...) .... /**
* @return 返回 ResultActions * 产生指定长度的随机字符
* @throws Exception exc *
*/ * @return str
protected ResultActions getMockData(MockHttpServletRequestBuilder builder) throws Exception { */
return getMockData(builder, null, null); protected String randomStr() {
} return UUID.randomUUID().toString();
}
/**
* 抽离的mock请求方法 重载 /**
* * 抽离的mock请求方法
* @param builder .. *
* @param token 用户登录的token * @param builder MockHttpServletRequestBuilder get(...) post(...) ....
* @return .. * @return 返回 ResultActions
* @throws Exception .. * @throws Exception exc
*/ */
protected ResultActions getMockData(MockHttpServletRequestBuilder builder, String token) throws Exception { protected ResultActions getMockData(MockHttpServletRequestBuilder builder) throws Exception {
return getMockData(builder, token, null); return getMockData(builder, null, null);
} }
/** /**
* 抽离的mock请求方法 重载 * 抽离的mock请求方法 重载
* *
* @param builder .. * @param builder ..
* @param token .. * @param token 用户登录的token
* @param content http中发送的APPLICATION_JSON的json数据 * @return ..
* @return .. * @throws Exception ..
* @throws Exception .. */
*/ protected ResultActions getMockData(MockHttpServletRequestBuilder builder, String token) throws Exception {
protected ResultActions getMockData(MockHttpServletRequestBuilder builder, String token, Object content) throws Exception { return getMockData(builder, token, null);
// MockHttpServletRequestBuilder mockHttpServletRequestBuilder = get(url); }
if (token != null) {
builder.header("Authorization", token); /**
} * 抽离的mock请求方法 重载
if (content != null) { *
builder.content(mapper.writeValueAsString(content)).contentType(MediaType.APPLICATION_JSON); * @param builder ..
logger.debug("param::json->{}", mapper.writeValueAsString(content)); * @param token ..
} * @param content http中发送的APPLICATION_JSON的json数据
return mockMvc.perform(builder).andExpect(status().isOk()); * @return ..
} * @throws Exception ..
*/
protected ResultActions getMockData(MockHttpServletRequestBuilder builder, String token, Object content) throws Exception {
protected <T> Response<T> getResponse(String json) { // MockHttpServletRequestBuilder mockHttpServletRequestBuilder = get(url);
return getResponse(json, OBJECT_TYPE); if (token != null) {
} builder.header("Authorization", token);
}
protected <T> Response<T> getResponse(MvcResult result) { if (content != null) {
return getResponse(result, OBJECT_TYPE); builder.content(mapper.writeValueAsString(content)).contentType(MediaType.APPLICATION_JSON);
} logger.debug("param::json->{}", mapper.writeValueAsString(content));
}
/** return mockMvc.perform(builder).andExpect(status().isOk());
* 根据json 信息反序列化成Response对象 }
*
* @param json json
* @param <T> 泛型 protected <T> Response<T> getResponse(String json) {
* @return Response对象 return getResponse(json, OBJECT_TYPE);
*/ }
protected <T> Response<T> getResponse(String json, TypeReference<?> responseType) {
Response<T> response = null; protected <T> Response<T> getResponse(MvcResult result) {
try { return getResponse(result, OBJECT_TYPE);
response = mapper.readValue(json, responseType); }
} catch (IOException e) {
logger.error("解析json Response对象错误json:[{}]", json); /**
e.printStackTrace(); * 根据json 信息反序列化成Response对象
} *
assertNotNull(response); * @param json json
return response; * @param <T> 泛型
} * @return Response对象
*/
/** protected <T> Response<T> getResponse(String json, TypeReference<?> responseType) {
* 根据json 信息反序列化成Response对象 Response<T> response = null;
* try {
* @param result MvcResult response = mapper.readValue(json, responseType);
* @param <T> 泛型 } catch (IOException e) {
* @return Response对象 logger.error("解析json Response对象错误json:[{}]", json);
*/ e.printStackTrace();
protected <T> Response<T> getResponse(MvcResult result, TypeReference<?> responseType) { }
try { assertNotNull(response);
return getResponse(result.getResponse().getContentAsString(), responseType); return response;
} catch (UnsupportedEncodingException e) { }
logger.error("解析json Response对象错误result:[{}]", result);
e.printStackTrace(); /**
} * 根据json 信息反序列化成Response对象
return null; *
} * @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 mockInjectInstance(Object service, String mailFiledName, Object impl) {
Field field;
try {
field = service.getClass().getDeclaredField(mailFiledName);
field.setAccessible(true);
field.set(service, impl);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
@Slf4j
public 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;
}
}
}
@Slf4j
public static class TestQiNiuServiceImpl implements QiniuService {
@Override
public QiniuResponse uploadFile(InputStream is, String fileName) {
QiniuResponse response = new QiniuResponse();
log.debug("上传文件请求,[fileName:{}]", fileName);
response.key = "key";
response.bucket = "bucket";
response.hash = "hash";
response.fsize = 1;
return response;
}
@Override
public FileInfo[] getFileList() {
log.debug("获取文件列表请求");
return new FileInfo[0];
}
}
}

View File

@@ -0,0 +1,37 @@
package cn.celess.blog;
import redis.embedded.RedisServer;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
/**
* @author : xiaohai
* @date : 2020/08/14 16:20
*/
@Component
public class RedisServerMock {
private RedisServer redisServer;
/**
* 构造方法之后执行.
*
* @throws IOException e
*/
@PostConstruct
public void startRedis() throws IOException {
redisServer = new RedisServer(6380);
redisServer.start();
}
/**
* 析构方法之后执行.
*/
@PreDestroy
public void stopRedis() {
redisServer.stop();
}
}

View File

@@ -1,162 +1,249 @@
package cn.celess.blog.controller; package cn.celess.blog.controller;
import cn.celess.blog.BaseTest; import cn.celess.blog.BaseTest;
import cn.celess.blog.entity.PartnerSite; import cn.celess.blog.entity.PartnerSite;
import cn.celess.blog.entity.Response; import cn.celess.blog.entity.Response;
import cn.celess.blog.entity.model.PageData; import cn.celess.blog.entity.model.PageData;
import cn.celess.blog.entity.request.LinkReq; import cn.celess.blog.entity.request.LinkApplyReq;
import cn.celess.blog.mapper.PartnerMapper; import cn.celess.blog.entity.request.LinkReq;
import com.fasterxml.jackson.core.type.TypeReference; import cn.celess.blog.exception.MyException;
import org.junit.Test; import cn.celess.blog.mapper.PartnerMapper;
import org.springframework.beans.factory.annotation.Autowired; import com.fasterxml.jackson.core.type.TypeReference;
import org.junit.Test;
import java.util.List; import org.springframework.beans.factory.annotation.Autowired;
import static cn.celess.blog.enmu.ResponseEnum.*; import java.util.List;
import static org.junit.Assert.*; import cn.celess.blog.service.MailService;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import cn.celess.blog.service.PartnerSiteService;
import com.fasterxml.jackson.core.JsonProcessingException;
public class LinksControllerTest extends BaseTest { import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
@Autowired import net.sf.json.JSONObject;
PartnerMapper mapper; import org.junit.Test;
private static final TypeReference<?> LINK_MODEL_TYPE = new TypeReference<Response<PartnerSite>>() { import org.springframework.beans.factory.annotation.Autowired;
}; import org.springframework.http.MediaType;
private static final TypeReference<?> LINK_MODEL_LIST_TYPE = new TypeReference<Response<List<PartnerSite>>>() { import org.springframework.mail.SimpleMailMessage;
};
private static final TypeReference<?> LINK_MODEL_PAGE_TYPE = new TypeReference<Response<PageData<PartnerSite>>>() { import java.lang.reflect.Field;
}; import java.util.UUID;
@Test import static cn.celess.blog.enmu.ResponseEnum.*;
public void create() throws Exception { import static org.junit.Assert.*;
LinkReq linkReq = new LinkReq(); import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
linkReq.setName(randomStr(4));
linkReq.setOpen(false); @Slf4j
linkReq.setUrl("https://" + randomStr(4) + "example.com"); public class LinksControllerTest extends BaseTest {
getMockData(post("/admin/links/create"), adminLogin(), linkReq).andDo(result -> {
Response<PartnerSite> response = getResponse(result, LINK_MODEL_TYPE); @Autowired
assertEquals(SUCCESS.getCode(), response.getCode()); PartnerMapper mapper;
PartnerSite site = response.getResult(); private static final TypeReference<?> LINK_MODEL_TYPE = new TypeReference<Response<PartnerSite>>() {
assertNotNull(site.getId()); };
assertEquals(linkReq.getName(), site.getName()); private static final TypeReference<?> LINK_MODEL_LIST_TYPE = new TypeReference<Response<List<PartnerSite>>>() {
assertEquals(linkReq.getUrl(), site.getUrl()); };
assertEquals(linkReq.isOpen(), site.getOpen()); private static final TypeReference<?> LINK_MODEL_PAGE_TYPE = new TypeReference<Response<PageData<PartnerSite>>>() {
}); };
@Autowired
// https/http PartnerSiteService partnerSiteService;
linkReq.setName(randomStr(4));
linkReq.setOpen(false);
linkReq.setUrl(randomStr(4) + ".example.com"); @Test
getMockData(post("/admin/links/create"), adminLogin(), linkReq).andDo(result -> { public void create() throws Exception {
Response<PartnerSite> response = getResponse(result, LINK_MODEL_TYPE); LinkReq linkReq = new LinkReq();
assertEquals(SUCCESS.getCode(), response.getCode()); linkReq.setName(randomStr(4));
PartnerSite site = response.getResult(); linkReq.setOpen(false);
assertEquals("http://" + linkReq.getUrl(), site.getUrl()); linkReq.setUrl("https://" + randomStr(4) + "example.com");
}); getMockData(post("/admin/links/create"), adminLogin(), linkReq).andDo(result -> {
Response<PartnerSite> response = getResponse(result, LINK_MODEL_TYPE);
// 测试已存在的数据 assertEquals(SUCCESS.getCode(), response.getCode());
getMockData(post("/admin/links/create"), adminLogin(), linkReq).andDo(result -> PartnerSite site = response.getResult();
assertEquals(DATA_HAS_EXIST.getCode(), getResponse(result, STRING_TYPE).getCode()) assertNotNull(site.getId());
); assertEquals(linkReq.getName(), site.getName());
} assertEquals(linkReq.getUrl(), site.getUrl());
assertEquals(linkReq.isOpen(), site.getOpen());
@Test });
public void del() throws Exception {
PartnerSite partnerSite = new PartnerSite(); // https/http
partnerSite.setName(randomStr(4)); linkReq.setName(randomStr(4));
partnerSite.setOpen(true); linkReq.setOpen(false);
partnerSite.setDesc(""); linkReq.setUrl(randomStr(4) + ".example.com");
partnerSite.setIconPath(""); getMockData(post("/admin/links/create"), adminLogin(), linkReq).andDo(result -> {
partnerSite.setUrl("https://" + randomStr(4) + ".celess.cn"); Response<PartnerSite> response = getResponse(result, LINK_MODEL_TYPE);
mapper.insert(partnerSite); assertEquals(SUCCESS.getCode(), response.getCode());
PartnerSite latest = mapper.getLastest(); PartnerSite site = response.getResult();
assertNotNull(latest.getId()); assertEquals("http://" + linkReq.getUrl(), site.getUrl());
getMockData(delete("/admin/links/del/" + latest.getId()), adminLogin()).andDo(result -> { });
Response<Boolean> response = getResponse(result, BOOLEAN_TYPE);
assertEquals(SUCCESS.getCode(), response.getCode()); // 测试已存在的数据
assertTrue(response.getResult()); getMockData(post("/admin/links/create"), adminLogin(), linkReq).andDo(result ->
}); assertEquals(DATA_HAS_EXIST.getCode(), getResponse(result, STRING_TYPE).getCode())
long id = latest.getId(); );
do { }
id += 1;
} while (mapper.existsById(id)); @Test
System.out.println("删除ID=" + id + "的数据"); public void del() throws Exception {
getMockData(delete("/admin/links/del/" + id), adminLogin()).andDo(result -> PartnerSite partnerSite = new PartnerSite();
assertEquals(DATA_NOT_EXIST.getCode(), getResponse(result, STRING_TYPE).getCode()) partnerSite.setName(randomStr(4));
); partnerSite.setOpen(true);
} partnerSite.setDesc("");
partnerSite.setIconPath("");
@Test partnerSite.setUrl("https://" + randomStr(4) + ".celess.cn");
public void update() throws Exception { mapper.insert(partnerSite);
// 增数据 PartnerSite latest = mapper.getLastest();
PartnerSite partnerSite = new PartnerSite(); assertNotNull(latest.getId());
partnerSite.setName(randomStr(4)); getMockData(delete("/admin/links/del/" + latest.getId()), adminLogin()).andDo(result -> {
partnerSite.setOpen(true); Response<Boolean> response = getResponse(result, BOOLEAN_TYPE);
partnerSite.setDesc(""); assertEquals(SUCCESS.getCode(), response.getCode());
partnerSite.setIconPath(""); assertTrue(response.getResult());
partnerSite.setDelete(false); });
partnerSite.setUrl("https://" + randomStr(5) + ".celess.cn"); long id = latest.getId();
mapper.insert(partnerSite); do {
// 查数据 id += 1;
PartnerSite latest = mapper.getLastest(); } while (mapper.existsById(id));
assertNotNull(latest.getId()); System.out.println("删除ID=" + id + "的数据");
// 构建请求 getMockData(delete("/admin/links/del/" + id), adminLogin()).andDo(result ->
LinkReq linkReq = new LinkReq(); assertEquals(DATA_NOT_EXIST.getCode(), getResponse(result, STRING_TYPE).getCode())
linkReq.setUrl(latest.getUrl()); );
linkReq.setOpen(!latest.getOpen()); }
linkReq.setName(randomStr(4));
linkReq.setId(latest.getId()); @Test
public void update() throws Exception {
getMockData(put("/admin/links/update"), adminLogin(), linkReq).andDo(result -> { // 增数据
Response<PartnerSite> response = getResponse(result, LINK_MODEL_TYPE); PartnerSite partnerSite = new PartnerSite();
assertEquals(SUCCESS.getCode(), response.getCode()); partnerSite.setName(randomStr(4));
PartnerSite site = response.getResult(); partnerSite.setOpen(true);
assertNotNull(site.getId()); partnerSite.setDesc("");
assertEquals(linkReq.getId(), site.getId().longValue()); partnerSite.setIconPath("");
assertEquals(linkReq.getUrl(), site.getUrl()); partnerSite.setDelete(false);
assertEquals(linkReq.getName(), site.getName()); partnerSite.setUrl("https://" + randomStr(5) + ".celess.cn");
assertEquals(linkReq.isOpen(), site.getOpen()); mapper.insert(partnerSite);
}); // 查数据
} PartnerSite latest = mapper.getLastest();
assertNotNull(latest.getId());
@Test // 构建请求
public void allForOpen() throws Exception { LinkReq linkReq = new LinkReq();
getMockData(get("/links")).andDo(result -> { linkReq.setUrl(latest.getUrl());
Response<List<PartnerSite>> response = getResponse(result, LINK_MODEL_LIST_TYPE); linkReq.setOpen(!latest.getOpen());
assertEquals(SUCCESS.getCode(), response.getCode()); linkReq.setName(randomStr(4));
response.getResult().forEach(site -> { linkReq.setId(latest.getId());
assertNotNull(site.getUrl());
assertNull(site.getOpen()); getMockData(put("/admin/links/update"), adminLogin(), linkReq).andDo(result -> {
assertNotNull(site.getName()); Response<PartnerSite> response = getResponse(result, LINK_MODEL_TYPE);
}); assertEquals(SUCCESS.getCode(), response.getCode());
}); PartnerSite site = response.getResult();
} assertNotNull(site.getId());
assertEquals(linkReq.getId(), site.getId().longValue());
@Test assertEquals(linkReq.getUrl(), site.getUrl());
public void all() throws Exception { assertEquals(linkReq.getName(), site.getName());
getMockData(get("/admin/links?page=1&count=10"), adminLogin()).andDo(result -> { assertEquals(linkReq.isOpen(), site.getOpen());
Response<PageData<PartnerSite>> response = getResponse(result, LINK_MODEL_PAGE_TYPE); });
assertEquals(SUCCESS.getCode(), response.getCode()); }
PageData<PartnerSite> pageData = response.getResult();
assertEquals(1, pageData.getPageNum()); @Test
assertEquals(10, pageData.getPageSize()); public void allForOpen() throws Exception {
for (PartnerSite site : pageData.getList()) { getMockData(get("/links")).andDo(result -> {
assertNotNull(site.getUrl()); Response<List<PartnerSite>> response = getResponse(result, LINK_MODEL_LIST_TYPE);
assertNotNull(site.getName()); assertEquals(SUCCESS.getCode(), response.getCode());
assertNotNull(site.getOpen()); response.getResult().forEach(site -> {
} assertNotNull(site.getUrl());
}); assertNull(site.getOpen());
} assertNotNull(site.getName());
});
// 手动测试 });
// @Test }
public void apply() throws Exception {
long l = System.currentTimeMillis(); @Test
String url = "https://www.example.com"; public void all() throws Exception {
getMockData(post("/apply?name=小海博客Api测试请忽略&url=" + url)).andDo(result -> assertEquals(SUCCESS.getCode(), getResponse(result, OBJECT_TYPE).getCode())); getMockData(get("/admin/links?page=1&count=10"), adminLogin()).andDo(result -> {
System.out.println("耗时:" + (System.currentTimeMillis() - l) / 1000 + "s"); Response<PageData<PartnerSite>> response = getResponse(result, LINK_MODEL_PAGE_TYPE);
url = "xxx"; assertEquals(SUCCESS.getCode(), response.getCode());
getMockData(post("/apply?name=小海博客Api测试请忽略&url=" + url)).andDo(result -> assertEquals(PARAMETERS_URL_ERROR.getCode(), getResponse(result, OBJECT_TYPE).getCode())); PageData<PartnerSite> pageData = response.getResult();
assertEquals(1, pageData.getPageNum());
} assertEquals(10, pageData.getPageSize());
for (PartnerSite site : pageData.getList()) {
assertNotNull(site.getUrl());
assertNotNull(site.getName());
assertNotNull(site.getOpen());
}
});
}
@Test
public void apply() {
// 做service 层的测试
// mockEmailServiceInstance(partnerSiteService, "mailService");
mockInjectInstance(partnerSiteService, "mailService", new TestMailServiceImpl());
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

@@ -1,264 +1,274 @@
package cn.celess.blog.controller; package cn.celess.blog.controller;
import cn.celess.blog.BaseTest; import cn.celess.blog.BaseTest;
import cn.celess.blog.entity.Response; import cn.celess.blog.entity.Response;
import cn.celess.blog.entity.User; import cn.celess.blog.entity.User;
import cn.celess.blog.entity.model.PageData; import cn.celess.blog.entity.model.PageData;
import cn.celess.blog.entity.model.UserModel; import cn.celess.blog.entity.model.UserModel;
import cn.celess.blog.entity.request.LoginReq; import cn.celess.blog.entity.request.LoginReq;
import cn.celess.blog.entity.request.UserReq; import cn.celess.blog.entity.request.UserReq;
import cn.celess.blog.mapper.UserMapper; import cn.celess.blog.mapper.UserMapper;
import cn.celess.blog.util.MD5Util; import cn.celess.blog.service.UserService;
import cn.celess.blog.util.RedisUtil; import cn.celess.blog.util.MD5Util;
import com.fasterxml.jackson.core.type.TypeReference; import cn.celess.blog.util.RedisUtil;
import org.junit.Test; import com.fasterxml.jackson.core.type.TypeReference;
import org.springframework.beans.factory.annotation.Autowired; import org.junit.Test;
import org.springframework.http.MediaType; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.mock.web.MockMultipartFile;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.util.MultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import java.io.InputStream;
import java.net.HttpURLConnection; import java.io.InputStream;
import java.net.URL; import java.net.HttpURLConnection;
import java.util.*; import java.net.URL;
import java.util.concurrent.TimeUnit; import java.util.*;
import java.util.stream.Collectors; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static cn.celess.blog.enmu.ResponseEnum.*;
import static org.junit.Assert.*; import static cn.celess.blog.enmu.ResponseEnum.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.junit.Assert.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
public class UserControllerTest extends BaseTest { import static cn.celess.blog.enmu.ResponseEnum.*;
@Autowired
UserMapper userMapper; public class UserControllerTest extends BaseTest {
@Autowired
RedisUtil redisUtil; @Autowired
private static final TypeReference<?> USER_MODEL_TYPE = new TypeReference<Response<UserModel>>() { UserMapper userMapper;
}; @Autowired
private static final TypeReference<?> USER_MODEL_PAGE_TYPE = new TypeReference<Response<PageData<UserModel>>>() {
}; RedisUtil redisUtil;
private static final TypeReference<?> USER_MODEL_LIST_TYPE = new TypeReference<Response<List<Map<String, Object>>>>() { private static final TypeReference<?> USER_MODEL_TYPE = new TypeReference<Response<UserModel>>() {
}; };
private static final TypeReference<?> USER_MODEL_PAGE_TYPE = new TypeReference<Response<PageData<UserModel>>>() {
@Test };
public void login() throws Exception { private static final TypeReference<?> USER_MODEL_LIST_TYPE = new TypeReference<Response<List<Map<String, Object>>>>() {
assertNotNull(userLogin()); };
assertNotNull(adminLogin()); UserService userService;
// 用户不存在
LoginReq req = new LoginReq();
req.setEmail("zh@celess.cn"); @Test
req.setPassword("123456789"); public void login() throws Exception {
req.setIsRememberMe(false); assertNotNull(userLogin());
getMockData(post("/login"), null, req).andDo(result -> assertEquals(USER_NOT_EXIST.getCode(), getResponse(result, STRING_TYPE).getCode())); assertNotNull(adminLogin());
} // 用户不存在
LoginReq req = new LoginReq();
@Test req.setEmail("zh@celess.cn");
public void registration() { req.setPassword("123456789");
// ignore req.setIsRememberMe(false);
} getMockData(post("/login"), null, req).andDo(result -> assertEquals(USER_NOT_EXIST.getCode(), getResponse(result, STRING_TYPE).getCode()));
}
@Test
public void logout() throws Exception { @Test
getMockData(get("/logout")).andDo(result -> assertEquals(SUCCESS.getCode(), getResponse(result, STRING_TYPE).getCode())); public void registration() {
getMockData(get("/logout"), adminLogin()).andDo(result -> assertEquals(SUCCESS.getCode(), getResponse(result).getCode())); // ignore
} }
@Test @Test
public void updateInfo() throws Exception { public void logout() throws Exception {
String desc = randomStr(4); getMockData(get("/logout")).andDo(result -> assertEquals(SUCCESS.getCode(), getResponse(result, STRING_TYPE).getCode()));
String disPlayName = randomStr(4); getMockData(get("/logout"), adminLogin()).andDo(result -> assertEquals(SUCCESS.getCode(), getResponse(result).getCode()));
getMockData(put("/user/userInfo/update?desc=" + desc + "&displayName=" + disPlayName), userLogin()).andDo(result -> { }
Response<UserModel> response = getResponse(result, USER_MODEL_TYPE);
assertEquals(SUCCESS.getCode(), response.getCode()); @Test
UserModel u = response.getResult(); public void updateInfo() throws Exception {
assertEquals(desc, u.getDesc()); String desc = randomStr(4);
assertEquals(disPlayName, u.getDisplayName()); String disPlayName = randomStr(4);
assertNotNull(u.getId()); getMockData(put("/user/userInfo/update?desc=" + desc + "&displayName=" + disPlayName), userLogin()).andDo(result -> {
}); Response<UserModel> response = getResponse(result, USER_MODEL_TYPE);
} assertEquals(SUCCESS.getCode(), response.getCode());
UserModel u = response.getResult();
@Test assertEquals(desc, u.getDesc());
public void getUserInfo() throws Exception { assertEquals(disPlayName, u.getDisplayName());
getMockData(get("/user/userInfo"), userLogin()).andDo(result -> { assertNotNull(u.getId());
Response<UserModel> response = getResponse(result, USER_MODEL_TYPE); });
assertEquals(SUCCESS.getCode(), response.getCode()); }
UserModel u = response.getResult();
assertNotNull(u.getId()); @Test
assertNotNull(u.getEmail()); public void getUserInfo() throws Exception {
assertNotNull(u.getDisplayName()); getMockData(get("/user/userInfo"), userLogin()).andDo(result -> {
assertNotNull(u.getEmailStatus()); Response<UserModel> response = getResponse(result, USER_MODEL_TYPE);
assertNotNull(u.getAvatarImgUrl()); assertEquals(SUCCESS.getCode(), response.getCode());
assertNotNull(u.getDesc()); UserModel u = response.getResult();
assertNotNull(u.getRecentlyLandedDate()); assertNotNull(u.getId());
assertNotNull(u.getRole()); assertNotNull(u.getEmail());
}); assertNotNull(u.getDisplayName());
} assertNotNull(u.getEmailStatus());
assertNotNull(u.getAvatarImgUrl());
@Test assertNotNull(u.getDesc());
public void upload() throws Exception { assertNotNull(u.getRecentlyLandedDate());
URL url = new URL("https://56462271.oss-cn-beijing.aliyuncs.com/web/logo.png"); assertNotNull(u.getRole());
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); });
connection.setRequestMethod("GET"); }
InputStream inputStream = connection.getInputStream();
assertNotNull(inputStream); @Test
MockMultipartFile file = new MockMultipartFile("file", "logo.png", MediaType.IMAGE_PNG_VALUE, inputStream); public void upload() throws Exception {
getMockData(multipart("/user/imgUpload").file(file), userLogin()).andDo(result -> { URL url = new URL("https://56462271.oss-cn-beijing.aliyuncs.com/web/logo.png");
Response<Object> response = getResponse(result, OBJECT_TYPE); HttpURLConnection connection = (HttpURLConnection) url.openConnection();
assertEquals(SUCCESS.getCode(), response.getCode()); connection.setRequestMethod("GET");
assertNotNull(response.getResult()); InputStream inputStream = connection.getInputStream();
}); assertNotNull(inputStream);
}
// mock 实现类
@Test mockInjectInstance(userService, "qiniuService", new TestQiNiuServiceImpl());
public void sendResetPwdEmail() {
// ignore MockMultipartFile file = new MockMultipartFile("file", "logo.png", MediaType.IMAGE_PNG_VALUE, inputStream);
} getMockData(multipart("/user/imgUpload").file(file), userLogin()).andDo(result -> {
Response<Object> response = getResponse(result, OBJECT_TYPE);
@Test assertEquals(SUCCESS.getCode(), response.getCode());
public void sendVerifyEmail() { assertNotNull(response.getResult());
// ignore });
} }
@Test @Test
public void emailVerify() throws Exception { public void sendResetPwdEmail() {
String email = randomStr(4) + "@celess.cn"; // ignore
String pwd = MD5Util.getMD5("123456789"); }
userMapper.addUser(new User(email, pwd));
String verifyId = randomStr(); @Test
LoginReq req = new LoginReq(email, "123456789", true); public void sendVerifyEmail() {
redisUtil.setEx(email + "-verify", verifyId, 2, TimeUnit.DAYS); // ignore
getMockData(post("/emailVerify").param("verifyId", verifyId).param("email", email), login(req)).andDo(result -> }
assertEquals(SUCCESS.getCode(), getResponse(result, OBJECT_TYPE).getCode())
); @Test
} public void emailVerify() throws Exception {
String email = randomStr(4) + "@celess.cn";
@Test String pwd = MD5Util.getMD5("123456789");
public void resetPwd() throws Exception { userMapper.addUser(new User(email, pwd));
String email = randomStr(4) + "@celess.cn"; String verifyId = randomStr();
String pwd = MD5Util.getMD5("1234567890"); LoginReq req = new LoginReq(email, "123456789", true);
userMapper.addUser(new User(email, pwd)); redisUtil.setEx(email + "-verify", verifyId, 2, TimeUnit.DAYS);
LoginReq req = new LoginReq(email, "1234567890", true); getMockData(post("/emailVerify").param("verifyId", verifyId).param("email", email), login(req)).andDo(result ->
String verifyId = randomStr(); assertEquals(SUCCESS.getCode(), getResponse(result, OBJECT_TYPE).getCode())
// 设置验证id );
redisUtil.setEx(email + "-resetPwd", verifyId, 2, TimeUnit.DAYS); }
MockHttpServletRequestBuilder resetPwd = post("/resetPwd").param("verifyId", verifyId).param("email", email).param("pwd", "123456789");
// 未验证 @Test
getMockData(resetPwd, login(req)).andDo(result -> assertEquals(USEREMAIL_NOT_VERIFY.getCode(), getResponse(result, OBJECT_TYPE).getCode())); public void resetPwd() throws Exception {
// 设置未验证 String email = randomStr(4) + "@celess.cn";
userMapper.updateEmailStatus(email, true); String pwd = MD5Util.getMD5("1234567890");
// 正常 userMapper.addUser(new User(email, pwd));
getMockData(resetPwd, login(req)).andDo(result -> assertEquals(SUCCESS.getCode(), getResponse(result, OBJECT_TYPE).getCode())); LoginReq req = new LoginReq(email, "1234567890", true);
} String verifyId = randomStr();
// 设置验证id
@Test redisUtil.setEx(email + "-resetPwd", verifyId, 2, TimeUnit.DAYS);
public void multipleDelete() throws Exception { MockHttpServletRequestBuilder resetPwd = post("/resetPwd").param("verifyId", verifyId).param("email", email).param("pwd", "123456789");
List<User> userList = new ArrayList<>(); // 未验证
for (int i = 0; i < 10; i++) { getMockData(resetPwd, login(req)).andDo(result -> assertEquals(USEREMAIL_NOT_VERIFY.getCode(), getResponse(result, OBJECT_TYPE).getCode()));
String s = randomStr(); // 设置未验证
String email = s.substring(s.length() - 4) + "@celess.cn"; userMapper.updateEmailStatus(email, true);
String pwd = MD5Util.getMD5("123456789"); // 正常
User user = new User(email, pwd); getMockData(resetPwd, login(req)).andDo(result -> assertEquals(SUCCESS.getCode(), getResponse(result, OBJECT_TYPE).getCode()));
int i1 = userMapper.addUser(user); }
if (i1 == 0) {
continue; @Test
} public void multipleDelete() throws Exception {
userList.add(userMapper.findByEmail(email)); List<User> userList = new ArrayList<>();
if (i == 9) { for (int i = 0; i < 10; i++) {
//设置一个管理员 String s = randomStr();
userMapper.setUserRole(userMapper.findByEmail(email).getId(), "admin"); String email = s.substring(s.length() - 4) + "@celess.cn";
} String pwd = MD5Util.getMD5("123456789");
} User user = new User(email, pwd);
List<Integer> idList = userList.stream().map(user -> user.getId().intValue()).collect(Collectors.toList()); int i1 = userMapper.addUser(user);
getMockData(delete("/admin/user/delete"), adminLogin(), idList).andDo(result -> { if (i1 == 0) {
Response<List<Map<String, Object>>> response = getResponse(result, USER_MODEL_LIST_TYPE); continue;
assertEquals(SUCCESS.getCode(), response.getCode()); }
response.getResult().forEach(o -> { userList.add(userMapper.findByEmail(email));
// 判断响应数据中是否包含输入的id if (i == 9) {
assertTrue(idList.contains((int) o.get("id"))); //设置一个管理员
// 判断处理状态 userMapper.setUserRole(userMapper.findByEmail(email).getId(), "admin");
boolean status = (boolean) o.get("status"); }
if (o.containsKey("msg")) }
assertFalse(status); List<Integer> idList = userList.stream().map(user -> user.getId().intValue()).collect(Collectors.toList());
else getMockData(delete("/admin/user/delete"), adminLogin(), idList).andDo(result -> {
assertTrue(status); Response<List<Map<String, Object>>> response = getResponse(result, USER_MODEL_LIST_TYPE);
}); assertEquals(SUCCESS.getCode(), response.getCode());
}); response.getResult().forEach(o -> {
// 判断响应数据中是否包含输入的id
} assertTrue(idList.contains((int) o.get("id")));
// 判断处理状态
@Test boolean status = (boolean) o.get("status");
public void updateInfoByAdmin() throws Exception { if (o.containsKey("msg"))
UserReq userReq = new UserReq(); assertFalse(status);
String email = randomStr(4) + "@celess.cn"; else
User user = new User(email, MD5Util.getMD5("123456789")); assertTrue(status);
userMapper.addUser(user); });
User userByDb = userMapper.findByEmail(email); });
userReq.setId(userByDb.getId());
userReq.setPwd(randomStr().substring(0, 10)); }
userReq.setDesc(randomStr());
userReq.setEmailStatus(new Random().nextBoolean()); @Test
userReq.setRole("admin"); public void updateInfoByAdmin() throws Exception {
userReq.setDisplayName(randomStr(4)); UserReq userReq = new UserReq();
userReq.setEmail(randomStr(5) + "@celess.cn"); String email = randomStr(4) + "@celess.cn";
getMockData(put("/admin/user"), adminLogin(), userReq).andDo(result -> { User user = new User(email, MD5Util.getMD5("123456789"));
Response<UserModel> response = getResponse(result, USER_MODEL_TYPE); userMapper.addUser(user);
assertEquals(SUCCESS.getCode(), response.getCode()); User userByDb = userMapper.findByEmail(email);
UserModel userModel = response.getResult(); userReq.setId(userByDb.getId());
assertEquals(userReq.getId(), userModel.getId()); userReq.setPwd(randomStr().substring(0, 10));
assertEquals(userReq.getRole(), userModel.getRole()); userReq.setDesc(randomStr());
assertEquals(userReq.getEmail(), userModel.getEmail()); userReq.setEmailStatus(new Random().nextBoolean());
assertEquals(userReq.getDesc(), userModel.getDesc()); userReq.setRole("admin");
assertEquals(userReq.getDisplayName(), userModel.getDisplayName()); userReq.setDisplayName(randomStr(4));
}); userReq.setEmail(randomStr(5) + "@celess.cn");
} getMockData(put("/admin/user"), adminLogin(), userReq).andDo(result -> {
Response<UserModel> response = getResponse(result, USER_MODEL_TYPE);
@Test assertEquals(SUCCESS.getCode(), response.getCode());
public void getAllUser() throws Exception { UserModel userModel = response.getResult();
getMockData(get("/admin/users?page=1&count=10"), adminLogin()).andDo(result -> { assertEquals(userReq.getId(), userModel.getId());
Response<PageData<UserModel>> response = getResponse(result, USER_MODEL_PAGE_TYPE); assertEquals(userReq.getRole(), userModel.getRole());
assertEquals(SUCCESS.getCode(), response.getCode()); assertEquals(userReq.getEmail(), userModel.getEmail());
// 结果集非空 assertEquals(userReq.getDesc(), userModel.getDesc());
assertNotNull(response.getResult()); assertEquals(userReq.getDisplayName(), userModel.getDisplayName());
// 判断pageInfo是否包装完全 });
PageData<UserModel> pageData = response.getResult(); }
assertNotEquals(0, pageData.getTotal());
assertEquals(1, pageData.getPageNum()); @Test
assertEquals(10, pageData.getPageSize()); public void getAllUser() throws Exception {
// 内容完整 getMockData(get("/admin/users?page=1&count=10"), adminLogin()).andDo(result -> {
for (UserModel u : pageData.getList()) { Response<PageData<UserModel>> response = getResponse(result, USER_MODEL_PAGE_TYPE);
assertNotNull(u.getId()); assertEquals(SUCCESS.getCode(), response.getCode());
assertNotNull(u.getEmail()); // 结果集非空
assertNotNull(u.getRole()); assertNotNull(response.getResult());
assertNotNull(u.getEmailStatus()); // 判断pageInfo是否包装完全
assertNotNull(u.getDisplayName()); PageData<UserModel> pageData = response.getResult();
} assertNotEquals(0, pageData.getTotal());
}); assertEquals(1, pageData.getPageNum());
} assertEquals(10, pageData.getPageSize());
// 内容完整
@Test for (UserModel u : pageData.getList()) {
public void getEmailStatus() throws Exception { assertNotNull(u.getId());
String email = randomStr(4) + "@celess.cn"; assertNotNull(u.getEmail());
getMockData(get("/emailStatus/" + email)).andDo(result -> assertFalse((Boolean) getResponse(result, BOOLEAN_TYPE).getResult())); assertNotNull(u.getRole());
getMockData(get("/emailStatus/" + ADMIN_EMAIL)).andDo(result -> assertTrue((Boolean) getResponse(result, BOOLEAN_TYPE).getResult())); assertNotNull(u.getEmailStatus());
} assertNotNull(u.getDisplayName());
}
@Test });
public void setPwd() throws Exception { }
String email = randomStr(4) + "@celess.cn";
assertEquals(1, userMapper.addUser(new User(email, MD5Util.getMD5("1234567890")))); @Test
LoginReq req = new LoginReq(email, "1234567890", false); public void getEmailStatus() throws Exception {
String token = login(req); String email = randomStr(4) + "@celess.cn";
assertNotNull(token); getMockData(get("/emailStatus/" + email)).andDo(result -> assertFalse((Boolean) getResponse(result, BOOLEAN_TYPE).getResult()));
MultiValueMap<String, String> param = new LinkedMultiValueMap<String, String>(); getMockData(get("/emailStatus/" + ADMIN_EMAIL)).andDo(result -> assertTrue((Boolean) getResponse(result, BOOLEAN_TYPE).getResult()));
param.add("pwd", "1234567890"); }
param.add("newPwd", "aaabbbccc");
param.add("confirmPwd", "aaabbbccc"); @Test
getMockData(post("/user/setPwd").params(param), token).andDo(result -> { public void setPwd() throws Exception {
assertEquals(SUCCESS.getCode(), getResponse(result).getCode()); String email = randomStr(4) + "@celess.cn";
assertEquals(MD5Util.getMD5("aaabbbccc"), userMapper.getPwd(email)); assertEquals(1, userMapper.addUser(new User(email, MD5Util.getMD5("1234567890"))));
}); LoginReq req = new LoginReq(email, "1234567890", false);
} String token = login(req);
assertNotNull(token);
MultiValueMap<String, String> param = new LinkedMultiValueMap<String, String>();
param.add("pwd", "1234567890");
param.add("newPwd", "aaabbbccc");
param.add("confirmPwd", "aaabbbccc");
getMockData(post("/user/setPwd").params(param), token).andDo(result -> {
assertEquals(SUCCESS.getCode(), getResponse(result).getCode());
assertEquals(MD5Util.getMD5("aaabbbccc"), userMapper.getPwd(email));
});
}
} }

View File

@@ -35,7 +35,7 @@ public class PartnerMapperTest extends BaseTest {
partnerSite.setIconPath(randomStr(5)); partnerSite.setIconPath(randomStr(5));
partnerSite.setDesc(randomStr(5)); partnerSite.setDesc(randomStr(5));
partnerSite.setOpen(false); partnerSite.setOpen(false);
partnerSite.setUrl("www.celess.cn?random=" + randomStr(4)); partnerSite.setUrl("www.celess.cn/?random=" + randomStr(4));
assertEquals(1, partnerMapper.update(partnerSite)); 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());
}
}