Compare commits
40 Commits
v2.4.0
...
feat-multl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d462cc876 | ||
|
|
ec96a787ef | ||
|
|
91de56cb32 | ||
|
|
e2a3fb6a6c | ||
|
|
49ff1865bb | ||
|
|
b920034ad6 | ||
|
|
76f3d16e09 | ||
|
|
9dafc6d5a7 | ||
|
|
ec693da079 | ||
|
|
58498ef225 | ||
|
|
c56a3eaf83 | ||
|
|
e0abfb7d70 | ||
|
|
96cb2dcee4 | ||
|
|
e39763ad0c | ||
|
|
a3edc00a03 | ||
|
|
c0687b4776 | ||
|
|
b3b3a7a908 | ||
|
|
56efdc44d7 | ||
|
|
e4684e6150 | ||
|
|
65d65221e8 | ||
|
|
47df223655 | ||
|
|
fa95f2f69e | ||
|
|
5598804ddc | ||
|
|
ed7d18d491 | ||
|
|
2fbe030da9 | ||
|
|
5f3cbece7b | ||
|
|
4942daf900 | ||
|
|
9f070169b4 | ||
|
|
4fa114eb1e | ||
|
|
431ce8ac28 | ||
|
|
49000e9ee6 | ||
|
|
19068ff14d | ||
|
|
3d0253a35a | ||
|
|
0283bd11dc | ||
|
|
60347c7629 | ||
|
|
8de0cbded8 | ||
|
|
0ba7e06695 | ||
|
|
512d04f3e9 | ||
|
|
ada8f67171 | ||
|
|
81ee71adf1 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -14,6 +14,8 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
KEY: ${{ secrets.WEB_HOOK_ACCESS_KEY }}
|
KEY: ${{ secrets.WEB_HOOK_ACCESS_KEY }}
|
||||||
|
QINIU_ACCESSKEY: ${{ secrets.QINIU_ACCESSKEY }}
|
||||||
|
QINIU_SECRETKEY: ${{ secrets.QINIU_SECRETKEY }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|||||||
71
.github/workflows/codeql-analysis.yml
vendored
Normal file
71
.github/workflows/codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# For most projects, this workflow file will not need changing; you simply need
|
||||||
|
# to commit it to your repository.
|
||||||
|
#
|
||||||
|
# You may wish to alter this file to override the set of languages analyzed,
|
||||||
|
# or to provide custom queries or build logic.
|
||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [master]
|
||||||
|
schedule:
|
||||||
|
- cron: '0 14 * * 2'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
# Override automatic language detection by changing the below list
|
||||||
|
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
|
||||||
|
language: ['java']
|
||||||
|
# Learn more...
|
||||||
|
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
# We must fetch at least the immediate parents so that if this is
|
||||||
|
# a pull request then we can checkout the head.
|
||||||
|
fetch-depth: 2
|
||||||
|
|
||||||
|
# If this run was triggered by a pull request event, then checkout
|
||||||
|
# the head of the pull request instead of the merge commit.
|
||||||
|
- run: git checkout HEAD^2
|
||||||
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v1
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
# By default, queries listed here will override any specified in a config file.
|
||||||
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
|
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||||
|
|
||||||
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
|
- name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v1
|
||||||
|
|
||||||
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
|
# 📚 https://git.io/JvXDl
|
||||||
|
|
||||||
|
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||||
|
# and modify them (or add more) to build your code if your project
|
||||||
|
# uses a compiled language
|
||||||
|
|
||||||
|
#- run: |
|
||||||
|
# make bootstrap
|
||||||
|
# make release
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v1
|
||||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@@ -12,9 +12,9 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# env:
|
env:
|
||||||
# APPLICATION_PROPERTIES_TEST: ${{ secrets.APPLICATION_PROPERTIES_TEST }}
|
QINIU_ACCESSKEY: ${{ secrets.QINIU_ACCESSKEY }}
|
||||||
# APPLICATION_PROPERTIES_PROD: ${{ secrets.APPLICATION_PROPERTIES_PROD }}
|
QINIU_SECRETKEY: ${{ secrets.QINIU_SECRETKEY }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|||||||
299
doc/API.md
299
doc/API.md
@@ -1411,6 +1411,78 @@
|
|||||||
| 401 | Unauthorized ||
|
| 401 | Unauthorized ||
|
||||||
| 403 | Forbidden ||
|
| 403 | Forbidden ||
|
||||||
| 404 | Not Found ||
|
| 404 | Not Found ||
|
||||||
|
## fileUpload
|
||||||
|
|
||||||
|
|
||||||
|
**接口描述**:
|
||||||
|
|
||||||
|
|
||||||
|
**接口地址**:`/fileUpload`
|
||||||
|
|
||||||
|
|
||||||
|
**请求方式**:`POST`
|
||||||
|
|
||||||
|
|
||||||
|
**consumes**:`["application/json"]`
|
||||||
|
|
||||||
|
|
||||||
|
**produces**:`["*/*"]`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**请求参数**:
|
||||||
|
|
||||||
|
| 参数名称 | 参数说明 | in | 是否必须 | 数据类型 | schema |
|
||||||
|
| ------------ | -------------------------------- |-----------|--------|----|--- |
|
||||||
|
|file[]| file[] | formData | true |array | file |
|
||||||
|
|
||||||
|
**响应示例**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"msg": "",
|
||||||
|
"result": [
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应参数**:
|
||||||
|
|
||||||
|
|
||||||
|
| 参数名称 | 参数说明 | 类型 | schema |
|
||||||
|
| ------------ | -------------------|-------|----------- |
|
||||||
|
|code| |integer(int32) | integer(int32) |
|
||||||
|
|msg| |string | |
|
||||||
|
|result| |array | Map«string,object» |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**schema属性说明**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Map«string,object»**
|
||||||
|
|
||||||
|
| 参数名称 | 参数说明 | 类型 | schema |
|
||||||
|
| ------------ | ------------------|--------|----------- |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**响应状态**:
|
||||||
|
|
||||||
|
|
||||||
|
| 状态码 | 说明 | schema |
|
||||||
|
| ------------ | -------------------------------- |---------------------- |
|
||||||
|
| 200 | OK |Response«List«Map«string,object»»»|
|
||||||
|
| 201 | Created ||
|
||||||
|
| 401 | Unauthorized ||
|
||||||
|
| 403 | Forbidden ||
|
||||||
|
| 404 | Not Found ||
|
||||||
## headerInfo
|
## headerInfo
|
||||||
|
|
||||||
|
|
||||||
@@ -1623,6 +1695,231 @@
|
|||||||
| 401 | Unauthorized ||
|
| 401 | Unauthorized ||
|
||||||
| 403 | Forbidden ||
|
| 403 | Forbidden ||
|
||||||
| 404 | Not Found ||
|
| 404 | Not Found ||
|
||||||
|
# config-controller
|
||||||
|
|
||||||
|
## getConfiguration
|
||||||
|
|
||||||
|
|
||||||
|
**接口描述**:
|
||||||
|
|
||||||
|
|
||||||
|
**接口地址**:`/admin/config`
|
||||||
|
|
||||||
|
|
||||||
|
**请求方式**:`GET`
|
||||||
|
|
||||||
|
|
||||||
|
**consumes**:``
|
||||||
|
|
||||||
|
|
||||||
|
**produces**:`["*/*"]`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**请求参数**:
|
||||||
|
暂无
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**响应示例**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"msg": "",
|
||||||
|
"result": [
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"name": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应参数**:
|
||||||
|
|
||||||
|
|
||||||
|
| 参数名称 | 参数说明 | 类型 | schema |
|
||||||
|
| ------------ | -------------------|-------|----------- |
|
||||||
|
|code| |integer(int32) | integer(int32) |
|
||||||
|
|msg| |string | |
|
||||||
|
|result| |array | Config |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**schema属性说明**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Config**
|
||||||
|
|
||||||
|
| 参数名称 | 参数说明 | 类型 | schema |
|
||||||
|
| ------------ | ------------------|--------|----------- |
|
||||||
|
|id | |integer(int32) | |
|
||||||
|
|name | |string | |
|
||||||
|
|value | |string | |
|
||||||
|
|
||||||
|
**响应状态**:
|
||||||
|
|
||||||
|
|
||||||
|
| 状态码 | 说明 | schema |
|
||||||
|
| ------------ | -------------------------------- |---------------------- |
|
||||||
|
| 200 | OK |Response«List«Config»»|
|
||||||
|
| 401 | Unauthorized ||
|
||||||
|
| 403 | Forbidden ||
|
||||||
|
| 404 | Not Found ||
|
||||||
|
## addConfiguration
|
||||||
|
|
||||||
|
|
||||||
|
**接口描述**:
|
||||||
|
|
||||||
|
|
||||||
|
**接口地址**:`/admin/config`
|
||||||
|
|
||||||
|
|
||||||
|
**请求方式**:`POST`
|
||||||
|
|
||||||
|
|
||||||
|
**consumes**:`["application/json"]`
|
||||||
|
|
||||||
|
|
||||||
|
**produces**:`["*/*"]`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**请求参数**:
|
||||||
|
|
||||||
|
| 参数名称 | 参数说明 | in | 是否必须 | 数据类型 | schema |
|
||||||
|
| ------------ | -------------------------------- |-----------|--------|----|--- |
|
||||||
|
|configs| configs | query | false |array | Config |
|
||||||
|
|
||||||
|
**响应示例**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"msg": "",
|
||||||
|
"result": [
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"name": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应参数**:
|
||||||
|
|
||||||
|
|
||||||
|
| 参数名称 | 参数说明 | 类型 | schema |
|
||||||
|
| ------------ | -------------------|-------|----------- |
|
||||||
|
|code| |integer(int32) | integer(int32) |
|
||||||
|
|msg| |string | |
|
||||||
|
|result| |array | Config |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**schema属性说明**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Config**
|
||||||
|
|
||||||
|
| 参数名称 | 参数说明 | 类型 | schema |
|
||||||
|
| ------------ | ------------------|--------|----------- |
|
||||||
|
|id | |integer(int32) | |
|
||||||
|
|name | |string | |
|
||||||
|
|value | |string | |
|
||||||
|
|
||||||
|
**响应状态**:
|
||||||
|
|
||||||
|
|
||||||
|
| 状态码 | 说明 | schema |
|
||||||
|
| ------------ | -------------------------------- |---------------------- |
|
||||||
|
| 200 | OK |Response«List«Config»»|
|
||||||
|
| 201 | Created ||
|
||||||
|
| 401 | Unauthorized ||
|
||||||
|
| 403 | Forbidden ||
|
||||||
|
| 404 | Not Found ||
|
||||||
|
## updateConfiguration
|
||||||
|
|
||||||
|
|
||||||
|
**接口描述**:
|
||||||
|
|
||||||
|
|
||||||
|
**接口地址**:`/admin/config`
|
||||||
|
|
||||||
|
|
||||||
|
**请求方式**:`PUT`
|
||||||
|
|
||||||
|
|
||||||
|
**consumes**:`["application/json"]`
|
||||||
|
|
||||||
|
|
||||||
|
**produces**:`["*/*"]`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**请求参数**:
|
||||||
|
|
||||||
|
| 参数名称 | 参数说明 | in | 是否必须 | 数据类型 | schema |
|
||||||
|
| ------------ | -------------------------------- |-----------|--------|----|--- |
|
||||||
|
|configs| configs | query | false |array | Config |
|
||||||
|
|
||||||
|
**响应示例**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"msg": "",
|
||||||
|
"result": [
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"name": "",
|
||||||
|
"value": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应参数**:
|
||||||
|
|
||||||
|
|
||||||
|
| 参数名称 | 参数说明 | 类型 | schema |
|
||||||
|
| ------------ | -------------------|-------|----------- |
|
||||||
|
|code| |integer(int32) | integer(int32) |
|
||||||
|
|msg| |string | |
|
||||||
|
|result| |array | Config |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**schema属性说明**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Config**
|
||||||
|
|
||||||
|
| 参数名称 | 参数说明 | 类型 | schema |
|
||||||
|
| ------------ | ------------------|--------|----------- |
|
||||||
|
|id | |integer(int32) | |
|
||||||
|
|name | |string | |
|
||||||
|
|value | |string | |
|
||||||
|
|
||||||
|
**响应状态**:
|
||||||
|
|
||||||
|
|
||||||
|
| 状态码 | 说明 | schema |
|
||||||
|
| ------------ | -------------------------------- |---------------------- |
|
||||||
|
| 200 | OK |Response«List«Config»»|
|
||||||
|
| 201 | Created ||
|
||||||
|
| 401 | Unauthorized ||
|
||||||
|
| 403 | Forbidden ||
|
||||||
|
| 404 | Not Found ||
|
||||||
# links-controller
|
# links-controller
|
||||||
|
|
||||||
## all
|
## all
|
||||||
@@ -1649,8 +1946,8 @@
|
|||||||
| 参数名称 | 参数说明 | in | 是否必须 | 数据类型 | schema |
|
| 参数名称 | 参数说明 | in | 是否必须 | 数据类型 | schema |
|
||||||
| ------------ | -------------------------------- |-----------|--------|----|--- |
|
| ------------ | -------------------------------- |-----------|--------|----|--- |
|
||||||
|count| count | query | true |integer | |
|
|count| count | query | true |integer | |
|
||||||
|page| page | query | true |integer | |
|
|
||||||
|deleted| deleted | query | false |boolean | |
|
|deleted| deleted | query | false |boolean | |
|
||||||
|
|page| page | query | true |integer | |
|
||||||
|
|
||||||
**响应示例**:
|
**响应示例**:
|
||||||
|
|
||||||
|
|||||||
2
pom.xml
2
pom.xml
@@ -131,7 +131,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.12</version>
|
<version>4.13.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- JJwt -->
|
<!-- JJwt -->
|
||||||
|
|||||||
@@ -1,20 +1,34 @@
|
|||||||
package cn.celess.blog;
|
package cn.celess.blog;
|
||||||
|
|
||||||
import org.mybatis.spring.annotation.MapperScan;
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.slf4j.Logger;
|
import org.springframework.boot.ApplicationArguments;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zheng
|
||||||
|
*/
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@EnableAsync
|
@EnableAsync
|
||||||
@MapperScan("cn.celess.blog.mapper")
|
@MapperScan("cn.celess.blog.mapper")
|
||||||
public class BlogApplication {
|
public class BlogApplication {
|
||||||
public static final Logger logger = LoggerFactory.getLogger(BlogApplication.class);
|
public static ConfigurableApplicationContext context;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(BlogApplication.class, args);
|
context = SpringApplication.run(BlogApplication.class, args);
|
||||||
logger.info("启动完成!");
|
}
|
||||||
|
|
||||||
|
public static void restart() {
|
||||||
|
ApplicationArguments args = context.getBean(ApplicationArguments.class);
|
||||||
|
|
||||||
|
Thread thread = new Thread(() -> {
|
||||||
|
context.close();
|
||||||
|
context = SpringApplication.run(BlogApplication.class, args.getSourceArgs());
|
||||||
|
});
|
||||||
|
thread.setDaemon(false);
|
||||||
|
thread.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package cn.celess.blog.configuration;
|
||||||
|
|
||||||
|
import cn.celess.blog.enmu.ConfigKeyEnum;
|
||||||
|
import cn.celess.blog.entity.Config;
|
||||||
|
import cn.celess.blog.mapper.ConfigMapper;
|
||||||
|
import cn.celess.blog.service.fileserviceimpl.LocalFileServiceImpl;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.boot.ApplicationRunner;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2020/10/16 16:00
|
||||||
|
* @desc :
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class ApplicationListener implements ApplicationRunner {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ConfigMapper configMapper;
|
||||||
|
@Autowired
|
||||||
|
Environment env;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(ApplicationArguments args) throws Exception {
|
||||||
|
log.info("博客启动!");
|
||||||
|
// 设置初始值
|
||||||
|
setProperty(ConfigKeyEnum.FILE_QINIU_SECRET_KEY);
|
||||||
|
setProperty(ConfigKeyEnum.FILE_QINIU_ACCESS_KEY);
|
||||||
|
setProperty(ConfigKeyEnum.FILE_QINIU_BUCKET);
|
||||||
|
setProperty(ConfigKeyEnum.BLOG_FILE_PATH);
|
||||||
|
|
||||||
|
List<Config> configurations = configMapper.getConfigurations()
|
||||||
|
.stream()
|
||||||
|
.filter(config -> config.getValue() != null && !"".equals(config.getValue()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
configurations.forEach(config -> System.setProperty(config.getName(), config.getValue()));
|
||||||
|
log.debug("注入配置成功 {}", configurations.stream().map(Config::getName).collect(Collectors.toList()));
|
||||||
|
File path = new File(LocalFileServiceImpl.getPath(System.getProperty(ConfigKeyEnum.BLOG_FILE_PATH.getKey())));
|
||||||
|
if (!path.exists() && !path.mkdirs()) {
|
||||||
|
throw new IllegalAccessException("创建数据目录失败==>" + path.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setProperty(ConfigKeyEnum e) {
|
||||||
|
String property = env.getProperty(e.getKey());
|
||||||
|
if (property != null) {
|
||||||
|
System.setProperty(e.getKey(), property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,41 +1,81 @@
|
|||||||
package cn.celess.blog.configuration;
|
package cn.celess.blog.configuration;
|
||||||
|
|
||||||
import com.alibaba.druid.pool.DruidDataSource;
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author : xiaohai
|
* @author : xiaohai
|
||||||
* @date : 2019/03/28 14:26
|
* @date : 2019/03/28 14:26
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Configuration
|
@Configuration
|
||||||
public class DruidConfig {
|
public class DruidConfig {
|
||||||
@Value("${spring.datasource.url}")
|
|
||||||
private String dbUrl;
|
|
||||||
|
|
||||||
@Value("${spring.datasource.username}")
|
@Autowired
|
||||||
private String username;
|
Environment env;
|
||||||
|
|
||||||
@Value("${spring.datasource.password}")
|
public static final String DB_CONFIG_PATH = System.getProperty("user.home") + "/blog/application.properties";
|
||||||
private String password;
|
public static final String DB_CONFIG_URL_PREFIX = "spring.datasource.url";
|
||||||
|
public static final String DB_CONFIG_USERNAME_PREFIX = "spring.datasource.username";
|
||||||
@Value("${spring.datasource.driver-class-name}")
|
public static final String DB_CONFIG_PASSWORD_PREFIX = "spring.datasource.password";
|
||||||
private String driverClassName;
|
public static final String DB_CONFIG_DRIVER_CLASS_NAME_PREFIX = "spring.datasource.driver-class-name";
|
||||||
|
public static final String TEST_PROFILES = "test";
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public DruidDataSource druidDataSource() {
|
public DruidDataSource initDataSource() throws IOException {
|
||||||
DruidDataSource dataSource = new DruidDataSource();
|
DruidDataSource dataSource;
|
||||||
dataSource.setDriverClassName(driverClassName);
|
File file = new File(DB_CONFIG_PATH);
|
||||||
// 数据库基本信息
|
if (file.exists() && !Arrays.asList(env.getActiveProfiles()).contains(TEST_PROFILES)) {
|
||||||
dataSource.setUrl(dbUrl);
|
log.debug("从文件中获取数据库配置");
|
||||||
dataSource.setUsername(username);
|
dataSource = readConfigFromFile(file);
|
||||||
dataSource.setPassword(password);
|
} else {
|
||||||
|
log.debug("默认数据库配置");
|
||||||
// 数据库连接池配置
|
dataSource = defaultDruidSource();
|
||||||
|
}
|
||||||
dataSource.setInitialSize(10);
|
dataSource.setInitialSize(10);
|
||||||
dataSource.setMinIdle(10);
|
dataSource.setMinIdle(10);
|
||||||
dataSource.setMaxActive(100);
|
dataSource.setMaxActive(100);
|
||||||
|
dataSource.setValidationQuery("select 1");
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DruidDataSource readConfigFromFile(File file) throws IOException {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
FileInputStream fis = new FileInputStream(file);
|
||||||
|
properties.load(fis);
|
||||||
|
fis.close();
|
||||||
|
String url = properties.getProperty(DB_CONFIG_URL_PREFIX, null);
|
||||||
|
String username = properties.getProperty(DB_CONFIG_USERNAME_PREFIX, null);
|
||||||
|
String password = properties.getProperty(DB_CONFIG_PASSWORD_PREFIX, null);
|
||||||
|
String className = properties.getProperty(DB_CONFIG_DRIVER_CLASS_NAME_PREFIX, null);
|
||||||
|
if (url == null || username == null || password == null || className == null) {
|
||||||
|
return defaultDruidSource();
|
||||||
|
}
|
||||||
|
DruidDataSource dataSource = new DruidDataSource();
|
||||||
|
dataSource.setDriverClassName(className);
|
||||||
|
dataSource.setUrl(url);
|
||||||
|
dataSource.setUsername(username);
|
||||||
|
dataSource.setPassword(password);
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private DruidDataSource defaultDruidSource() {
|
||||||
|
DruidDataSource dataSource = new DruidDataSource();
|
||||||
|
dataSource.setDriverClassName(env.getProperty(DruidConfig.DB_CONFIG_DRIVER_CLASS_NAME_PREFIX));
|
||||||
|
dataSource.setUrl(env.getProperty(DruidConfig.DB_CONFIG_URL_PREFIX));
|
||||||
|
dataSource.setUsername(env.getProperty(DruidConfig.DB_CONFIG_USERNAME_PREFIX));
|
||||||
|
dataSource.setPassword(env.getProperty(DruidConfig.DB_CONFIG_PASSWORD_PREFIX));
|
||||||
return dataSource;
|
return dataSource;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package cn.celess.blog.controller;
|
|||||||
|
|
||||||
import cn.celess.blog.enmu.ResponseEnum;
|
import cn.celess.blog.enmu.ResponseEnum;
|
||||||
import cn.celess.blog.entity.Response;
|
import cn.celess.blog.entity.Response;
|
||||||
import cn.celess.blog.entity.model.QiniuResponse;
|
import cn.celess.blog.entity.model.FileResponse;
|
||||||
import cn.celess.blog.exception.MyException;
|
import cn.celess.blog.exception.MyException;
|
||||||
import cn.celess.blog.service.CountService;
|
import cn.celess.blog.service.CountService;
|
||||||
import cn.celess.blog.service.QiniuService;
|
import cn.celess.blog.service.FileService;
|
||||||
import cn.celess.blog.util.HttpUtil;
|
import cn.celess.blog.util.HttpUtil;
|
||||||
import cn.celess.blog.util.RedisUserUtil;
|
import cn.celess.blog.util.RedisUserUtil;
|
||||||
import cn.celess.blog.util.RedisUtil;
|
import cn.celess.blog.util.RedisUtil;
|
||||||
@@ -42,7 +42,7 @@ public class CommonController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
CountService countService;
|
CountService countService;
|
||||||
@Autowired
|
@Autowired
|
||||||
QiniuService qiniuService;
|
FileService fileService;
|
||||||
@Autowired
|
@Autowired
|
||||||
RedisUtil redisUtil;
|
RedisUtil redisUtil;
|
||||||
@Autowired
|
@Autowired
|
||||||
@@ -161,10 +161,10 @@ public class CommonController {
|
|||||||
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())) {
|
||||||
QiniuResponse qiniuResponse = qiniuService.uploadFile(file.getInputStream(), "img_" + System.currentTimeMillis() + mime);
|
FileResponse fileResponse = fileService.getFileManager().uploadFile(file.getInputStream(), "img_" + System.currentTimeMillis() + mime);
|
||||||
map.put("success", 1);
|
map.put("success", 1);
|
||||||
map.put("message", "上传成功");
|
map.put("message", "上传成功");
|
||||||
map.put("url", "http://cdn.celess.cn/" + qiniuResponse.key);
|
map.put("url", "http://cdn.celess.cn/" + fileResponse.key);
|
||||||
response.getWriter().println(mapper.writeValueAsString(map));
|
response.getWriter().println(mapper.writeValueAsString(map));
|
||||||
redisUtil.setEx(request.getRemoteAddr() + "-ImgUploadTimes", uploadTimes + 1 + "", 2, TimeUnit.HOURS);
|
redisUtil.setEx(request.getRemoteAddr() + "-ImgUploadTimes", uploadTimes + 1 + "", 2, TimeUnit.HOURS);
|
||||||
return;
|
return;
|
||||||
@@ -208,12 +208,12 @@ public class CommonController {
|
|||||||
assert fileName != null;
|
assert fileName != null;
|
||||||
String mime = fileName.substring(fileName.lastIndexOf("."));
|
String mime = fileName.substring(fileName.lastIndexOf("."));
|
||||||
String name = fileName.replace(mime, "").replaceAll(" ", "");
|
String name = fileName.replace(mime, "").replaceAll(" ", "");
|
||||||
QiniuResponse qiniuResponse = qiniuService.uploadFile(file.getInputStream(), "file_" + name + '_' + System.currentTimeMillis() + mime);
|
FileResponse fileResponse = fileService.getFileManager().uploadFile(file.getInputStream(), "file_" + name + '_' + System.currentTimeMillis() + mime);
|
||||||
resp.put("originalFilename", fileName);
|
resp.put("originalFilename", fileName);
|
||||||
resp.put("success", qiniuResponse != null);
|
resp.put("success", fileResponse != null);
|
||||||
if (qiniuResponse != null) {
|
if (fileResponse != null) {
|
||||||
resp.put("host", "http://cdn.celess.cn/");
|
resp.put("host", "http://cdn.celess.cn/");
|
||||||
resp.put("path", qiniuResponse.key);
|
resp.put("path", fileResponse.key);
|
||||||
}
|
}
|
||||||
result.add(resp);
|
result.add(resp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package cn.celess.blog.controller;
|
||||||
|
|
||||||
|
import cn.celess.blog.entity.Config;
|
||||||
|
import cn.celess.blog.entity.Response;
|
||||||
|
import cn.celess.blog.mapper.ConfigMapper;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2020/10/16 20:56
|
||||||
|
* @desc : 配置管理接口
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class ConfigController {
|
||||||
|
@Autowired
|
||||||
|
ConfigMapper configMapper;
|
||||||
|
|
||||||
|
@GetMapping("/admin/config")
|
||||||
|
public Response<List<Config>> getConfiguration() {
|
||||||
|
return Response.success(configMapper.getConfigurations());
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/admin/config")
|
||||||
|
public Response<List<Config>> updateConfiguration(@RequestBody List<Config> configs) {
|
||||||
|
configs.forEach(config -> configMapper.updateConfiguration(config));
|
||||||
|
configs.forEach(config -> System.setProperty(config.getName(), config.getValue()));
|
||||||
|
return Response.success(configMapper.getConfigurations());
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/admin/config")
|
||||||
|
public Response<List<Config>> addConfiguration(@RequestBody List<Config> configs) {
|
||||||
|
configs.forEach(config -> configMapper.addConfiguration(config));
|
||||||
|
configs.forEach(config -> System.setProperty(config.getName(), config.getValue()));
|
||||||
|
return Response.success(configMapper.getConfigurations());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package cn.celess.blog.controller;
|
||||||
|
|
||||||
|
import cn.celess.blog.BlogApplication;
|
||||||
|
import cn.celess.blog.enmu.ConfigKeyEnum;
|
||||||
|
import cn.celess.blog.enmu.ResponseEnum;
|
||||||
|
import cn.celess.blog.entity.Config;
|
||||||
|
import cn.celess.blog.entity.InstallParam;
|
||||||
|
import cn.celess.blog.entity.Response;
|
||||||
|
import cn.celess.blog.exception.MyException;
|
||||||
|
import cn.celess.blog.mapper.ConfigMapper;
|
||||||
|
import cn.celess.blog.service.InstallService;
|
||||||
|
import cn.celess.blog.util.RegexUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2020/10/18 15:36
|
||||||
|
* @desc :
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Controller
|
||||||
|
@Validated
|
||||||
|
public class InstallController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
InstallService installService;
|
||||||
|
@Autowired
|
||||||
|
ConfigMapper configMapper;
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/is_install")
|
||||||
|
@ResponseBody
|
||||||
|
public Response<Map<String, Object>> isInstall() {
|
||||||
|
Map<String, Object> install = installService.isInstall();
|
||||||
|
return Response.success(install);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/install")
|
||||||
|
@ResponseBody
|
||||||
|
public Response<Object> install(@Valid @RequestBody InstallParam installParam) {
|
||||||
|
if (!RegexUtil.emailMatch(installParam.getEmail())) {
|
||||||
|
throw new MyException(ResponseEnum.PARAMETERS_EMAIL_ERROR);
|
||||||
|
}
|
||||||
|
if (!RegexUtil.pwdMatch(installParam.getPassword())) {
|
||||||
|
throw new MyException(ResponseEnum.PARAMETERS_PWD_ERROR);
|
||||||
|
}
|
||||||
|
return Response.success(installService.install(installParam));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/default_config")
|
||||||
|
@ResponseBody
|
||||||
|
public Response<String> defaultConfig() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/install")
|
||||||
|
public String install() {
|
||||||
|
Config configuration = configMapper.getConfiguration(ConfigKeyEnum.BLOG_INSTALLED.getKey());
|
||||||
|
if (Boolean.parseBoolean(configuration.getValue())) {
|
||||||
|
return "index.html";
|
||||||
|
}
|
||||||
|
log.info("博客第一次运行,还未安装");
|
||||||
|
return "install.html";
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/main/java/cn/celess/blog/enmu/ConfigKeyEnum.java
Normal file
37
src/main/java/cn/celess/blog/enmu/ConfigKeyEnum.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package cn.celess.blog.enmu;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2020/10/16 16:41
|
||||||
|
* @desc :
|
||||||
|
*/
|
||||||
|
public enum ConfigKeyEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 枚举
|
||||||
|
*/
|
||||||
|
FILE_TYPE("file.type"),
|
||||||
|
FILE_QINIU_ACCESS_KEY("file.qiniu.accessKey"),
|
||||||
|
FILE_QINIU_SECRET_KEY("file.qiniu.secretKey"),
|
||||||
|
FILE_QINIU_BUCKET("file.qiniu.bucket"),
|
||||||
|
FILE_LOCAL_DIRECTORY_PATH("file.local.directoryPath"),
|
||||||
|
BLOG_FILE_PATH("blog.file.path"),
|
||||||
|
BLOG_INSTALLED("blog.installed"),
|
||||||
|
DB_TYPE("db.type"),
|
||||||
|
DB_URL("spring.datasource.url"),
|
||||||
|
DB_USERNAME("spring.datasource.username"),
|
||||||
|
DB_PASSWORD("spring.datasource.password"),
|
||||||
|
DB_DRIVER_CLASS_NAME("spring.datasource.driver-class-name"),
|
||||||
|
BLOG_DB_PATH("blog.db.path");
|
||||||
|
|
||||||
|
|
||||||
|
private final String key;
|
||||||
|
|
||||||
|
ConfigKeyEnum(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/main/java/cn/celess/blog/entity/Config.java
Normal file
26
src/main/java/cn/celess/blog/entity/Config.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package cn.celess.blog.entity;
|
||||||
|
|
||||||
|
import cn.celess.blog.enmu.ConfigKeyEnum;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2020/10/16 15:24
|
||||||
|
* @desc :
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Config {
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public Config(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Config(ConfigKeyEnum e) {
|
||||||
|
this.name = e.getKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/main/java/cn/celess/blog/entity/InstallParam.java
Normal file
38
src/main/java/cn/celess/blog/entity/InstallParam.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package cn.celess.blog.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2020/10/18 14:52
|
||||||
|
* @desc :
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class InstallParam {
|
||||||
|
@NotBlank(message = "数据库类型不可为空")
|
||||||
|
private String dbType;
|
||||||
|
|
||||||
|
@NotBlank(message = "数据库主机不可为空")
|
||||||
|
private String dbHost;
|
||||||
|
|
||||||
|
@NotBlank(message = "数据库名称不可为空")
|
||||||
|
private String dbName;
|
||||||
|
|
||||||
|
@NotBlank(message = "数据库用户名不可为空")
|
||||||
|
private String dbUsername;
|
||||||
|
|
||||||
|
@NotBlank(message = "数据库密码不可为空")
|
||||||
|
private String dbPassword;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* user 相关
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "用户邮箱地址不可为空")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@NotBlank(message = "用户密码不可为空")
|
||||||
|
private String password;
|
||||||
|
}
|
||||||
25
src/main/java/cn/celess/blog/entity/model/FileInfo.java
Normal file
25
src/main/java/cn/celess/blog/entity/model/FileInfo.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package cn.celess.blog.entity.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2020/10/15 22:16
|
||||||
|
* @desc :
|
||||||
|
*/
|
||||||
|
public class FileInfo {
|
||||||
|
/**
|
||||||
|
* 文件名
|
||||||
|
*/
|
||||||
|
public String key;
|
||||||
|
/**
|
||||||
|
* 文件hash值
|
||||||
|
*/
|
||||||
|
public String hash;
|
||||||
|
/**
|
||||||
|
* 文件大小,单位:字节
|
||||||
|
*/
|
||||||
|
public long size;
|
||||||
|
/**
|
||||||
|
* 文件上传时间,单位为:100纳秒
|
||||||
|
*/
|
||||||
|
public long uploadTime;
|
||||||
|
}
|
||||||
@@ -5,9 +5,9 @@ package cn.celess.blog.entity.model;
|
|||||||
* @author : xiaohai
|
* @author : xiaohai
|
||||||
* @date : 2019/04/21 22:43
|
* @date : 2019/04/21 22:43
|
||||||
*/
|
*/
|
||||||
public class QiniuResponse {
|
public class FileResponse {
|
||||||
public String key;
|
public String key;
|
||||||
public String hash;
|
public String hash;
|
||||||
public String bucket;
|
public String type;
|
||||||
public long fsize;
|
public long size;
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.mail.SimpleMailMessage;
|
import org.springframework.mail.SimpleMailMessage;
|
||||||
import org.springframework.validation.BindException;
|
import org.springframework.validation.BindException;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||||
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
@@ -18,6 +20,10 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||||||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.validation.ConstraintViolation;
|
||||||
|
import javax.validation.ConstraintViolationException;
|
||||||
|
import javax.validation.ValidationException;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author : xiaohai
|
* @author : xiaohai
|
||||||
@@ -41,27 +47,32 @@ public class ExceptionHandle {
|
|||||||
if (e instanceof MyException) {
|
if (e instanceof MyException) {
|
||||||
MyException exception = (MyException) e;
|
MyException exception = (MyException) e;
|
||||||
logger.debug("返回了自定义的exception,[code={},msg={},result={}]", exception.getCode(), e.getMessage(), exception.getResult());
|
logger.debug("返回了自定义的exception,[code={},msg={},result={}]", exception.getCode(), e.getMessage(), exception.getResult());
|
||||||
return new Response(exception.getCode(), e.getMessage(), exception.getResult());
|
return new Response<>(exception.getCode(), e.getMessage(), exception.getResult());
|
||||||
}
|
}
|
||||||
//请求路径不支持该方法
|
//请求路径不支持该方法
|
||||||
if (e instanceof HttpRequestMethodNotSupportedException) {
|
if (e instanceof HttpRequestMethodNotSupportedException) {
|
||||||
logger.debug("遇到请求路径与请求方法不匹配的请求,[msg={},path:{},method:{}]", e.getMessage(), request.getRequestURL(), request.getMethod());
|
logger.debug("遇到请求路径与请求方法不匹配的请求,[msg={},path:{},method:{}]", e.getMessage(), request.getRequestURL(), request.getMethod());
|
||||||
return new Response(ResponseEnum.ERROR.getCode(), e.getMessage(), null);
|
return new Response<>(ResponseEnum.ERROR.getCode(), e.getMessage(), null);
|
||||||
}
|
}
|
||||||
//数据输入类型不匹配
|
//数据输入类型不匹配
|
||||||
if (e instanceof MethodArgumentTypeMismatchException) {
|
if (e instanceof MethodArgumentTypeMismatchException) {
|
||||||
logger.debug("输入类型不匹配,[msg={}]", e.getMessage());
|
logger.debug("输入类型不匹配,[msg={}]", e.getMessage());
|
||||||
return new Response(ResponseEnum.PARAMETERS_ERROR.getCode(), "数据输入有问题,请修改后再访问", null);
|
return new Response<>(ResponseEnum.PARAMETERS_ERROR.getCode(), "数据输入有问题,请修改后再访问", null);
|
||||||
}
|
}
|
||||||
//数据验证失败
|
//数据验证失败
|
||||||
if (e instanceof BindException) {
|
if (e instanceof BindException) {
|
||||||
logger.debug("数据验证失败,[msg={}]", e.getMessage());
|
logger.debug("数据验证失败,[msg={}]", e.getMessage());
|
||||||
return new Response(ResponseEnum.PARAMETERS_ERROR.getCode(), "数据输入有问题,请修改", null);
|
return new Response<>(ResponseEnum.PARAMETERS_ERROR.getCode(), "数据输入有问题,请修改", null);
|
||||||
}
|
}
|
||||||
//数据输入不完整
|
//数据输入不完整
|
||||||
if (e instanceof MissingServletRequestParameterException) {
|
if (e instanceof MissingServletRequestParameterException) {
|
||||||
logger.debug("数据输入不完整,[msg={}]", e.getMessage());
|
logger.debug("数据输入不完整,[msg={}]", e.getMessage());
|
||||||
return new Response(ResponseEnum.PARAMETERS_ERROR.getCode(), "数据输入不完整,请检查", null);
|
return new Response<>(ResponseEnum.PARAMETERS_ERROR.getCode(), "数据输入不完整,请检查", null);
|
||||||
|
}
|
||||||
|
if (e instanceof MethodArgumentNotValidException) {
|
||||||
|
logger.debug("数据验证失败,[msg: {}]", e.getMessage());
|
||||||
|
BindingResult violations = ((MethodArgumentNotValidException) e).getBindingResult();
|
||||||
|
return new Response<>(ResponseEnum.PARAMETERS_ERROR.getCode(), violations.getAllErrors().get(0).getDefaultMessage(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 发送错误信息到邮箱
|
// 发送错误信息到邮箱
|
||||||
@@ -70,7 +81,7 @@ public class ExceptionHandle {
|
|||||||
sendMessage(e);
|
sendMessage(e);
|
||||||
}
|
}
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return new Response(ResponseEnum.ERROR.getCode(), "服务器出现错误,已记录", null);
|
return new Response<>(ResponseEnum.ERROR.getCode(), "服务器出现错误,已记录", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
55
src/main/java/cn/celess/blog/mapper/ConfigMapper.java
Normal file
55
src/main/java/cn/celess/blog/mapper/ConfigMapper.java
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package cn.celess.blog.mapper;
|
||||||
|
|
||||||
|
import cn.celess.blog.entity.Config;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2020/10/16 15:24
|
||||||
|
* @desc :
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
@Repository
|
||||||
|
public interface ConfigMapper {
|
||||||
|
/**
|
||||||
|
* 获取单个配置
|
||||||
|
*
|
||||||
|
* @param key 配置名
|
||||||
|
* @return 配置
|
||||||
|
*/
|
||||||
|
Config getConfiguration(String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新配置
|
||||||
|
*
|
||||||
|
* @param c 配置
|
||||||
|
* @return 改变数据行数
|
||||||
|
*/
|
||||||
|
int updateConfiguration(Config c);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有配置
|
||||||
|
*
|
||||||
|
* @return 所有配置
|
||||||
|
*/
|
||||||
|
List<Config> getConfigurations();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增配置
|
||||||
|
*
|
||||||
|
* @param c 配置
|
||||||
|
* @return 改变行数
|
||||||
|
*/
|
||||||
|
int addConfiguration(Config c);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除配置
|
||||||
|
*
|
||||||
|
* @param id 主键id
|
||||||
|
* @return 改变行数
|
||||||
|
*/
|
||||||
|
int deleteConfiguration(int id);
|
||||||
|
}
|
||||||
40
src/main/java/cn/celess/blog/service/FileManager.java
Normal file
40
src/main/java/cn/celess/blog/service/FileManager.java
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package cn.celess.blog.service;
|
||||||
|
|
||||||
|
import cn.celess.blog.entity.model.FileInfo;
|
||||||
|
import cn.celess.blog.entity.model.FileResponse;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2020/10/15 18:19
|
||||||
|
* @desc : 文件管理器 定义操作文件的方法
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public interface FileManager {
|
||||||
|
/**
|
||||||
|
* 上传文件到文件存储容器中
|
||||||
|
*
|
||||||
|
* @param is 文件流
|
||||||
|
* @param fileName 文件名
|
||||||
|
* @return FileResponse
|
||||||
|
*/
|
||||||
|
FileResponse uploadFile(InputStream is, String fileName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件列表
|
||||||
|
*
|
||||||
|
* @return 文件信息
|
||||||
|
*/
|
||||||
|
List<FileInfo> getFileList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除文件
|
||||||
|
*
|
||||||
|
* @param fileName 文件名
|
||||||
|
* @return 是否删除成功
|
||||||
|
*/
|
||||||
|
boolean deleteFile(String fileName);
|
||||||
|
}
|
||||||
18
src/main/java/cn/celess/blog/service/FileService.java
Normal file
18
src/main/java/cn/celess/blog/service/FileService.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package cn.celess.blog.service;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2019/04/25 18:15
|
||||||
|
*/
|
||||||
|
@Service("fileService")
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface FileService {
|
||||||
|
/**
|
||||||
|
* 获取文件管理器
|
||||||
|
*
|
||||||
|
* @return 文件管理器 可以操作文件
|
||||||
|
*/
|
||||||
|
FileManager getFileManager();
|
||||||
|
}
|
||||||
20
src/main/java/cn/celess/blog/service/InstallService.java
Normal file
20
src/main/java/cn/celess/blog/service/InstallService.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package cn.celess.blog.service;
|
||||||
|
|
||||||
|
import cn.celess.blog.entity.InstallParam;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2020/10/23 16:22
|
||||||
|
* @desc :
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public interface InstallService {
|
||||||
|
Map<String, Object> isInstall();
|
||||||
|
|
||||||
|
Map<String, Object> install(@NotNull InstallParam installParam);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package cn.celess.blog.service;
|
|
||||||
|
|
||||||
import cn.celess.blog.entity.model.QiniuResponse;
|
|
||||||
import com.qiniu.storage.model.FileInfo;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author : xiaohai
|
|
||||||
* @date : 2019/04/25 18:15
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public interface QiniuService {
|
|
||||||
/**
|
|
||||||
* 上传文件
|
|
||||||
*
|
|
||||||
* @param is InputStream流
|
|
||||||
* @param fileName 文件名
|
|
||||||
* @return 响应数据
|
|
||||||
*/
|
|
||||||
QiniuResponse uploadFile(InputStream is, String fileName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取文件列表
|
|
||||||
*
|
|
||||||
* @return 文件列表
|
|
||||||
*/
|
|
||||||
FileInfo[] getFileList();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package cn.celess.blog.service.fileserviceimpl;
|
||||||
|
|
||||||
|
import cn.celess.blog.enmu.ConfigKeyEnum;
|
||||||
|
import cn.celess.blog.service.FileManager;
|
||||||
|
import cn.celess.blog.service.FileService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2020/10/15 18:52
|
||||||
|
* @desc : 提供文件管理器的服务
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service("fileServiceImpl")
|
||||||
|
public class FileServiceImpl implements FileService {
|
||||||
|
@Resource(name = "qiniuFileServiceImpl")
|
||||||
|
FileManager qiniuFileManager;
|
||||||
|
|
||||||
|
@Resource(name = "localFileServiceImpl")
|
||||||
|
FileManager localFileServiceImpl;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileManager getFileManager() {
|
||||||
|
String property = System.getProperty(ConfigKeyEnum.FILE_TYPE.getKey());
|
||||||
|
log.info("获取到{}:{}", ConfigKeyEnum.FILE_TYPE.getKey(), property);
|
||||||
|
if ("qiniu".equals(property)){
|
||||||
|
return qiniuFileManager;
|
||||||
|
}else if ("local".equals(property)){
|
||||||
|
return localFileServiceImpl;
|
||||||
|
}
|
||||||
|
return localFileServiceImpl;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
package cn.celess.blog.service.fileserviceimpl;
|
||||||
|
|
||||||
|
import cn.celess.blog.enmu.ConfigKeyEnum;
|
||||||
|
import cn.celess.blog.entity.model.FileInfo;
|
||||||
|
import cn.celess.blog.entity.model.FileResponse;
|
||||||
|
import cn.celess.blog.service.FileManager;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2020/10/16 14:39
|
||||||
|
* @desc :
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service("localFileServiceImpl")
|
||||||
|
public class LocalFileServiceImpl implements FileManager {
|
||||||
|
private static String path = null;
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
@Override
|
||||||
|
public FileResponse uploadFile(InputStream is, String fileName) {
|
||||||
|
if (path == null) {
|
||||||
|
path = System.getProperty(ConfigKeyEnum.FILE_LOCAL_DIRECTORY_PATH.getKey());
|
||||||
|
}
|
||||||
|
// 判断文件夹是否存在
|
||||||
|
File directory = new File(getPath(path));
|
||||||
|
if (!directory.exists() && directory.mkdirs()) {
|
||||||
|
log.info("不存在文件夹,创建文件夹=>{}", directory.getAbsolutePath());
|
||||||
|
}
|
||||||
|
log.info("上传文件 {}", fileName);
|
||||||
|
// 存储文件
|
||||||
|
File file1 = new File(getPath(path) + File.separator + fileName);
|
||||||
|
FileOutputStream fos = new FileOutputStream(file1);
|
||||||
|
byte[] cache = new byte[1024 * 100];
|
||||||
|
int len = 0;
|
||||||
|
FileResponse fileResponse = new FileResponse();
|
||||||
|
while ((len = is.read(cache)) != -1) {
|
||||||
|
fileResponse.size += len;
|
||||||
|
fos.write(cache, 0, len);
|
||||||
|
}
|
||||||
|
fos.flush();
|
||||||
|
fos.close();
|
||||||
|
is.close();
|
||||||
|
fileResponse.key = URLEncoder.encode(fileName, "UTF-8");
|
||||||
|
fileResponse.type = "local";
|
||||||
|
return fileResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
@Override
|
||||||
|
public List<FileInfo> getFileList() {
|
||||||
|
if (path == null) {
|
||||||
|
path = System.getProperty(ConfigKeyEnum.FILE_LOCAL_DIRECTORY_PATH.getKey());
|
||||||
|
}
|
||||||
|
File file = new File(getPath(path));
|
||||||
|
File[] files = file.listFiles();
|
||||||
|
List<FileInfo> fileInfoList = new ArrayList<>();
|
||||||
|
if (files == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (File file1 : files) {
|
||||||
|
FileInfo fileInfo = new FileInfo();
|
||||||
|
fileInfo.key = URLEncoder.encode(file1.getName(), "UTF-8");
|
||||||
|
fileInfo.size = file1.length();
|
||||||
|
BasicFileAttributes basicFileAttributes = Files.readAttributes(file1.toPath(), BasicFileAttributes.class);
|
||||||
|
fileInfo.uploadTime = basicFileAttributes.creationTime().toMillis();
|
||||||
|
fileInfoList.add(fileInfo);
|
||||||
|
}
|
||||||
|
return fileInfoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteFile(String fileName) {
|
||||||
|
if (path == null) {
|
||||||
|
path = System.getProperty(ConfigKeyEnum.FILE_LOCAL_DIRECTORY_PATH.getKey());
|
||||||
|
}
|
||||||
|
File file = new File(getPath(path) + File.separator + fileName);
|
||||||
|
return file.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getPath(String path) {
|
||||||
|
if (path == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String pathCop = path.replaceAll("//", File.separator);
|
||||||
|
if (path.startsWith("~")) {
|
||||||
|
// 家目录
|
||||||
|
pathCop = path.replaceFirst("~", "");
|
||||||
|
pathCop = System.getProperty("user.home") + pathCop;
|
||||||
|
}
|
||||||
|
return pathCop;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
package cn.celess.blog.service.fileserviceimpl;
|
||||||
|
|
||||||
|
import cn.celess.blog.enmu.ConfigKeyEnum;
|
||||||
|
import cn.celess.blog.entity.model.FileInfo;
|
||||||
|
import cn.celess.blog.entity.model.FileResponse;
|
||||||
|
import cn.celess.blog.service.FileManager;
|
||||||
|
import com.qiniu.common.QiniuException;
|
||||||
|
import com.qiniu.common.Zone;
|
||||||
|
import com.qiniu.http.Response;
|
||||||
|
import com.qiniu.storage.BucketManager;
|
||||||
|
import com.qiniu.storage.Configuration;
|
||||||
|
import com.qiniu.storage.UploadManager;
|
||||||
|
import com.qiniu.util.Auth;
|
||||||
|
import com.qiniu.util.StringMap;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2019/04/25 18:15
|
||||||
|
*/
|
||||||
|
@Service("qiniuFileServiceImpl")
|
||||||
|
public class QiniuFileServiceImpl implements FileManager {
|
||||||
|
private static final Configuration cfg = new Configuration(Zone.zone2());
|
||||||
|
private static UploadManager uploadManager;
|
||||||
|
private static BucketManager bucketManager;
|
||||||
|
private static Auth auth;
|
||||||
|
|
||||||
|
private String bucket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* todo :: 添加reload 方法 配置修改重新创建对象
|
||||||
|
*/
|
||||||
|
private void init() {
|
||||||
|
String accessKey = System.getProperty(ConfigKeyEnum.FILE_QINIU_ACCESS_KEY.getKey());
|
||||||
|
String secretKey = System.getProperty(ConfigKeyEnum.FILE_QINIU_SECRET_KEY.getKey());
|
||||||
|
this.bucket = System.getProperty(ConfigKeyEnum.FILE_QINIU_BUCKET.getKey());
|
||||||
|
if (auth == null || uploadManager == null || bucketManager == null) {
|
||||||
|
auth = Auth.create(accessKey, secretKey);
|
||||||
|
uploadManager = new UploadManager(cfg);
|
||||||
|
bucketManager = new BucketManager(auth, cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileResponse uploadFile(InputStream is, String fileName) {
|
||||||
|
init();
|
||||||
|
//文件存在则删除文件
|
||||||
|
if (continueFile(fileName)) {
|
||||||
|
try {
|
||||||
|
System.out.println(bucketManager.delete(bucket, fileName).toString());
|
||||||
|
} catch (QiniuException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//上传
|
||||||
|
try {
|
||||||
|
Response response = uploadManager.put(is, fileName, auth.uploadToken(bucket), null, null);
|
||||||
|
FileResponse fileResponse = new FileResponse();
|
||||||
|
StringMap stringMap = response.jsonToMap();
|
||||||
|
|
||||||
|
fileResponse.key = (String) stringMap.get("key");
|
||||||
|
fileResponse.type = "qiniu";
|
||||||
|
fileResponse.size = 0;
|
||||||
|
fileResponse.hash = (String) stringMap.get("hash");
|
||||||
|
|
||||||
|
return fileResponse;
|
||||||
|
} catch (QiniuException e) {
|
||||||
|
Response r = e.response;
|
||||||
|
System.err.println(r.toString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FileInfo> getFileList() {
|
||||||
|
init();
|
||||||
|
List<FileInfo> infoList = null;
|
||||||
|
BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(bucket, "", 1000, "");
|
||||||
|
while (fileListIterator.hasNext()) {
|
||||||
|
//处理获取的file list结果
|
||||||
|
infoList = new ArrayList<com.qiniu.storage.model.FileInfo>(Arrays.asList(fileListIterator.next()))
|
||||||
|
.stream()
|
||||||
|
.map(item -> {
|
||||||
|
FileInfo fileInfo = new FileInfo();
|
||||||
|
fileInfo.key = item.key;
|
||||||
|
fileInfo.hash = item.hash;
|
||||||
|
fileInfo.size = item.fsize;
|
||||||
|
fileInfo.uploadTime = item.putTime;
|
||||||
|
return fileInfo;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
return infoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
@Override
|
||||||
|
public boolean deleteFile(String fileName) {
|
||||||
|
init();
|
||||||
|
Response response = bucketManager.delete(bucket, fileName);
|
||||||
|
return "".equals(response.bodyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean continueFile(String key) {
|
||||||
|
List<FileInfo> fileList = getFileList();
|
||||||
|
for (FileInfo fileInfo : fileList) {
|
||||||
|
if (key.equals(fileInfo.key)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package cn.celess.blog.service.serviceimpl;
|
||||||
|
|
||||||
|
import cn.celess.blog.BlogApplication;
|
||||||
|
import cn.celess.blog.enmu.ConfigKeyEnum;
|
||||||
|
import cn.celess.blog.enmu.ResponseEnum;
|
||||||
|
import cn.celess.blog.entity.Config;
|
||||||
|
import cn.celess.blog.entity.InstallParam;
|
||||||
|
import cn.celess.blog.entity.User;
|
||||||
|
import cn.celess.blog.exception.MyException;
|
||||||
|
import cn.celess.blog.mapper.ConfigMapper;
|
||||||
|
import cn.celess.blog.mapper.UserMapper;
|
||||||
|
import cn.celess.blog.service.InstallService;
|
||||||
|
import cn.celess.blog.service.fileserviceimpl.LocalFileServiceImpl;
|
||||||
|
import cn.celess.blog.util.MD5Util;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author : xiaohai
|
||||||
|
* @date : 2020/10/23 16:23
|
||||||
|
* @desc :
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class InstallServiceImpl implements InstallService {
|
||||||
|
|
||||||
|
public static final String MYSQL_DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";
|
||||||
|
public static final String H2_DRIVER_CLASS_NAME = "org.h2.Driver";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ConfigMapper configMapper;
|
||||||
|
@Autowired
|
||||||
|
UserMapper userMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> isInstall() {
|
||||||
|
Config installed = configMapper.getConfiguration(ConfigKeyEnum.BLOG_INSTALLED.getKey());
|
||||||
|
Boolean isInstall = Boolean.valueOf(installed.getValue());
|
||||||
|
Map<String, Object> result = new HashMap<>(3);
|
||||||
|
result.put("is_install", isInstall);
|
||||||
|
if (isInstall) {
|
||||||
|
Map<String, String> configMap = configMapper.getConfigurations()
|
||||||
|
.stream()
|
||||||
|
.filter(config -> config.getValue() != null)
|
||||||
|
.collect(Collectors.toMap(Config::getName, Config::getValue));
|
||||||
|
result.put(ConfigKeyEnum.FILE_TYPE.getKey(), configMap.get(ConfigKeyEnum.FILE_TYPE.getKey()));
|
||||||
|
result.put(ConfigKeyEnum.DB_TYPE.getKey(), configMap.get(ConfigKeyEnum.DB_TYPE.getKey()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Map<String, Object> install(@NotNull InstallParam installParam) {
|
||||||
|
User user = new User(installParam.getEmail(), MD5Util.getMD5(installParam.getPassword()));
|
||||||
|
userMapper.addUser(user);
|
||||||
|
userMapper.setUserRole(user.getId(), "admin");
|
||||||
|
|
||||||
|
|
||||||
|
Config install = configMapper.getConfiguration(ConfigKeyEnum.BLOG_INSTALLED.getKey());
|
||||||
|
boolean isInstall = Boolean.parseBoolean(install.getValue());
|
||||||
|
if (isInstall) {
|
||||||
|
throw new MyException(ResponseEnum.FAILURE, "已经安装过了");
|
||||||
|
}
|
||||||
|
|
||||||
|
Config config = new Config(ConfigKeyEnum.DB_TYPE);
|
||||||
|
config.setValue(installParam.getDbType());
|
||||||
|
Properties properties = new Properties();
|
||||||
|
StringBuilder urlSb = new StringBuilder();
|
||||||
|
if ("h2".equals(installParam.getDbType())) {
|
||||||
|
properties.setProperty(ConfigKeyEnum.DB_DRIVER_CLASS_NAME.getKey(), H2_DRIVER_CLASS_NAME);
|
||||||
|
urlSb.append("jdbc:h2:");
|
||||||
|
} else {
|
||||||
|
properties.setProperty(ConfigKeyEnum.DB_DRIVER_CLASS_NAME.getKey(), MYSQL_DRIVER_CLASS_NAME);
|
||||||
|
urlSb.append("jdbc:mysql:");
|
||||||
|
}
|
||||||
|
// TODO ::
|
||||||
|
urlSb.append(installParam.getDbHost()).append('/').append(installParam.getDbName());
|
||||||
|
properties.setProperty(ConfigKeyEnum.DB_URL.getKey(), urlSb.toString());
|
||||||
|
properties.setProperty(ConfigKeyEnum.DB_USERNAME.getKey(), installParam.getDbUsername());
|
||||||
|
properties.setProperty(ConfigKeyEnum.DB_PASSWORD.getKey(), installParam.getDbPassword());
|
||||||
|
|
||||||
|
Config configuration = configMapper.getConfiguration(ConfigKeyEnum.BLOG_DB_PATH.getKey());
|
||||||
|
|
||||||
|
File file = new File(LocalFileServiceImpl.getPath(configuration.getValue()));
|
||||||
|
if (!file.exists() && file.createNewFile()) {
|
||||||
|
log.info("创建数据库配置文件: {}", file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
FileInputStream fis = new FileInputStream(file);
|
||||||
|
FileOutputStream fos = new FileOutputStream(file);
|
||||||
|
properties.load(fis);
|
||||||
|
|
||||||
|
configMapper.addConfiguration(config);
|
||||||
|
properties.store(fos, "DB CONFIG");
|
||||||
|
|
||||||
|
install.setValue(Boolean.valueOf(true).toString());
|
||||||
|
configMapper.updateConfiguration(install);
|
||||||
|
|
||||||
|
log.info("重启...");
|
||||||
|
|
||||||
|
// 重启
|
||||||
|
BlogApplication.restart();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
package cn.celess.blog.service.serviceimpl;
|
|
||||||
|
|
||||||
import cn.celess.blog.entity.model.QiniuResponse;
|
|
||||||
import cn.celess.blog.service.QiniuService;
|
|
||||||
import com.qiniu.common.QiniuException;
|
|
||||||
import com.qiniu.common.Zone;
|
|
||||||
import com.qiniu.http.Response;
|
|
||||||
import com.qiniu.storage.BucketManager;
|
|
||||||
import com.qiniu.storage.Configuration;
|
|
||||||
import com.qiniu.storage.UploadManager;
|
|
||||||
import com.qiniu.storage.model.FileInfo;
|
|
||||||
import com.qiniu.util.Auth;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author : xiaohai
|
|
||||||
* @date : 2019/04/25 18:15
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class QiniuServiceImpl implements QiniuService {
|
|
||||||
private static final Configuration cfg = new Configuration(Zone.zone2());
|
|
||||||
private static UploadManager uploadManager;
|
|
||||||
private static BucketManager bucketManager;
|
|
||||||
private static Auth auth;
|
|
||||||
|
|
||||||
@Value("${qiniu.accessKey}")
|
|
||||||
private String accessKey;
|
|
||||||
@Value("${qiniu.secretKey}")
|
|
||||||
private String secretKey;
|
|
||||||
@Value("${qiniu.bucket}")
|
|
||||||
private String bucket;
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
if (auth == null || uploadManager == null || bucketManager == null) {
|
|
||||||
auth = Auth.create(accessKey, secretKey);
|
|
||||||
uploadManager = new UploadManager(cfg);
|
|
||||||
bucketManager = new BucketManager(auth, cfg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public QiniuResponse uploadFile(InputStream is, String fileName) {
|
|
||||||
init();
|
|
||||||
//文件存在则删除文件
|
|
||||||
if (continueFile(fileName)) {
|
|
||||||
try {
|
|
||||||
System.out.println(bucketManager.delete(bucket, fileName).toString());
|
|
||||||
} catch (QiniuException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//上传
|
|
||||||
try {
|
|
||||||
Response response = uploadManager.put(is, fileName, auth.uploadToken(bucket), null, null);
|
|
||||||
return response.jsonToObject(QiniuResponse.class);
|
|
||||||
} catch (QiniuException e) {
|
|
||||||
Response r = e.response;
|
|
||||||
System.err.println(r.toString());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FileInfo[] getFileList() {
|
|
||||||
init();
|
|
||||||
BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(bucket, "", 1000, "");
|
|
||||||
FileInfo[] items = null;
|
|
||||||
while (fileListIterator.hasNext()) {
|
|
||||||
//处理获取的file list结果
|
|
||||||
items = fileListIterator.next();
|
|
||||||
}
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean continueFile(String key) {
|
|
||||||
FileInfo[] allFile = getFileList();
|
|
||||||
for (FileInfo fileInfo : allFile) {
|
|
||||||
if (key.equals(fileInfo.key)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,15 +5,15 @@ import cn.celess.blog.enmu.RoleEnum;
|
|||||||
import cn.celess.blog.enmu.UserAccountStatusEnum;
|
import cn.celess.blog.enmu.UserAccountStatusEnum;
|
||||||
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.FileResponse;
|
||||||
import cn.celess.blog.entity.model.PageData;
|
import cn.celess.blog.entity.model.PageData;
|
||||||
import cn.celess.blog.entity.model.QiniuResponse;
|
|
||||||
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.exception.MyException;
|
import cn.celess.blog.exception.MyException;
|
||||||
import cn.celess.blog.mapper.UserMapper;
|
import cn.celess.blog.mapper.UserMapper;
|
||||||
|
import cn.celess.blog.service.FileService;
|
||||||
import cn.celess.blog.service.MailService;
|
import cn.celess.blog.service.MailService;
|
||||||
import cn.celess.blog.service.QiniuService;
|
|
||||||
import cn.celess.blog.service.UserService;
|
import cn.celess.blog.service.UserService;
|
||||||
import cn.celess.blog.util.*;
|
import cn.celess.blog.util.*;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
@@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.mail.SimpleMailMessage;
|
import org.springframework.mail.SimpleMailMessage;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.beans.Transient;
|
import java.beans.Transient;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -45,8 +46,8 @@ public class UserServiceImpl implements UserService {
|
|||||||
HttpServletRequest request;
|
HttpServletRequest request;
|
||||||
@Autowired
|
@Autowired
|
||||||
MailService mailService;
|
MailService mailService;
|
||||||
@Autowired
|
@Resource(name = "fileServiceImpl")
|
||||||
QiniuService qiniuService;
|
FileService fileService;
|
||||||
@Autowired
|
@Autowired
|
||||||
RedisUtil redisUtil;
|
RedisUtil redisUtil;
|
||||||
@Autowired
|
@Autowired
|
||||||
@@ -185,7 +186,7 @@ public class UserServiceImpl implements UserService {
|
|||||||
@Override
|
@Override
|
||||||
public Object updateUserAavatarImg(InputStream is, String mime) {
|
public Object updateUserAavatarImg(InputStream is, String mime) {
|
||||||
User user = redisUserUtil.get();
|
User user = redisUserUtil.get();
|
||||||
QiniuResponse upload = qiniuService.uploadFile(is, user.getEmail() + "_" + user.getId() + mime.toLowerCase());
|
FileResponse upload = fileService.getFileManager().uploadFile(is, user.getEmail() + "_" + user.getId() + mime.toLowerCase());
|
||||||
user.setAvatarImgUrl(upload.key);
|
user.setAvatarImgUrl(upload.key);
|
||||||
userMapper.updateAvatarImgUrl(upload.key, user.getId());
|
userMapper.updateAvatarImgUrl(upload.key, user.getId());
|
||||||
redisUserUtil.set(user);
|
redisUserUtil.set(user);
|
||||||
|
|||||||
65
src/main/resources/application-easyDeploy.properties
Normal file
65
src/main/resources/application-easyDeploy.properties
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
|
||||||
|
spring.datasource.url=jdbc:h2:~/blog/db
|
||||||
|
spring.datasource.driver-class-name=org.h2.Driver
|
||||||
|
spring.datasource.username=sa
|
||||||
|
spring.datasource.password=sa
|
||||||
|
|
||||||
|
spring.datasource.platform=h2
|
||||||
|
spring.datasource.sql-script-encoding=utf-8
|
||||||
|
spring.datasource.initialization-mode=never
|
||||||
|
spring.datasource.schema=classpath:sql/schema-h2.sql
|
||||||
|
spring.datasource.data=classpath:sql/data.sql
|
||||||
|
|
||||||
|
spring.h2.console.path=/h2-console
|
||||||
|
spring.h2.console.enabled=true
|
||||||
|
|
||||||
|
# 生成JWT时候的密钥
|
||||||
|
jwt.secret=11111222223333444455556667778888
|
||||||
|
# sitemap 存放地址
|
||||||
|
sitemap.path=/www/wwwroot/celess.cn/sitemap.xml
|
||||||
|
|
||||||
|
|
||||||
|
############### 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
|
||||||
|
|
||||||
|
################## 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
|
||||||
|
|
||||||
|
############### redis ##############
|
||||||
|
# REDIS (RedisProperties)
|
||||||
|
# Redis数据库索引(默认为0)
|
||||||
|
spring.redis.database=1
|
||||||
|
# Redis服务器地址
|
||||||
|
spring.redis.host=127.0.0.1
|
||||||
|
# Redis服务器连接端口 解决端口冲突 防止使用本地的redis
|
||||||
|
spring.redis.port=6379
|
||||||
|
# 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
|
||||||
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
server.port=8081
|
server.port=8081
|
||||||
|
|
||||||
# 七牛的密钥配置
|
# 七牛的密钥配置
|
||||||
qiniu.accessKey=
|
file.qiniu.accessKey=
|
||||||
qiniu.secretKey=
|
file.qiniu.secretKey=
|
||||||
qiniu.bucket=
|
file.qiniu.bucket=
|
||||||
# sitemap 存放地址
|
# sitemap 存放地址
|
||||||
sitemap.path=
|
sitemap.path=
|
||||||
# 生成JWT时候的密钥
|
# 生成JWT时候的密钥
|
||||||
@@ -62,12 +62,6 @@ spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFact
|
|||||||
spring.mail.properties.mail.smtp.socketFactory.fallback=false
|
spring.mail.properties.mail.smtp.socketFactory.fallback=false
|
||||||
|
|
||||||
|
|
||||||
#### 用于nginx的代理 获取真实ip
|
|
||||||
server.use-forward-headers = true
|
|
||||||
server.tomcat.remote-ip-header = X-Real-IP
|
|
||||||
server.tomcat.protocol-header = X-Forwarded-Proto
|
|
||||||
|
|
||||||
|
|
||||||
############### redis ##############
|
############### redis ##############
|
||||||
# REDIS (RedisProperties)
|
# REDIS (RedisProperties)
|
||||||
# Redis数据库索引(默认为0)
|
# Redis数据库索引(默认为0)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
server.port=8081
|
server.port=8081
|
||||||
|
|
||||||
# 七牛的密钥配置
|
# 七牛的密钥配置
|
||||||
qiniu.accessKey=
|
file.qiniu.accessKey=${QINIU_ACCESSKEY:null}
|
||||||
qiniu.secretKey=
|
file.qiniu.secretKey=${QINIU_SECRETKEY:null}
|
||||||
qiniu.bucket=
|
file.qiniu.bucket=xiaohai
|
||||||
# sitemap 存放地址
|
# sitemap 存放地址
|
||||||
sitemap.path=
|
sitemap.path=
|
||||||
# 生成JWT时候的密钥
|
# 生成JWT时候的密钥
|
||||||
@@ -32,10 +32,9 @@ spring.datasource.username=sa
|
|||||||
spring.datasource.password=
|
spring.datasource.password=
|
||||||
|
|
||||||
|
|
||||||
spring.datasource.platform=h2
|
|
||||||
spring.datasource.sql-script-encoding=utf-8
|
spring.datasource.sql-script-encoding=utf-8
|
||||||
spring.datasource.initialization-mode=ALWAYS
|
spring.datasource.initialization-mode=ALWAYS
|
||||||
spring.datasource.schema=classpath:sql/schema_h2.sql
|
spring.datasource.schema=classpath:sql/schema-h2.sql
|
||||||
spring.datasource.data=classpath:sql/data.sql
|
spring.datasource.data=classpath:sql/data.sql
|
||||||
|
|
||||||
|
|
||||||
@@ -50,13 +49,6 @@ pagehelper.support-methods-arguments=true
|
|||||||
pagehelper.params=count=countSql
|
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 ##############
|
############### email ##############
|
||||||
spring.mail.host=smtp.163.com
|
spring.mail.host=smtp.163.com
|
||||||
spring.mail.username=
|
spring.mail.username=
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
spring.profiles.active=prod
|
spring.profiles.active=easyDeploy
|
||||||
####七牛的配置
|
|
||||||
####cn.celess.blog.service.serviceimpl.QiniuServiceImpl
|
|
||||||
logging.level.cn.celess.blog=debug
|
logging.level.cn.celess.blog=debug
|
||||||
logging.level.cn.celess.blog.mapper=info
|
logging.level.cn.celess.blog.mapper=info
|
||||||
|
|
||||||
|
#### 用于nginx的代理 获取真实ip
|
||||||
|
server.use-forward-headers = true
|
||||||
|
server.tomcat.remote-ip-header = X-Real-IP
|
||||||
|
server.tomcat.protocol-header = X-Forwarded-Proto
|
||||||
|
|
||||||
## 修改openSource 添加-test 文件用于测试 -prod文件用于线上发布
|
## 修改openSource 添加-test 文件用于测试 -prod文件用于线上发布
|
||||||
50
src/main/resources/mapper/ConfigMapper.xml
Normal file
50
src/main/resources/mapper/ConfigMapper.xml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="cn.celess.blog.mapper.ConfigMapper">
|
||||||
|
|
||||||
|
<resultMap type="cn.celess.blog.entity.Config" id="ConfigMap">
|
||||||
|
<result property="id" column="conf_id" jdbcType="INTEGER"/>
|
||||||
|
<result property="name" column="conf_name" jdbcType="VARCHAR"/>
|
||||||
|
<result property="value" column="conf_value" jdbcType="VARCHAR"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<!--查询单个-->
|
||||||
|
<select id="getConfiguration" resultMap="ConfigMap">
|
||||||
|
select conf_id,
|
||||||
|
conf_name,
|
||||||
|
conf_value
|
||||||
|
from config
|
||||||
|
where conf_name = #{key}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!--查询指定行数据-->
|
||||||
|
<select id="getConfigurations" resultMap="ConfigMap">
|
||||||
|
select conf_id,
|
||||||
|
conf_name,
|
||||||
|
conf_value
|
||||||
|
from config
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
<!--新增所有列-->
|
||||||
|
<insert id="addConfiguration" keyProperty="id" useGeneratedKeys="true">
|
||||||
|
insert into config(conf_name, conf_value)
|
||||||
|
values (#{name}, #{value})
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
|
||||||
|
<!--通过主键修改数据-->
|
||||||
|
<update id="updateConfiguration">
|
||||||
|
update config
|
||||||
|
set conf_value = #{value}
|
||||||
|
where conf_id = #{id}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!--通过主键删除-->
|
||||||
|
<delete id="deleteConfiguration">
|
||||||
|
delete
|
||||||
|
from config
|
||||||
|
where conf_id = #{id}
|
||||||
|
</delete>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
110
src/main/resources/public/css/install.css
Normal file
110
src/main/resources/public/css/install.css
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box {
|
||||||
|
width: 600px;
|
||||||
|
height: 45vh;
|
||||||
|
padding: 8px 10px;
|
||||||
|
border: 1px solid rgba(50, 50, 50, .1);
|
||||||
|
border-radius: 3px;
|
||||||
|
position: relative;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-inner {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-inner select, input, button {
|
||||||
|
width: 90%;
|
||||||
|
margin: 12px 5%;
|
||||||
|
height: 40px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid rgba(50, 50, 50, .1);
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus {
|
||||||
|
border: 1px solid rgba(0, 50, 50, .6);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-inner h3 {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.err-msg {
|
||||||
|
display: none;
|
||||||
|
color: red;
|
||||||
|
width: 100%;
|
||||||
|
padding-left: 30px;
|
||||||
|
font-size: small;
|
||||||
|
font-weight: lighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.show-err-tip {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#first-page, #second-page {
|
||||||
|
height: 100%;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
height: 0 !important;
|
||||||
|
visibility: hidden;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.show {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#next-step, .button-group {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group button {
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group #install {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 20px;
|
||||||
|
background: #1890ff;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-show {
|
||||||
|
z-index: 10000;
|
||||||
|
display: flex !important;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
171
src/main/resources/public/css/loading.css
Normal file
171
src/main/resources/public/css/loading.css
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
.pacman {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
box-sizing: border-box;
|
||||||
|
flex: 0 1 auto;
|
||||||
|
display: none;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-basis: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
/*height: 200px;*/
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: #ececec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.pacman > div:nth-child(2) {
|
||||||
|
-webkit-animation: pacman-balls 1s 0s infinite linear;
|
||||||
|
animation: pacman-balls 1s 0s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pacman > div:nth-child(3) {
|
||||||
|
-webkit-animation: pacman-balls 1s 0.33s infinite linear;
|
||||||
|
animation: pacman-balls 1s 0.33s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pacman > div:nth-child(4) {
|
||||||
|
-webkit-animation: pacman-balls 1s 0.66s infinite linear;
|
||||||
|
animation: pacman-balls 1s 0.66s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pacman > div:nth-child(5) {
|
||||||
|
-webkit-animation: pacman-balls 1s 0.99s infinite linear;
|
||||||
|
animation: pacman-balls 1s 0.99s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pacman > div:first-of-type {
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
border-right: 25px solid transparent;
|
||||||
|
border-top: 25px solid #ed5565;
|
||||||
|
border-left: 25px solid #ed5565;
|
||||||
|
border-bottom: 25px solid #ed5565;
|
||||||
|
border-radius: 25px;
|
||||||
|
-webkit-animation: rotate_pacman_half_up 0.5s 0s infinite;
|
||||||
|
animation: rotate_pacman_half_up 0.5s 0s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pacman > div:nth-child(2) {
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
border-right: 25px solid transparent;
|
||||||
|
border-top: 25px solid #ed5565;
|
||||||
|
border-left: 25px solid #ed5565;
|
||||||
|
border-bottom: 25px solid #ed5565;
|
||||||
|
border-radius: 25px;
|
||||||
|
-webkit-animation: rotate_pacman_half_down 0.5s 0s infinite;
|
||||||
|
animation: rotate_pacman_half_down 0.5s 0s infinite;
|
||||||
|
margin-top: -50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pacman > div:nth-child(3), .pacman > div:nth-child(4), .pacman > div:nth-child(5), .pacman > div:nth-child(6) {
|
||||||
|
background-color: #ed5565;
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
border-radius: 100%;
|
||||||
|
margin: 2px;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
position: absolute;
|
||||||
|
-webkit-transform: translate(0, -6.25px);
|
||||||
|
-ms-transform: translate(0, -6.25px);
|
||||||
|
transform: translate(0, -6.25px);
|
||||||
|
top: 25px;
|
||||||
|
left: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes rotate_pacman_half_up {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(270deg);
|
||||||
|
transform: rotate(270deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
-webkit-transform: rotate(360deg);
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(270deg);
|
||||||
|
transform: rotate(270deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotate_pacman_half_up {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(270deg);
|
||||||
|
transform: rotate(270deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
-webkit-transform: rotate(360deg);
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(270deg);
|
||||||
|
transform: rotate(270deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes rotate_pacman_half_down {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(90deg);
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(90deg);
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotate_pacman_half_down {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(90deg);
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(90deg);
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes pacman-balls {
|
||||||
|
75% {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: translate(-100px, -6.25px);
|
||||||
|
transform: translate(-100px, -6.25px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pacman-balls {
|
||||||
|
75% {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
-webkit-transform: translate(-100px, -6.25px);
|
||||||
|
transform: translate(-100px, -6.25px);
|
||||||
|
}
|
||||||
|
}
|
||||||
164
src/main/resources/public/install.html
Normal file
164
src/main/resources/public/install.html
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>博客安装页面</title>
|
||||||
|
<link rel="stylesheet" href="css/install.css">
|
||||||
|
<link rel="stylesheet" href="css/loading.css">
|
||||||
|
<script src="//cdn.bootcdn.net/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="loading">
|
||||||
|
<div class="loader-inner pacman">
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<p style="margin-top: 20px;margin-left: 10px;">
|
||||||
|
加载中....
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-inner">
|
||||||
|
<div id="first-page" class="show">
|
||||||
|
<h3>数据库配置</h3>
|
||||||
|
<!-- 数据库-->
|
||||||
|
<select id="db-type">
|
||||||
|
<option value="h2">H2数据库</option>
|
||||||
|
<option value="mysql">Mysql数据库</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<input id="db-host" type="text" placeholder="请输入数据库的主机地址">
|
||||||
|
<span class="err-msg" id="err-tip-db-host">数据库的主机地址不可为空</span>
|
||||||
|
|
||||||
|
<input id="db-name" type="text" placeholder="请输入数据库的名称">
|
||||||
|
<span class="err-msg" id="err-tip-db-name">数据库的地址名称不可为空</span>
|
||||||
|
|
||||||
|
<input id="db-username" type="text" placeholder="请输入数据库用户名">
|
||||||
|
<span class="err-msg" id="err-tip-db-username">数据库用户名不可为空</span>
|
||||||
|
|
||||||
|
<input id="db-password" type="password" placeholder="请输入数据库密码">
|
||||||
|
<span class="err-msg" id="err-tip-db-password">数据库密码不可为空</span>
|
||||||
|
|
||||||
|
<button onclick="nextPage()" id="next-step">下一步</button>
|
||||||
|
</div>
|
||||||
|
<div id="second-page" class="hidden">
|
||||||
|
<h3>新建管理员用户</h3>
|
||||||
|
<input id="email" type="email" placeholder="请输入用户名">
|
||||||
|
<span class="err-msg" id="err-tip-email">用户名不可为空</span>
|
||||||
|
<input id="password" type="password" placeholder="请输入密码">
|
||||||
|
<span class="err-msg" id="err-tip-password">密码不可为空</span>
|
||||||
|
<div class="button-group">
|
||||||
|
<button onclick="preStep()" id="pre-step">上一步</button>
|
||||||
|
<button onclick="postInstallEvent()" id="install"> 安装</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
let requestData;
|
||||||
|
let interValId;
|
||||||
|
|
||||||
|
function postInstallEvent() {
|
||||||
|
requestData.email = $('#email').val()
|
||||||
|
requestData.password = $('#password').val()
|
||||||
|
$('#err-tip-email').removeClass("show-err-tip");
|
||||||
|
$('#err-tip-password').removeClass("show-err-tip");
|
||||||
|
!requestData.password && checkInput($('#password'), $('#err-tip-password'))
|
||||||
|
!requestData.email && checkInput($('#email'), $('#err-tip-email'))
|
||||||
|
if (!requestData.email || !requestData.password) return;
|
||||||
|
$('.loading').addClass('loading-show');
|
||||||
|
$.ajax('/install', {
|
||||||
|
method: "POST",
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: JSON.stringify(requestData),
|
||||||
|
withCredentials: true,
|
||||||
|
dataType: 'json',
|
||||||
|
success: function (data) {
|
||||||
|
console.log("data", data);
|
||||||
|
console.log("requestData", requestData);
|
||||||
|
interValId = setInterval(checkConnection, 500)
|
||||||
|
checkConnection();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkConnection() {
|
||||||
|
$.ajax('/is_install', {
|
||||||
|
method: "GET",
|
||||||
|
dataType: 'json',
|
||||||
|
success: function (data) {
|
||||||
|
if (data.result.is_install) {
|
||||||
|
console.log("安装成功");
|
||||||
|
window.location.href = '/';
|
||||||
|
} else {
|
||||||
|
console.log("安装失败");
|
||||||
|
}
|
||||||
|
$('.loading').removeClass('loading-show');
|
||||||
|
clearInterval(interValId);
|
||||||
|
},
|
||||||
|
error: function (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换下一页
|
||||||
|
*/
|
||||||
|
function nextPage() {
|
||||||
|
requestData = {
|
||||||
|
dbPassword: $('#db-password').val(),
|
||||||
|
dbType: $('#db-type').val(),
|
||||||
|
dbHost: $('#db-host').val(),
|
||||||
|
dbName: $('#db-name').val(),
|
||||||
|
dbUsername: $('#db-username').val(),
|
||||||
|
email: '',
|
||||||
|
password: '',
|
||||||
|
}
|
||||||
|
$('#err-tip-db-type').removeClass("show-err-tip");
|
||||||
|
$('#err-tip-db-host').removeClass("show-err-tip");
|
||||||
|
$('#err-tip-db-name').removeClass("show-err-tip");
|
||||||
|
$('#err-tip-db-username').removeClass("show-err-tip");
|
||||||
|
$('#err-tip-db-password').removeClass("show-err-tip");
|
||||||
|
!requestData.dbType && checkInput($('#db-type'), $('#err-tip-db-type'))
|
||||||
|
!requestData.dbHost && checkInput($('#db-host'), $('#err-tip-db-host'))
|
||||||
|
!requestData.dbName && checkInput($('#db-name'), $('#err-tip-db-name'))
|
||||||
|
!requestData.dbUsername && checkInput($('#db-username'), $('#err-tip-db-username'))
|
||||||
|
!requestData.dbPassword && checkInput($('#db-password'), $('#err-tip-db-password'))
|
||||||
|
if (!requestData.dbType || !requestData.dbUrl || !requestData.dbUsername || !requestData.dbPassword) return
|
||||||
|
$('#first-page').addClass('hidden');
|
||||||
|
$('#first-page').removeClass('show');
|
||||||
|
$('#second-page').addClass('show');
|
||||||
|
$('#second-page').removeClass('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function preStep() {
|
||||||
|
$('#second-page').addClass('hidden');
|
||||||
|
$('#second-page').removeClass('show');
|
||||||
|
$('#first-page').addClass('show');
|
||||||
|
$('#first-page').removeClass('hidden');
|
||||||
|
|
||||||
|
$('#err-tip-email').removeClass("show-err-tip");
|
||||||
|
$('#err-tip-password').removeClass("show-err-tip");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查组件的状态
|
||||||
|
* @param component 输入框
|
||||||
|
* @param errTipComponent 错误信息提示框
|
||||||
|
* @returns {boolean} 是否有错误
|
||||||
|
*/
|
||||||
|
function checkInput(component, errTipComponent) {
|
||||||
|
if (!component.val()) {
|
||||||
|
errTipComponent.addClass("show-err-tip");
|
||||||
|
component.focus();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -214,3 +214,12 @@ VALUES (1, '1.新增网站更新接口api \n2.新增友链api \n3.优化了文
|
|||||||
(16, '登陆处理过程变更,登陆时长修改至5天', '2019-11-22 11:39:03', 0),
|
(16, '登陆处理过程变更,登陆时长修改至5天', '2019-11-22 11:39:03', 0),
|
||||||
(17, '界面改版v2.0', '2020-04-06 11:00:53', 0);
|
(17, '界面改版v2.0', '2020-04-06 11:00:53', 0);
|
||||||
|
|
||||||
|
INSERT INTO config (conf_id, conf_name, conf_value)
|
||||||
|
VALUES (1, 'file.type', 'local'),
|
||||||
|
(2, 'file.qiniu.accessKey', null),
|
||||||
|
(3, 'file.qiniu.secretKey', null),
|
||||||
|
(4, 'file.qiniu.bucket', null),
|
||||||
|
(5, 'blog.file.path', '~/blog/'),
|
||||||
|
(6, 'file.local.directoryPath', '~/blog/files/'),
|
||||||
|
(8, 'blog.installed', 'false'),
|
||||||
|
(9, 'blog.db.path', '~/blog/db.properties')
|
||||||
@@ -8,6 +8,7 @@ drop table if exists tag_category;
|
|||||||
drop table if exists links;
|
drop table if exists links;
|
||||||
drop table if exists visitor;
|
drop table if exists visitor;
|
||||||
drop table if exists web_update;
|
drop table if exists web_update;
|
||||||
|
drop table if exists config;
|
||||||
|
|
||||||
-- 用户表
|
-- 用户表
|
||||||
CREATE TABLE `user`
|
CREATE TABLE `user`
|
||||||
@@ -115,6 +116,13 @@ CREATE TABLE `web_update`
|
|||||||
`is_delete` boolean not null default false comment '该数据是否被删除'
|
`is_delete` boolean not null default false comment '该数据是否被删除'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `config`
|
||||||
|
(
|
||||||
|
`conf_id` int primary key auto_increment,
|
||||||
|
`conf_name` varchar(255) unique not null comment '配置名',
|
||||||
|
`conf_value` varchar(255) default null comment '配置值'
|
||||||
|
);
|
||||||
|
|
||||||
CREATE VIEW articleView
|
CREATE VIEW articleView
|
||||||
(articleId, title, summary, mdContent, url, isOriginal, readingCount, likeCount, dislikeCount,
|
(articleId, title, summary, mdContent, url, isOriginal, readingCount, likeCount, dislikeCount,
|
||||||
publishDate, updateDate, isOpen,
|
publishDate, updateDate, isOpen,
|
||||||
@@ -8,6 +8,7 @@ drop table if exists tag_category;
|
|||||||
drop table if exists links;
|
drop table if exists links;
|
||||||
drop table if exists visitor;
|
drop table if exists visitor;
|
||||||
drop table if exists web_update;
|
drop table if exists web_update;
|
||||||
|
drop table if exists config;
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE `user`
|
CREATE TABLE `user`
|
||||||
@@ -88,7 +89,7 @@ CREATE TABLE `links`
|
|||||||
`l_url` varchar(255) unique 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_email` varchar(255) comment '网站管理员的邮箱',
|
||||||
`l_notification` boolean default false comment '是否通知了'
|
`l_notification` boolean default false comment '是否通知了'
|
||||||
) comment '友站表';
|
) comment '友站表';
|
||||||
@@ -110,6 +111,13 @@ CREATE TABLE `web_update`
|
|||||||
`is_delete` boolean not null default false comment '该数据是否被删除'
|
`is_delete` boolean not null default false comment '该数据是否被删除'
|
||||||
) comment '更新内容表';
|
) comment '更新内容表';
|
||||||
|
|
||||||
|
CREATE TABLE `config`
|
||||||
|
(
|
||||||
|
`conf_id` int primary key auto_increment,
|
||||||
|
`conf_name` varchar(255) unique not null comment '配置名',
|
||||||
|
`conf_value` varchar(255) default null comment '配置值'
|
||||||
|
);
|
||||||
|
|
||||||
CREATE VIEW articleView
|
CREATE VIEW articleView
|
||||||
(articleId, title, summary, mdContent, url, isOriginal, readingCount, likeCount, dislikeCount,
|
(articleId, title, summary, mdContent, url, isOriginal, readingCount, likeCount, dislikeCount,
|
||||||
publishDate, updateDate, isOpen,
|
publishDate, updateDate, isOpen,
|
||||||
|
|||||||
@@ -2,15 +2,15 @@ package cn.celess.blog;
|
|||||||
|
|
||||||
|
|
||||||
import cn.celess.blog.entity.Response;
|
import cn.celess.blog.entity.Response;
|
||||||
import cn.celess.blog.entity.model.QiniuResponse;
|
import cn.celess.blog.entity.model.FileInfo;
|
||||||
|
import cn.celess.blog.entity.model.FileResponse;
|
||||||
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.service.MailService;
|
import cn.celess.blog.service.MailService;
|
||||||
import cn.celess.blog.service.QiniuService;
|
import cn.celess.blog.service.FileManager;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.qiniu.storage.model.FileInfo;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -37,6 +37,8 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@@ -325,23 +327,29 @@ public class BaseTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public static class TestQiNiuServiceImpl implements QiniuService {
|
public static class TestFileManager implements FileManager {
|
||||||
@Override
|
@Override
|
||||||
public QiniuResponse uploadFile(InputStream is, String fileName) {
|
public FileResponse uploadFile(InputStream is, String fileName) {
|
||||||
QiniuResponse response = new QiniuResponse();
|
FileResponse response = new FileResponse();
|
||||||
log.debug("上传文件请求,[fileName:{}]", fileName);
|
log.debug("上传文件请求,[fileName:{}]", fileName);
|
||||||
|
|
||||||
response.key = "key";
|
response.key = "key";
|
||||||
response.bucket = "bucket";
|
response.type = "test";
|
||||||
response.hash = "hash";
|
response.hash = "hash";
|
||||||
response.fsize = 1;
|
response.size = 1;
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileInfo[] getFileList() {
|
public List<FileInfo> getFileList() {
|
||||||
log.debug("获取文件列表请求");
|
log.debug("获取文件列表请求");
|
||||||
return new FileInfo[0];
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteFile(String fileName) {
|
||||||
|
log.debug("删除[{}]成功", fileName);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
131
src/test/java/cn/celess/blog/configuration/DruidConfigTest.java
Normal file
131
src/test/java/cn/celess/blog/configuration/DruidConfigTest.java
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
package cn.celess.blog.configuration;
|
||||||
|
|
||||||
|
import cn.celess.blog.BaseTest;
|
||||||
|
import cn.celess.blog.enmu.ConfigKeyEnum;
|
||||||
|
import cn.celess.blog.service.fileserviceimpl.LocalFileServiceImpl;
|
||||||
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
public class DruidConfigTest extends BaseTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
Environment env;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
Environment globalEnvironment;
|
||||||
|
|
||||||
|
|
||||||
|
private File configFile;
|
||||||
|
private File bakConfigFile;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void initDataSource() throws IOException {
|
||||||
|
|
||||||
|
DruidConfig druidConfig = new DruidConfig();
|
||||||
|
|
||||||
|
druidConfig.env = env;
|
||||||
|
|
||||||
|
System.out.println(Arrays.toString(env.getActiveProfiles()));
|
||||||
|
|
||||||
|
// 无配置文件
|
||||||
|
assertTrue(!configFile.exists() || configFile.delete());
|
||||||
|
DruidDataSource druidDataSource = druidConfig.initDataSource();
|
||||||
|
|
||||||
|
// 加载初始化时候配置文件的数据库连接
|
||||||
|
assertEquals(env.getProperty(DruidConfig.DB_CONFIG_URL_PREFIX), druidDataSource.getUrl());
|
||||||
|
assertEquals(env.getProperty(DruidConfig.DB_CONFIG_DRIVER_CLASS_NAME_PREFIX), druidDataSource.getDriverClassName());
|
||||||
|
assertEquals(env.getProperty(DruidConfig.DB_CONFIG_USERNAME_PREFIX), druidDataSource.getUsername());
|
||||||
|
assertEquals(env.getProperty(DruidConfig.DB_CONFIG_PASSWORD_PREFIX), druidDataSource.getPassword());
|
||||||
|
assertTrue(configFile.createNewFile());
|
||||||
|
|
||||||
|
// 有配置文件的测试
|
||||||
|
Properties properties = new Properties();
|
||||||
|
FileInputStream fileInputStream = new FileInputStream(configFile);
|
||||||
|
properties.load(fileInputStream);
|
||||||
|
fileInputStream.close();
|
||||||
|
properties.setProperty(DruidConfig.DB_CONFIG_URL_PREFIX, "jdbc:mysql://localhost:3306/blog");
|
||||||
|
properties.setProperty(DruidConfig.DB_CONFIG_DRIVER_CLASS_NAME_PREFIX, "com.mysql.cj.jdbc.Driver");
|
||||||
|
properties.setProperty(DruidConfig.DB_CONFIG_USERNAME_PREFIX, "username");
|
||||||
|
properties.setProperty(DruidConfig.DB_CONFIG_PASSWORD_PREFIX, "password");
|
||||||
|
// 保存到文件
|
||||||
|
FileOutputStream fileOutputStream = new FileOutputStream(configFile);
|
||||||
|
properties.store(fileOutputStream, "数据库配置");
|
||||||
|
fileOutputStream.close();
|
||||||
|
druidDataSource = druidConfig.initDataSource();
|
||||||
|
assertEquals(properties.getProperty(DruidConfig.DB_CONFIG_URL_PREFIX), druidDataSource.getUrl());
|
||||||
|
assertEquals(properties.getProperty(DruidConfig.DB_CONFIG_DRIVER_CLASS_NAME_PREFIX), druidDataSource.getDriverClassName());
|
||||||
|
assertEquals(properties.getProperty(DruidConfig.DB_CONFIG_USERNAME_PREFIX), druidDataSource.getUsername());
|
||||||
|
assertEquals(properties.getProperty(DruidConfig.DB_CONFIG_PASSWORD_PREFIX), druidDataSource.getPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void setConfigBack() {
|
||||||
|
if (bakConfigFile.exists()) {
|
||||||
|
System.out.println("恢复配置文件成功");
|
||||||
|
copyFile(bakConfigFile, configFile);
|
||||||
|
assertTrue(bakConfigFile.delete());
|
||||||
|
} else {
|
||||||
|
configFile.deleteOnExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void recordConfig() {
|
||||||
|
File path = new File(LocalFileServiceImpl.getPath(System.getProperty(ConfigKeyEnum.BLOG_FILE_PATH.getKey())));
|
||||||
|
if (!path.exists() && !path.mkdirs()) {
|
||||||
|
fail("创建失败");
|
||||||
|
}
|
||||||
|
this.bakConfigFile = new File(DruidConfig.DB_CONFIG_PATH + ".bak");
|
||||||
|
this.configFile = new File(DruidConfig.DB_CONFIG_PATH);
|
||||||
|
if (configFile.exists()) {
|
||||||
|
System.out.println("备份文件成功");
|
||||||
|
copyFile(configFile, bakConfigFile);
|
||||||
|
}
|
||||||
|
when(this.env.getActiveProfiles()).thenReturn(new String[]{"dev"});
|
||||||
|
when(this.env.getProperty(DruidConfig.DB_CONFIG_PASSWORD_PREFIX)).thenReturn(globalEnvironment.getProperty(DruidConfig.DB_CONFIG_PASSWORD_PREFIX));
|
||||||
|
when(this.env.getProperty(DruidConfig.DB_CONFIG_URL_PREFIX)).thenReturn(globalEnvironment.getProperty(DruidConfig.DB_CONFIG_URL_PREFIX));
|
||||||
|
when(this.env.getProperty(DruidConfig.DB_CONFIG_USERNAME_PREFIX)).thenReturn(globalEnvironment.getProperty(DruidConfig.DB_CONFIG_USERNAME_PREFIX));
|
||||||
|
when(this.env.getProperty(DruidConfig.DB_CONFIG_DRIVER_CLASS_NAME_PREFIX)).thenReturn(globalEnvironment.getProperty(DruidConfig.DB_CONFIG_DRIVER_CLASS_NAME_PREFIX));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制文件
|
||||||
|
*
|
||||||
|
* @param src
|
||||||
|
* @param dist
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean copyFile(File src, File dist) {
|
||||||
|
try {
|
||||||
|
// 复制备份文件
|
||||||
|
FileOutputStream fos = new FileOutputStream(dist);
|
||||||
|
FileInputStream fis = new FileInputStream(src);
|
||||||
|
int len = 0;
|
||||||
|
byte[] bytes = new byte[1024];
|
||||||
|
while ((len = fis.read(bytes)) != -1) {
|
||||||
|
fos.write(bytes, 0, len);
|
||||||
|
}
|
||||||
|
fos.close();
|
||||||
|
fis.close();
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ 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.service.UserService;
|
import cn.celess.blog.service.UserService;
|
||||||
|
import cn.celess.blog.service.FileService;
|
||||||
import cn.celess.blog.util.MD5Util;
|
import cn.celess.blog.util.MD5Util;
|
||||||
import cn.celess.blog.util.RedisUtil;
|
import cn.celess.blog.util.RedisUtil;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
@@ -115,7 +116,7 @@ public class UserControllerTest extends BaseTest {
|
|||||||
assertNotNull(inputStream);
|
assertNotNull(inputStream);
|
||||||
|
|
||||||
// mock 实现类
|
// mock 实现类
|
||||||
mockInjectInstance(userService, "qiniuService", new TestQiNiuServiceImpl());
|
mockInjectInstance(userService, "fileService", (FileService) TestFileManager::new);
|
||||||
|
|
||||||
MockMultipartFile file = new MockMultipartFile("file", "logo.png", MediaType.IMAGE_PNG_VALUE, inputStream);
|
MockMultipartFile file = new MockMultipartFile("file", "logo.png", MediaType.IMAGE_PNG_VALUE, inputStream);
|
||||||
getMockData(multipart("/user/imgUpload").file(file), userLogin()).andDo(result -> {
|
getMockData(multipart("/user/imgUpload").file(file), userLogin()).andDo(result -> {
|
||||||
|
|||||||
63
src/test/java/cn/celess/blog/mapper/ConfigMapperTest.java
Normal file
63
src/test/java/cn/celess/blog/mapper/ConfigMapperTest.java
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package cn.celess.blog.mapper;
|
||||||
|
|
||||||
|
import cn.celess.blog.BaseTest;
|
||||||
|
import cn.celess.blog.entity.Config;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class ConfigMapperTest extends BaseTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ConfigMapper configMapper;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getConfiguration() {
|
||||||
|
Config file = configMapper.getConfiguration("file.type");
|
||||||
|
assertNotNull(file);
|
||||||
|
assertNotNull(file.getId());
|
||||||
|
assertEquals("file.type", file.getName());
|
||||||
|
assertEquals("local", file.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateConfiguration() {
|
||||||
|
Config config = generateConfig();
|
||||||
|
configMapper.addConfiguration(config);
|
||||||
|
assertNotNull(config.getId());
|
||||||
|
|
||||||
|
String s = randomStr();
|
||||||
|
config.setValue(s);
|
||||||
|
configMapper.updateConfiguration(config);
|
||||||
|
assertEquals(s, configMapper.getConfiguration(config.getName()).getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getConfigurations() {
|
||||||
|
assertTrue(configMapper.getConfigurations().size() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addConfiguration() {
|
||||||
|
Config config = generateConfig();
|
||||||
|
configMapper.addConfiguration(config);
|
||||||
|
assertNotNull(config.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void deleteConfiguration() {
|
||||||
|
Config config = generateConfig();
|
||||||
|
configMapper.addConfiguration(config);
|
||||||
|
assertNotNull(config.getId());
|
||||||
|
assertNotEquals(0, configMapper.deleteConfiguration(config.getId()));
|
||||||
|
assertNull(configMapper.getConfiguration(config.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Config generateConfig() {
|
||||||
|
Config config = new Config();
|
||||||
|
config.setName("test" + randomStr(4));
|
||||||
|
config.setValue(randomStr(4));
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
package cn.celess.blog.service.fileserviceimpl;
|
||||||
|
|
||||||
|
import cn.celess.blog.BaseTest;
|
||||||
|
import cn.celess.blog.enmu.ConfigKeyEnum;
|
||||||
|
import cn.celess.blog.entity.model.FileInfo;
|
||||||
|
import cn.celess.blog.entity.model.FileResponse;
|
||||||
|
import cn.celess.blog.service.FileManager;
|
||||||
|
import cn.celess.blog.service.FileService;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class FileManagerTest extends BaseTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
FileService fileService;
|
||||||
|
|
||||||
|
FileManager fileManager;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUploadFile() {
|
||||||
|
// 测试本地的文件上传
|
||||||
|
fileManager = null;
|
||||||
|
System.setProperty(ConfigKeyEnum.FILE_TYPE.getKey(), "local");
|
||||||
|
fileManager = fileService.getFileManager();
|
||||||
|
assertTrue(fileManager instanceof LocalFileServiceImpl);
|
||||||
|
uploadFile();
|
||||||
|
|
||||||
|
// 测试七牛云的文件上传
|
||||||
|
fileManager = null;
|
||||||
|
System.setProperty(ConfigKeyEnum.FILE_TYPE.getKey(), "qiniu");
|
||||||
|
fileManager = fileService.getFileManager();
|
||||||
|
assertTrue(fileManager instanceof QiniuFileServiceImpl);
|
||||||
|
uploadFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetFileList() {
|
||||||
|
// 测试获取本地的文件列表
|
||||||
|
fileManager = null;
|
||||||
|
System.setProperty(ConfigKeyEnum.FILE_TYPE.getKey(), "local");
|
||||||
|
fileManager = fileService.getFileManager();
|
||||||
|
assertTrue(fileManager instanceof LocalFileServiceImpl);
|
||||||
|
getFileList();
|
||||||
|
|
||||||
|
// 测试获取七牛云的文件列表
|
||||||
|
fileManager = null;
|
||||||
|
System.setProperty(ConfigKeyEnum.FILE_TYPE.getKey(), "qiniu");
|
||||||
|
fileManager = fileService.getFileManager();
|
||||||
|
assertTrue(fileManager instanceof QiniuFileServiceImpl);
|
||||||
|
getFileList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteFile() {
|
||||||
|
// 测试删除本地文件
|
||||||
|
fileManager = null;
|
||||||
|
System.setProperty(ConfigKeyEnum.FILE_TYPE.getKey(), "local");
|
||||||
|
fileManager = fileService.getFileManager();
|
||||||
|
assertTrue(fileManager instanceof LocalFileServiceImpl);
|
||||||
|
deleteFile();
|
||||||
|
|
||||||
|
// 测试删除七牛云文件
|
||||||
|
fileManager = null;
|
||||||
|
System.setProperty(ConfigKeyEnum.FILE_TYPE.getKey(), "qiniu");
|
||||||
|
fileManager = fileService.getFileManager();
|
||||||
|
assertTrue(fileManager instanceof QiniuFileServiceImpl);
|
||||||
|
deleteFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public void uploadFile() {
|
||||||
|
String fileName = null;
|
||||||
|
File file = createFile();
|
||||||
|
FileResponse fileResponse = fileManager.uploadFile(new FileInputStream(file), file.getName());
|
||||||
|
assertEquals(file.getName(), fileResponse.key);
|
||||||
|
assertEquals(System.getProperty(ConfigKeyEnum.FILE_TYPE.getKey()), fileResponse.type);
|
||||||
|
// assertNotNull(fileResponse.hash);
|
||||||
|
fileName = fileResponse.key;
|
||||||
|
|
||||||
|
fileManager.deleteFile(fileName);
|
||||||
|
|
||||||
|
file.deleteOnExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getFileList() {
|
||||||
|
List<FileInfo> fileList = fileManager.getFileList();
|
||||||
|
fileList.forEach(fileInfo -> {
|
||||||
|
assertNotNull(fileInfo.key);
|
||||||
|
// assertNotNull(fileInfo.hash);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteFile() {
|
||||||
|
uploadFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private File createFile() {
|
||||||
|
String fileName = "test." + randomStr(3);
|
||||||
|
File file = new File(fileName);
|
||||||
|
if (!file.exists() && file.createNewFile()) {
|
||||||
|
// 创建文件
|
||||||
|
log.debug("创建文件[{}]", fileName);
|
||||||
|
FileOutputStream outputStream = new FileOutputStream(file);
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
outputStream.write(new byte[1024]);
|
||||||
|
}
|
||||||
|
outputStream.flush();
|
||||||
|
outputStream.close();
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user