Compare commits
7 Commits
master
...
demo-restf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9167c8d652 | ||
|
|
0dcc3c12ec | ||
|
|
295b022762 | ||
|
|
e1c2edb92b | ||
|
|
6d4d53054d | ||
|
|
a18783fca4 | ||
|
|
086ab27837 |
21
.drone.yaml
@ -1,21 +0,0 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: mx-community
|
||||
steps:
|
||||
- name: build
|
||||
image: maven:3-jdk-8
|
||||
pull: if-not-exists
|
||||
volumes:
|
||||
- name: maven
|
||||
path: /root/.m2
|
||||
commands:
|
||||
- mvn clean package -DskipTests
|
||||
- ls -h
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
|
||||
volumes:
|
||||
- name: maven
|
||||
host:
|
||||
path: /opt/ci/maven/
|
||||
20
.gitignore
vendored
@ -1,12 +1,11 @@
|
||||
HELP.md
|
||||
target/
|
||||
log/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**
|
||||
!**/src/test/**
|
||||
*.class
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
*.log
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
@ -14,12 +13,18 @@ log/
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
@ -27,7 +32,6 @@ log/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
FROM hub.c.163.com/library/java:latest
|
||||
VOLUME /tmp
|
||||
ADD target/blog-1.0.1-SNAPSHOT.jar blog.jar
|
||||
ENTRYPOINT ["java","-jar","/blog.jar"]
|
||||
62
README.md
@ -1,48 +1,32 @@
|
||||
# Getting Started RestFul
|
||||
|
||||
### Reference Documentation
|
||||
|
||||
## 浅枫沐雪:
|
||||
For further reference, please consider the following sections:
|
||||
|
||||
**项目名称:** 浅枫沐雪开源版
|
||||
* [Official Gradle documentation](https://docs.gradle.org)
|
||||
* [Spring Boot Gradle Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.4.5/gradle-plugin/reference/html/)
|
||||
* [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.4.5/gradle-plugin/reference/html/#build-image)
|
||||
* [Rest Repositories](https://docs.spring.io/spring-boot/docs/2.4.5/reference/htmlsingle/#howto-use-exposing-spring-data-repositories-rest-endpoint)
|
||||
* [Spring Web](https://docs.spring.io/spring-boot/docs/2.4.5/reference/htmlsingle/#boot-features-developing-web-applications)
|
||||
* [Spring Data JPA](https://docs.spring.io/spring-boot/docs/2.4.5/reference/htmlsingle/#boot-features-jpa-and-spring-data)
|
||||
* [Spring Boot DevTools](https://docs.spring.io/spring-boot/docs/2.4.5/reference/htmlsingle/#using-boot-devtools)
|
||||
|
||||
**项目描述:**
|
||||
### Guides
|
||||
|
||||
主要用于博主分享学习经验,书写 技术文章,笔记以及日常生活的记录。
|
||||
The following guides illustrate how to use some features concretely:
|
||||
|
||||
**涉及技术:**
|
||||
* [Accessing JPA Data with REST](https://spring.io/guides/gs/accessing-data-rest/)
|
||||
* [Accessing Neo4j Data with REST](https://spring.io/guides/gs/accessing-neo4j-data-rest/)
|
||||
* [Accessing MongoDB Data with REST](https://spring.io/guides/gs/accessing-mongodb-data-rest/)
|
||||
* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/)
|
||||
* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/)
|
||||
* [Building REST services with Spring](https://spring.io/guides/tutorials/bookmarks/)
|
||||
* [Accessing Data with JPA](https://spring.io/guides/gs/accessing-data-jpa/)
|
||||
* [Accessing data with MySQL](https://spring.io/guides/gs/accessing-data-mysql/)
|
||||
|
||||
```java
|
||||
前端: Semantic-UI框架
|
||||
后端: JDK1.8+SpringBoot+ Spring Data JPA +MySQL5.7
|
||||
```
|
||||
### See Links
|
||||
|
||||
**项目介绍:**
|
||||
* https://zyue.wiki/articles/2019/01/05/1546684795983.htmlhttps://scans.gradle.com#gradle)
|
||||
* https://github.com/lizhongyue248/spring-boot-restful-api
|
||||
|
||||
1、整个项目前端采用 Semantic-UI,后端基于 SpringBoot,分为:
|
||||
|
||||
- 前台展示
|
||||
|
||||
首页、分类、标签、 归档、站长信息、搜索详情页、博客详情页
|
||||
|
||||
- 后台管理
|
||||
|
||||
登录、欢迎页、博客管理、新增/编辑博客、 分类管理、分类编辑/新增、标签管理
|
||||
|
||||
2、密码加密采用 MD5 进行加密,使得项目安全性有所提高。
|
||||
|
||||
3、博客编辑页面采用 Markdown 放行进行书写,集成了 Markdown 编辑器插件。期间使用 MarkdownUtil 工具将 Markdown 转化成 HTML 格式。
|
||||
|
||||
4、使用 CommentUtil 工具类以及 Semantic-UI 中自带的留言组件实现评论功能,让评论显示为层级
|
||||
|
||||
5、采用 SpringData JAP 连接数据库,简化 SQL 编写方式。
|
||||
|
||||
**项目收获:**
|
||||
|
||||
整个项目部署和测试阶段的调试 通过该项目的开发,让我对项目开发的整体流程有了一个全面的了解,加深了我对前后
|
||||
|
||||
端的技术栈的 掌握,以及使我能够独立部署项目,Linux 服务器相关操作更佳熟练。对自己的代码有了更佳严格的要求、 有了不同的
|
||||
|
||||
代码和业务思想,巩固了后端技术栈的知识,对代程序编写有更加深刻的认识!
|
||||
|
||||
## 感谢
|
||||
|
||||
原作者Github:https://github.com/yerenping/blog
|
||||
40
build.gradle
Normal file
@ -0,0 +1,40 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.4.5'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id 'java'
|
||||
}
|
||||
|
||||
group = 'com.example'
|
||||
version = '0.0.1-SNAPSHOT'
|
||||
sourceCompatibility = '1.8'
|
||||
|
||||
configurations {
|
||||
compileOnly {
|
||||
extendsFrom annotationProcessor
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
// 单个项目有效
|
||||
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/'}
|
||||
maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'}
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
//implementation 'org.springframework.boot:spring-boot-starter-data-rest'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||
// 显示完整sql
|
||||
implementation 'p6spy:p6spy:3.7.0'
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||
runtimeOnly 'mysql:mysql-connector-java'
|
||||
annotationProcessor 'org.projectlombok:lombok'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
185
gradlew
vendored
Normal file
@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
89
gradlew.bat
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
156
pom.xml
@ -1,156 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>cn.allms</groupId>
|
||||
<artifactId>blog</artifactId>
|
||||
<version>1.0.0-RELEASE</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>blog</name>
|
||||
<description>Demo project for Spring Boot</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.3.0.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>public</id>
|
||||
<name>aliyun nexus</name>
|
||||
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>public</id>
|
||||
<name>aliyun nexus</name>
|
||||
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!--jpa-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<!--thymeleaf-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
<!--web-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<!--devtools-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!--mysql-->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<!--lombok-->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!--test-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!--aop-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<!--引入Markdown转HTML的插件-->
|
||||
<dependency>
|
||||
<groupId>com.atlassian.commonmark</groupId>
|
||||
<artifactId>commonmark</artifactId>
|
||||
<version>0.10.0</version>
|
||||
</dependency>
|
||||
<!--扩展 标题-->
|
||||
<dependency>
|
||||
<groupId>com.atlassian.commonmark</groupId>
|
||||
<artifactId>commonmark-ext-heading-anchor</artifactId>
|
||||
<version>0.10.0</version>
|
||||
</dependency>
|
||||
<!--扩展 表格-->
|
||||
<dependency>
|
||||
<groupId>com.atlassian.commonmark</groupId>
|
||||
<artifactId>commonmark-ext-gfm-tables</artifactId>
|
||||
<version>0.10.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>5.3.5.Final</version>
|
||||
</dependency>
|
||||
<!--配置文件:注解-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
</dependency>
|
||||
<!--服务监控-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<!--fastjson-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.35</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.3.0.RELEASE</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
1
settings.gradle
Normal file
@ -0,0 +1 @@
|
||||
rootProject.name = 'demo-rest'
|
||||
@ -1,98 +0,0 @@
|
||||
package cn.allms.aspect;
|
||||
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author josxy
|
||||
*/
|
||||
@Component
|
||||
public class LogAspectOld {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
/**
|
||||
* 切点:cn.allms.controller
|
||||
*/
|
||||
//@Pointcut("execution(* cn.allms.controller.*.*(..))")
|
||||
public void log() {
|
||||
}
|
||||
|
||||
|
||||
// @Before("log()")
|
||||
public void doBefore(JoinPoint joinPoint) {
|
||||
// 获取request对象
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
assert attributes != null;
|
||||
HttpServletRequest request = attributes.getRequest();
|
||||
// URL
|
||||
String url = request.getRequestURL().toString();
|
||||
// IP
|
||||
String ip = request.getRemoteAddr();
|
||||
// 方法全名 = 类名.方法名
|
||||
String classMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
|
||||
// 请求对象
|
||||
Object[] args = joinPoint.getArgs();
|
||||
RequestLog requestLog = new RequestLog(url, ip, classMethod, args);
|
||||
|
||||
logger.info("Request : {}", requestLog);
|
||||
}
|
||||
|
||||
//@After("log()")
|
||||
public void doAfter() {
|
||||
// logger.info("-------doafter-----------");
|
||||
}
|
||||
|
||||
public void doAfterReturn(Object result) {
|
||||
logger.info("控制器方法名称Result : {}", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部类:用于存放请求信息,用日志的方式将其记录下来
|
||||
*/
|
||||
private class RequestLog {
|
||||
/**
|
||||
* 请求地址
|
||||
*/
|
||||
private String url;
|
||||
/**
|
||||
* 请求ip
|
||||
*/
|
||||
private String ip;
|
||||
/**
|
||||
* 请求方法
|
||||
*/
|
||||
private String classMethod;
|
||||
/**
|
||||
* 请求参数集合
|
||||
*/
|
||||
private Object[] args;
|
||||
|
||||
public RequestLog(String url, String ip, String classMethod, Object[] args) {
|
||||
this.url = url;
|
||||
this.ip = ip;
|
||||
this.classMethod = classMethod;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RequestLog{" +
|
||||
"url='" + url + '\'' +
|
||||
", ip='" + ip + '\'' +
|
||||
", classMethod='" + classMethod + '\'' +
|
||||
", args=" + Arrays.toString(args) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
package cn.allms.config;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 日志
|
||||
*
|
||||
* @author rainerosion
|
||||
* @date 2021/4/9 19:11
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@Aspect
|
||||
public class LogAspect {
|
||||
@Pointcut("execution(* cn.allms.controller.*.*(..))")
|
||||
public void webLog() {
|
||||
}
|
||||
|
||||
@Before("webLog()")
|
||||
public void doBefore(JoinPoint joinPoint) {
|
||||
// 开始打印请求日志
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request = attributes.getRequest();
|
||||
|
||||
// 打印请求相关参数
|
||||
log.info("========================================== Start ==========================================");
|
||||
// 打印请求 url
|
||||
log.info("[请求URL] : {}", request.getRequestURL().toString());
|
||||
// 打印 Http method
|
||||
log.info("[请求方法] : {}", request.getMethod());
|
||||
// 打印调用 controller 的全路径以及执行方法
|
||||
log.info("[请求类名] : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
|
||||
// 打印请求的 IP
|
||||
log.info("[请求IP] : {}", request.getRemoteAddr());
|
||||
// 打印请求入参
|
||||
log.info("[请求参数] : {}", JSONObject.toJSONString(joinPoint.getArgs()));
|
||||
}
|
||||
|
||||
@Around("webLog()")
|
||||
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
|
||||
long startTime = System.currentTimeMillis();
|
||||
Object result = proceedingJoinPoint.proceed();
|
||||
// 打印出参
|
||||
log.info("[响应结果] : {}", JSONObject.toJSONString(result));
|
||||
// 执行耗时
|
||||
log.info("[请求耗时] : {} ms", System.currentTimeMillis() - startTime);
|
||||
log.info("=========================================== End ===========================================");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
package cn.allms.config;
|
||||
|
||||
import cn.allms.interceptor.LoginInterceptor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
/**
|
||||
* 配置类
|
||||
*/
|
||||
@Configuration
|
||||
public class MyConfig extends WebMvcConfigurerAdapter {
|
||||
|
||||
//重写拦截器
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(new LoginInterceptor())
|
||||
.addPathPatterns("/admin/**")
|
||||
.excludePathPatterns("/admin")
|
||||
.excludePathPatterns("/admin/login");
|
||||
}
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
package cn.allms.config;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
/**
|
||||
* 随机图片配置类
|
||||
*
|
||||
* @author josxy
|
||||
*/
|
||||
@Data
|
||||
public class RandomPicturesConfig {
|
||||
private List<String> pictures;
|
||||
private final static String DEFAULT = "https://tva1.sinaimg.cn/large/0072Vf1pgy1foxk3rxvthj31kw0w0x3c";
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* 随机获取一种图片
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getRandomPicAddr() {
|
||||
Random random = new Random();
|
||||
System.out.println(this.pictures);
|
||||
System.out.println(this.pictures.get(random.nextInt(2)) + System.currentTimeMillis());
|
||||
return this.pictures.size() > 0 ?
|
||||
this.pictures.get(random.nextInt(2)) + System.currentTimeMillis() : DEFAULT;
|
||||
}
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
package cn.allms.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/10/12
|
||||
* @Description: com.yrp.controller
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Controller
|
||||
public class AboutShowController {
|
||||
@GetMapping("/about")
|
||||
public String about() {
|
||||
return "about";
|
||||
}
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
package cn.allms.controller;
|
||||
|
||||
import cn.allms.service.BlogService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/10/15
|
||||
* @Description: com.yrp.controller.admin
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Controller
|
||||
public class ArchiveShowController {
|
||||
@Autowired
|
||||
private BlogService blogServiceImpl;
|
||||
|
||||
|
||||
@GetMapping("/archives")
|
||||
public String archives(Model model) {
|
||||
model.addAttribute("archiveMap", blogServiceImpl.archiveBlog());
|
||||
model.addAttribute("blogCount", blogServiceImpl.countBlog());
|
||||
return "archives";
|
||||
}
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
package cn.allms.controller;
|
||||
|
||||
import cn.allms.po.User;
|
||||
import cn.allms.po.Comment;
|
||||
import cn.allms.service.BlogService;
|
||||
import cn.allms.service.CommentService;
|
||||
import cn.allms.util.MD5Utils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* 评论
|
||||
*/
|
||||
@Controller
|
||||
public class CommentController {
|
||||
|
||||
@Autowired
|
||||
private CommentService commentServiceImpl;
|
||||
|
||||
@Autowired
|
||||
private BlogService blogServiceImpl;
|
||||
|
||||
@Value("${comment.avatar}")
|
||||
private String avatar;
|
||||
|
||||
@Value("${comment.v2exUrl}")
|
||||
private String v2exUrl;
|
||||
|
||||
/**
|
||||
* 显示评论列表
|
||||
*
|
||||
* @param blogId
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/comments/{blogId}")
|
||||
public String comments(@PathVariable Long blogId, Model model) {
|
||||
model.addAttribute("comments", commentServiceImpl.listCommentByBlogId(blogId));
|
||||
return "blog :: commentList";
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交评论
|
||||
*
|
||||
* @param comment
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/comments")
|
||||
public String post(Comment comment, HttpSession session) {
|
||||
Long blogId = comment.getBlog().getId();
|
||||
//处理评论和博客之间的关系
|
||||
comment.setBlog(blogServiceImpl.getBlog(blogId));
|
||||
User user = (User) session.getAttribute("user");
|
||||
//管理员发
|
||||
if (user != null) {
|
||||
comment.setAvatar(user.getAvatar());
|
||||
comment.setAdminComment(true);
|
||||
comment.setNickname(user.getNickname());
|
||||
comment.setEmail(user.getEmail());
|
||||
//普通用户
|
||||
} else {
|
||||
comment.setAvatar(v2exUrl + MD5Utils.code(comment.getEmail()));
|
||||
}
|
||||
commentServiceImpl.saveComment(comment);
|
||||
return "redirect:/comments/" + blogId;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,80 +0,0 @@
|
||||
package cn.allms.controller;
|
||||
|
||||
import cn.allms.service.BlogService;
|
||||
import cn.allms.service.TagService;
|
||||
import cn.allms.service.TypeService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
/**
|
||||
* 首页index.html
|
||||
*/
|
||||
@Controller
|
||||
public class IndexController {
|
||||
|
||||
@Autowired
|
||||
private BlogService blogServiceImpl;
|
||||
|
||||
@Autowired
|
||||
private TypeService typeServiceImpl;
|
||||
|
||||
@Autowired
|
||||
private TagService tagServiceImpl;
|
||||
|
||||
/**
|
||||
* 首页面显示
|
||||
*
|
||||
* @param model
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/")
|
||||
public String index(Model model, @PageableDefault(size = 8, sort = {"updateTime"}, direction = Sort.Direction.DESC)
|
||||
Pageable pageable) {
|
||||
//1. 获取分页的博客列表
|
||||
model.addAttribute("page", blogServiceImpl.ListBlog(pageable));
|
||||
//2. 获取分类的内容(显示6条)
|
||||
model.addAttribute("types", typeServiceImpl.listTypeTop(6));
|
||||
//3. 获取标签的内容
|
||||
model.addAttribute("tags", tagServiceImpl.ListTagTop(10));
|
||||
//4. 显示推荐博客列表
|
||||
model.addAttribute("recommendBlogs", blogServiceImpl.listRecommendBlogTop(8));
|
||||
return "index";
|
||||
}
|
||||
|
||||
/**
|
||||
* 导航栏中的搜索功能实现
|
||||
*
|
||||
* @param pageable
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/search")
|
||||
public String search(@PageableDefault(size = 8, sort = {"updateTime"}, direction = Sort.Direction.DESC) Pageable pageable,
|
||||
@RequestParam String query, Model model) {
|
||||
model.addAttribute("page", blogServiceImpl.ListBlog(pageable, "%" + query + "%"));
|
||||
model.addAttribute("query", query);
|
||||
return "search";
|
||||
}
|
||||
|
||||
@GetMapping("/blog/{id}")
|
||||
public String blog(@PathVariable("id") Long id, Model model) {
|
||||
model.addAttribute("blog", blogServiceImpl.getAadConvertBlog(id));
|
||||
return "blog";
|
||||
}
|
||||
|
||||
@GetMapping("/footer/newblog")
|
||||
public String newblos(Model model) {
|
||||
model.addAttribute("newblogs", blogServiceImpl.listRecommendBlogTop(3));
|
||||
return "_fragments :: newblogList";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
package cn.allms.controller;
|
||||
|
||||
|
||||
import cn.allms.po.Tag;
|
||||
import cn.allms.service.TagService;
|
||||
import cn.allms.vo.BlogQuery;
|
||||
import cn.allms.service.BlogService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/10/12
|
||||
* @Description: com.yrp.controller
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Controller
|
||||
public class TagShowController {
|
||||
@Autowired
|
||||
private TagService tagServiceImpl;
|
||||
|
||||
|
||||
@Autowired
|
||||
private BlogService blogServiceImpl;
|
||||
|
||||
|
||||
@GetMapping("/tags/{id}")
|
||||
public String tags(Model model, @PageableDefault(size = 8, sort = {"updateTime"}, direction = Sort.Direction.DESC)
|
||||
@PathVariable Long id, Pageable pageable) {
|
||||
|
||||
List<Tag> tags = tagServiceImpl.ListTagTop(10000);
|
||||
if (id == -1 && tags.size() > 0) {
|
||||
id = tags.get(0).getId();
|
||||
}
|
||||
BlogQuery blogQuery = new BlogQuery();
|
||||
model.addAttribute("tags", tags);
|
||||
model.addAttribute("page", blogServiceImpl.ListBlog(id, pageable));
|
||||
model.addAttribute("avtiveTagId", id);
|
||||
return "tags";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
package cn.allms.controller;
|
||||
|
||||
import cn.allms.po.Type;
|
||||
import cn.allms.service.TypeService;
|
||||
import cn.allms.vo.BlogQuery;
|
||||
import cn.allms.service.BlogService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/10/12
|
||||
* @Description: com.yrp.controller
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Controller
|
||||
public class TypeShowController {
|
||||
@Autowired
|
||||
private TypeService typeServiceImpl;
|
||||
|
||||
|
||||
@Autowired
|
||||
private BlogService blogServiceImpl;
|
||||
|
||||
|
||||
@GetMapping("/types/{id}")
|
||||
public String types(Model model, @PageableDefault(size = 8, sort = {"updateTime"}, direction = Sort.Direction.DESC)
|
||||
@PathVariable Long id, Pageable pageable) {
|
||||
|
||||
List<Type> types = typeServiceImpl.listTypeTop(10000);
|
||||
if (id == -1 && types.size() > 0) {
|
||||
id = types.get(0).getId();
|
||||
}
|
||||
BlogQuery blogQuery = new BlogQuery();
|
||||
blogQuery.setTypeId(id);
|
||||
model.addAttribute("types", types);
|
||||
model.addAttribute("page", blogServiceImpl.ListBlog(pageable, blogQuery));
|
||||
model.addAttribute("avtiveTypeId", id);
|
||||
return "types";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,175 +0,0 @@
|
||||
package cn.allms.controller.admin;
|
||||
|
||||
import cn.allms.config.RandomPicturesConfig;
|
||||
import cn.allms.po.Blog;
|
||||
import cn.allms.po.User;
|
||||
import cn.allms.vo.BlogQuery;
|
||||
import cn.allms.service.BlogService;
|
||||
import cn.allms.service.TagService;
|
||||
import cn.allms.service.TypeService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/10/3
|
||||
* @Description: com.yrp.controller.admin
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("admin")
|
||||
public class BlogController {
|
||||
|
||||
|
||||
/**
|
||||
* 博客发布页面url
|
||||
*/
|
||||
private static final String INPUT = "admin/blogs-input";
|
||||
private static final String HEAD_URL = "https://api.rainss.cn/random.php?t=";
|
||||
private static final String HEAD_URL_1 = "https://api.rainss.cn/acgimgurl/acgurl.php?t=";
|
||||
|
||||
/**
|
||||
* 显示分页查询到的博客列表页面url
|
||||
*/
|
||||
private static final String LIST = "admin/blogs";
|
||||
|
||||
/**
|
||||
* 局部刷新表格查询到的数据url
|
||||
*/
|
||||
private static final String REDIRECT_LIST = "redirect:/admin/blogs";
|
||||
|
||||
@Autowired
|
||||
private BlogService blogServiceImpl;
|
||||
|
||||
@Autowired
|
||||
private TypeService typeServiceImpl;
|
||||
|
||||
@Autowired
|
||||
private TagService tagServiceImpl;
|
||||
|
||||
/**
|
||||
* 分页显示博客列表
|
||||
*
|
||||
* @param model
|
||||
* @param pageable
|
||||
* @param blog
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/blogs")
|
||||
public String showBlogs(Model model, @PageableDefault(size = 8, sort = {"updateTime"}, direction = Sort.Direction.DESC) Pageable pageable, BlogQuery blog) {
|
||||
model.addAttribute("page", blogServiceImpl.ListBlog(pageable, blog));
|
||||
model.addAttribute("types", typeServiceImpl.listType());
|
||||
return LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* 联合查询博客列表
|
||||
*
|
||||
* @param model
|
||||
* @param pageable
|
||||
* @param blog
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/blogs/search")
|
||||
public String searchBlogs(Model model, @PageableDefault(size = 8, sort = {"updateTime"}, direction = Sort.Direction.DESC) Pageable pageable,
|
||||
BlogQuery blog) {
|
||||
model.addAttribute("page", blogServiceImpl.ListBlog(pageable, blog));
|
||||
return "admin/blogs :: blogList";
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增博客页面
|
||||
*
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/blogs/input")
|
||||
public String inputBlog(Model model) {
|
||||
model.addAttribute("firstPicture", HEAD_URL_1 + System.currentTimeMillis());
|
||||
setTypeAadTag(model);
|
||||
return INPUT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 提交博客
|
||||
*
|
||||
* @param blog
|
||||
* @param attributes
|
||||
* @param session
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/blogs")
|
||||
public String post(Blog blog, RedirectAttributes attributes, HttpSession session) {
|
||||
blog.setUser((User) session.getAttribute("user"));
|
||||
blog.setType(typeServiceImpl.getType(blog.getType().getId()));
|
||||
blog.setTags(tagServiceImpl.ListTag(blog.getTagIds()));
|
||||
Blog b;
|
||||
Date date = new Date();
|
||||
//新增博客
|
||||
if (blog.getId() == null) {
|
||||
blog.setUpdateTime(date);
|
||||
blog.setCreateTime(date);
|
||||
blog.setViews(0);
|
||||
b = blogServiceImpl.saveBlog(blog);
|
||||
} else {//更新博客
|
||||
b = blogServiceImpl.updateBlog(blog.getId(), blog);
|
||||
}
|
||||
if (b == null) {
|
||||
attributes.addFlashAttribute("message", "操作失败");
|
||||
} else {
|
||||
attributes.addFlashAttribute("message", "操作成功");
|
||||
}
|
||||
return REDIRECT_LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除博客
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/blogs/{id}/delete")
|
||||
public String deleteBlog(@PathVariable("id") Long id) {
|
||||
blogServiceImpl.deleteBlog(id);
|
||||
return REDIRECT_LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改博客页面
|
||||
*
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/blogs/{id}/input")
|
||||
public String editBlog(@PathVariable("id") Long id, Model model) {
|
||||
setTypeAadTag(model);
|
||||
Blog blog = blogServiceImpl.getBlog(id);
|
||||
//处理tagIds
|
||||
blog.init();
|
||||
model.addAttribute("firstPicture", HEAD_URL_1 + System.currentTimeMillis());
|
||||
model.addAttribute("blog", blog);
|
||||
return INPUT;
|
||||
}
|
||||
|
||||
private void setTypeAadTag(Model model) {
|
||||
/*博客查询,为后面的编辑博客做准备*/
|
||||
model.addAttribute("blog", new Blog());
|
||||
/*分类查询*/
|
||||
model.addAttribute("types", typeServiceImpl.listType());
|
||||
/*标签查询*/
|
||||
model.addAttribute("tags", tagServiceImpl.ListTag());
|
||||
}
|
||||
}
|
||||
@ -1,75 +0,0 @@
|
||||
package cn.allms.controller.admin;
|
||||
|
||||
import cn.allms.po.User;
|
||||
import cn.allms.service.Userservice;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/9/28
|
||||
* @Description: com.yrp.controller.admin
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/admin")
|
||||
public class LoginController {
|
||||
|
||||
@Autowired
|
||||
private Userservice userservice;
|
||||
|
||||
/**
|
||||
* 显示用户登录页面
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping
|
||||
public String loginPage() {
|
||||
return "admin/login";
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
*
|
||||
* @param username
|
||||
* @param password
|
||||
* @param session
|
||||
* @param attributes
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/login")
|
||||
public String login(@RequestParam String username,
|
||||
@RequestParam String password,
|
||||
HttpSession session,
|
||||
RedirectAttributes attributes) {
|
||||
User user = userservice.checkUser(username, password);
|
||||
if (user != null) {
|
||||
user.setPassword(null);
|
||||
session.setAttribute("user", user);
|
||||
return "admin/index";
|
||||
} else {
|
||||
attributes.addFlashAttribute("message", "用户名和密码错误");
|
||||
return "redirect:/admin";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户注销
|
||||
*
|
||||
* @param session
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/logout")
|
||||
public String logout(HttpSession session) {
|
||||
session.removeAttribute("user");
|
||||
return "redirect:/admin";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,134 +0,0 @@
|
||||
package cn.allms.controller.admin;
|
||||
|
||||
|
||||
import cn.allms.po.Tag;
|
||||
import cn.allms.service.TagService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 标签
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/admin")
|
||||
public class TagController {
|
||||
|
||||
@Autowired
|
||||
private TagService tagServiceImpl;
|
||||
|
||||
/**
|
||||
* 分页查询标签列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/tags")
|
||||
public String types(@PageableDefault(size = 8, sort = {"id"}, direction = Sort.Direction.DESC)
|
||||
Pageable pageable, Model model) {
|
||||
model.addAttribute("page", tagServiceImpl.ListTag(pageable));
|
||||
return "admin/tags";
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示添加标签页面
|
||||
*
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/tags/input")
|
||||
public String showInput(Model model) {
|
||||
model.addAttribute("tag", new Tag());
|
||||
return "admin/tags-input";
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增标签
|
||||
*
|
||||
* @param tag
|
||||
* @param result
|
||||
* @param attributes
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/tags")
|
||||
public String post(@Valid Tag tag, BindingResult result, RedirectAttributes attributes) {
|
||||
Tag tag1 = tagServiceImpl.getTagByName(tag.getName());
|
||||
if (tag1 != null) {
|
||||
result.rejectValue("name", "nameError", "不能添加重复的标签");
|
||||
}
|
||||
if (result.hasErrors()) {
|
||||
return "admin/tags-input";
|
||||
}
|
||||
Tag t = tagServiceImpl.saveTag(tag);
|
||||
if (t == null) {
|
||||
attributes.addFlashAttribute("新增失败");
|
||||
} else {
|
||||
attributes.addFlashAttribute("新增成功");
|
||||
}
|
||||
return "redirect:/admin/tags";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示添加标签页面
|
||||
*
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/tags/{id}/input")
|
||||
public String editInput(@PathVariable("id") Long id, Model model) {
|
||||
model.addAttribute("tag", tagServiceImpl.getTag(id));
|
||||
return "admin/tags-input";
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改标签名
|
||||
*
|
||||
* @param tag
|
||||
* @param result
|
||||
* @param id
|
||||
* @param attributes
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/tags/{id}")
|
||||
public String editPost(@Valid Tag tag, BindingResult result, @PathVariable("id") Long id, RedirectAttributes attributes) {
|
||||
Tag tag1 = tagServiceImpl.getTagByName(tag.getName());
|
||||
if (tag1 != null) {
|
||||
result.rejectValue("name", "nameError", "不能添加重复的分类");
|
||||
}
|
||||
if (result.hasErrors()) {
|
||||
return "admin/tags-input";
|
||||
}
|
||||
Tag t = tagServiceImpl.updateTag(id, tag);
|
||||
if (t == null) {
|
||||
attributes.addFlashAttribute("message", "更新失败");
|
||||
} else {
|
||||
attributes.addFlashAttribute("message", "更新成功");
|
||||
}
|
||||
return "redirect:/admin/tags";
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除功能
|
||||
*
|
||||
* @param id
|
||||
* @param attributes
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/tags/{id}/delete")
|
||||
public String deleteById(@PathVariable("id") Long id, RedirectAttributes attributes) {
|
||||
tagServiceImpl.deleteTag(id);
|
||||
attributes.addFlashAttribute("message", "删除成功");
|
||||
return "redirect:/admin/tags";
|
||||
}
|
||||
}
|
||||
@ -1,127 +0,0 @@
|
||||
package cn.allms.controller.admin;
|
||||
|
||||
import cn.allms.po.Type;
|
||||
import cn.allms.service.TypeService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/9/29
|
||||
* @Description: com.yrp.controller.admin
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/admin")
|
||||
public class TypeController {
|
||||
|
||||
@Autowired
|
||||
private TypeService typeServiceImpl;
|
||||
|
||||
/**
|
||||
* 分页查询分类列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/types")
|
||||
public String types(@PageableDefault(size = 8, sort = {"id"}, direction = Sort.Direction.DESC)
|
||||
Pageable pageable, Model model) {
|
||||
model.addAttribute("page", typeServiceImpl.ListType(pageable));
|
||||
return "admin/types";
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示新增页面
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/types/input")
|
||||
public String showInput(Model model) {
|
||||
model.addAttribute("type", new Type());
|
||||
return "admin/types-input";
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增分类
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
||||
@PostMapping("/types")
|
||||
public String post(@Valid Type type, BindingResult result, RedirectAttributes attributes) {
|
||||
//1.判断用户名是有重复
|
||||
Type type1 = typeServiceImpl.getTypeByName(type.getName());
|
||||
if (type1 != null) {
|
||||
result.rejectValue("name", "nameError", "不能添加重复的分类");
|
||||
}
|
||||
//2. 后端校验用户名是否为空
|
||||
if (result.hasErrors()) {
|
||||
return "admin/types-input";
|
||||
}
|
||||
Type t = typeServiceImpl.saveType(type);
|
||||
if (t == null) {
|
||||
attributes.addFlashAttribute("message", "新增失败");
|
||||
} else {
|
||||
attributes.addFlashAttribute("message", "新增成功");
|
||||
}
|
||||
return "redirect:/admin/types";
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到修改分类页面
|
||||
*
|
||||
* @param id
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/types/{id}/input")
|
||||
public String editInput(@PathVariable("id") Long id, Model model) {
|
||||
model.addAttribute("type", typeServiceImpl.getType(id));
|
||||
return "admin/types-input";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改分类
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
||||
@PostMapping("/types/{id}")
|
||||
public String editPost(@Valid Type type, BindingResult result, @PathVariable Long id, RedirectAttributes attributes) {
|
||||
Type type1 = typeServiceImpl.getTypeByName(type.getName());
|
||||
if (type1 != null) {
|
||||
result.rejectValue("name", "nameError", "不能添加重复的分类");
|
||||
}
|
||||
|
||||
if (result.hasErrors()) {
|
||||
return "admin/types-input";
|
||||
}
|
||||
Type t = typeServiceImpl.updateType(id, type);
|
||||
if (t == null) {
|
||||
attributes.addFlashAttribute("message", "更新失败");
|
||||
} else {
|
||||
attributes.addFlashAttribute("message", "更新成功");
|
||||
}
|
||||
return "redirect:/admin/types";
|
||||
}
|
||||
|
||||
@GetMapping("/types/{id}/delete")
|
||||
public String deleteTypeById(@PathVariable("id") Long id, RedirectAttributes attributes) {
|
||||
typeServiceImpl.deleteType(id);
|
||||
attributes.addFlashAttribute("message", "删除成功");
|
||||
return "redirect:/admin/types";
|
||||
}
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
package cn.allms.dao;
|
||||
|
||||
import cn.allms.po.Blog;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/10/3
|
||||
* @Description: com.yrp.dao
|
||||
* @version: 1.0
|
||||
*/
|
||||
|
||||
public interface BlogRepository extends JpaRepository<Blog, Long>, JpaSpecificationExecutor<Blog> {
|
||||
|
||||
@Query("select b from Blog b where b.recommend = true")
|
||||
List<Blog> findTop(Pageable pageable);
|
||||
|
||||
@Query("select b from Blog b where b.title like ?1 or b.content like ?1")
|
||||
Page<Blog> findByQuery(String query, Pageable pageable);
|
||||
|
||||
@Transactional
|
||||
@Modifying
|
||||
@Query("update Blog b set b.views= b.views+1 where b.id = ?1")
|
||||
int updateViews(Long id);
|
||||
|
||||
@Query("select function('date_format',b.updateTime,'%Y') as year from Blog b group by function('date_format',b.updateTime,'%Y') order by year desc ")
|
||||
List<String> findGroupYear();
|
||||
|
||||
@Query("select b from Blog b where function('date_format',b.updateTime,'%Y') = ?1")
|
||||
List<Blog> findByYear(String year);
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
package cn.allms.dao;
|
||||
|
||||
|
||||
import cn.allms.po.Comment;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/9/28
|
||||
* @Description: com.yrp.dao
|
||||
* @version: 1.0
|
||||
*/
|
||||
public interface CommentRepository extends JpaRepository<Comment, Long> {
|
||||
|
||||
List<Comment> findByBlogIdAndParentCommentNull(Long blogId, Sort sort);
|
||||
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
package cn.allms.dao;
|
||||
|
||||
import cn.allms.po.Tag;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 标签
|
||||
*/
|
||||
public interface TagRepository extends JpaRepository<Tag, Long> {
|
||||
Tag findByName(String name);
|
||||
|
||||
|
||||
@Query("select t from Tag t")
|
||||
List<Tag> findTop(Pageable pageable);
|
||||
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
package cn.allms.dao;
|
||||
|
||||
import cn.allms.po.Type;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/9/29
|
||||
* @Description: com.yrp.dao
|
||||
* @version: 1.0
|
||||
*/
|
||||
public interface TypeRepository extends JpaRepository<Type, Long> {
|
||||
|
||||
Type findByName(String name);
|
||||
|
||||
|
||||
/**
|
||||
* 查询type按照分页的方式
|
||||
*
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
@Query("select t from Type t")
|
||||
List<Type> findTop(Pageable pageable);
|
||||
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package cn.allms.dao;
|
||||
|
||||
import cn.allms.po.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/9/28
|
||||
* @Description: com.yrp.dao
|
||||
* @version: 1.0
|
||||
*/
|
||||
public interface UserRepository extends JpaRepository<User, Long> {
|
||||
/**
|
||||
* 通过用户名和密码查询用户
|
||||
*
|
||||
* @param username
|
||||
* @param password
|
||||
* @return
|
||||
*/
|
||||
User findByUsernameAndPassword(String username, String password);
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
package cn.allms.exception;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* 博客为空的异常
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||
public class NotFoundException extends RuntimeException {
|
||||
public NotFoundException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public NotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public NotFoundException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
package cn.allms.handler;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@ControllerAdvice
|
||||
public class ControllerExceptionHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ControllerExceptionHandler.class);
|
||||
|
||||
/**
|
||||
* 异常处理
|
||||
*
|
||||
* @param request
|
||||
* @param e
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler({Exception.class})
|
||||
public ModelAndView handleException(HttpServletRequest request, Exception e) throws Exception {
|
||||
|
||||
logger.error("Request URL : {} , Exception : {}", request.getRequestURL(), e);
|
||||
|
||||
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) {
|
||||
throw e;
|
||||
}
|
||||
ModelAndView mav = new ModelAndView();
|
||||
mav.addObject("url", request.getRequestURL());
|
||||
mav.addObject("exception", e);
|
||||
mav.setViewName("error/error");
|
||||
|
||||
return mav;
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
package cn.allms.interceptor;
|
||||
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* 登录拦截器
|
||||
*/
|
||||
public class LoginInterceptor extends HandlerInterceptorAdapter {
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
Object handler) throws Exception {
|
||||
//1. 用户未登录
|
||||
if (request.getSession().getAttribute("user") == null) {
|
||||
response.sendRedirect("/admin");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1,250 +0,0 @@
|
||||
package cn.allms.po;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "t_blog")
|
||||
public class Blog {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
private String title;
|
||||
@Basic(fetch = FetchType.LAZY)
|
||||
@Lob
|
||||
private String content;
|
||||
private String firstPicture;
|
||||
private String flag;
|
||||
private Integer views;
|
||||
private boolean appreciation;
|
||||
private boolean shareStatement;
|
||||
private boolean commentabled;
|
||||
private boolean published;
|
||||
private boolean recommend;
|
||||
private String description;
|
||||
@Transient
|
||||
private String tagIds;
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date createTime;
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date updateTime;
|
||||
|
||||
@ManyToOne
|
||||
private Type type;
|
||||
|
||||
@ManyToMany(cascade = {CascadeType.PERSIST})
|
||||
private List<Tag> tags = new ArrayList<>();
|
||||
|
||||
|
||||
@ManyToOne
|
||||
private User user;
|
||||
|
||||
@OneToMany(mappedBy = "blog")
|
||||
private List<Comment> comments = new ArrayList<>();
|
||||
|
||||
|
||||
public void init() {
|
||||
this.tagIds = tagsToIds(this.getTags());
|
||||
}
|
||||
|
||||
//1,2,3
|
||||
private String tagsToIds(List<Tag> tags) {
|
||||
if (!tags.isEmpty()) {
|
||||
StringBuffer ids = new StringBuffer();
|
||||
boolean flag = false;
|
||||
for (Tag tag : tags) {
|
||||
if (flag) {
|
||||
ids.append(",");
|
||||
} else {
|
||||
flag = true;
|
||||
}
|
||||
ids.append(tag.getId());
|
||||
}
|
||||
return ids.toString();
|
||||
} else {
|
||||
return tagIds;
|
||||
}
|
||||
}
|
||||
|
||||
public Blog() {
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getFirstPicture() {
|
||||
return firstPicture;
|
||||
}
|
||||
|
||||
public void setFirstPicture(String firstPicture) {
|
||||
this.firstPicture = firstPicture;
|
||||
}
|
||||
|
||||
public String getFlag() {
|
||||
return flag;
|
||||
}
|
||||
|
||||
public void setFlag(String flag) {
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
public Integer getViews() {
|
||||
return views;
|
||||
}
|
||||
|
||||
public void setViews(Integer views) {
|
||||
this.views = views;
|
||||
}
|
||||
|
||||
public boolean isAppreciation() {
|
||||
return appreciation;
|
||||
}
|
||||
|
||||
public void setAppreciation(boolean appreciation) {
|
||||
this.appreciation = appreciation;
|
||||
}
|
||||
|
||||
public boolean isShareStatement() {
|
||||
return shareStatement;
|
||||
}
|
||||
|
||||
public void setShareStatement(boolean shareStatement) {
|
||||
this.shareStatement = shareStatement;
|
||||
}
|
||||
|
||||
public boolean isCommentabled() {
|
||||
return commentabled;
|
||||
}
|
||||
|
||||
public void setCommentabled(boolean commentabled) {
|
||||
this.commentabled = commentabled;
|
||||
}
|
||||
|
||||
public boolean isPublished() {
|
||||
return published;
|
||||
}
|
||||
|
||||
public void setPublished(boolean published) {
|
||||
this.published = published;
|
||||
}
|
||||
|
||||
public boolean isRecommend() {
|
||||
return recommend;
|
||||
}
|
||||
|
||||
public void setRecommend(boolean recommend) {
|
||||
this.recommend = recommend;
|
||||
}
|
||||
|
||||
public Date getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public Date getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public void setUpdateTime(Date updateTime) {
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public List<Tag> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public void setTags(List<Tag> tags) {
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public List<Comment> getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public void setComments(List<Comment> comments) {
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
public String getTagIds() {
|
||||
return tagIds;
|
||||
}
|
||||
|
||||
public void setTagIds(String tagIds) {
|
||||
this.tagIds = tagIds;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Blog{" +
|
||||
"id=" + id +
|
||||
", title='" + title + '\'' +
|
||||
", content='" + content + '\'' +
|
||||
", firstPicture='" + firstPicture + '\'' +
|
||||
", flag='" + flag + '\'' +
|
||||
", views=" + views +
|
||||
", appreciation=" + appreciation +
|
||||
", shareStatement=" + shareStatement +
|
||||
", commentabled=" + commentabled +
|
||||
", published=" + published +
|
||||
", recommend=" + recommend +
|
||||
", description='" + description + '\'' +
|
||||
", tagIds='" + tagIds + '\'' +
|
||||
", createTime=" + createTime +
|
||||
", updateTime=" + updateTime +
|
||||
", type=" + type +
|
||||
", tags=" + tags +
|
||||
", user=" + user +
|
||||
", comments=" + comments +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -1,133 +0,0 @@
|
||||
package cn.allms.po;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "t_comment")
|
||||
public class Comment {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
private String nickname;
|
||||
private String email;
|
||||
private String content;
|
||||
private String avatar;
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date createTime;
|
||||
|
||||
@ManyToOne
|
||||
private Blog blog;
|
||||
|
||||
@OneToMany(mappedBy = "parentComment")
|
||||
private List<Comment> replyComments = new ArrayList<>();
|
||||
|
||||
@ManyToOne
|
||||
private Comment parentComment;
|
||||
|
||||
|
||||
private boolean adminComment;
|
||||
|
||||
|
||||
public Comment() {
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
public void setAvatar(String avatar) {
|
||||
this.avatar = avatar;
|
||||
}
|
||||
|
||||
public Date getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public Blog getBlog() {
|
||||
return blog;
|
||||
}
|
||||
|
||||
public void setBlog(Blog blog) {
|
||||
this.blog = blog;
|
||||
}
|
||||
|
||||
public List<Comment> getReplyComments() {
|
||||
return replyComments;
|
||||
}
|
||||
|
||||
public void setReplyComments(List<Comment> replyComments) {
|
||||
this.replyComments = replyComments;
|
||||
}
|
||||
|
||||
public Comment getParentComment() {
|
||||
return parentComment;
|
||||
}
|
||||
|
||||
public void setParentComment(Comment parentComment) {
|
||||
this.parentComment = parentComment;
|
||||
}
|
||||
|
||||
public boolean isAdminComment() {
|
||||
return adminComment;
|
||||
}
|
||||
|
||||
public void setAdminComment(boolean adminComment) {
|
||||
this.adminComment = adminComment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Comment{" +
|
||||
"id=" + id +
|
||||
", nickname='" + nickname + '\'' +
|
||||
", email='" + email + '\'' +
|
||||
", content='" + content + '\'' +
|
||||
", avatar='" + avatar + '\'' +
|
||||
", createTime=" + createTime +
|
||||
", blog=" + blog +
|
||||
", replyComments=" + replyComments +
|
||||
", parentComment=" + parentComment +
|
||||
", adminComment=" + adminComment +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
package cn.allms.po;
|
||||
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by limi on 2017/10/14.
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "t_tag")
|
||||
public class Tag {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
@NotBlank(message = "标签名不能为空")
|
||||
private String name;
|
||||
|
||||
@ManyToMany(mappedBy = "tags")
|
||||
private List<Blog> blogs = new ArrayList<>();
|
||||
|
||||
public Tag() {
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Blog> getBlogs() {
|
||||
return blogs;
|
||||
}
|
||||
|
||||
public void setBlogs(List<Blog> blogs) {
|
||||
this.blogs = blogs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Tag{" +
|
||||
"id=" + id +
|
||||
", name='" + name + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
package cn.allms.po;
|
||||
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "t_type")
|
||||
public class Type {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
@NotBlank(message = "分类名不能为空")
|
||||
private String name;
|
||||
|
||||
@OneToMany(mappedBy = "type")
|
||||
private List<Blog> blogs = new ArrayList<>();
|
||||
|
||||
public Type() {
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Blog> getBlogs() {
|
||||
return blogs;
|
||||
}
|
||||
|
||||
public void setBlogs(List<Blog> blogs) {
|
||||
this.blogs = blogs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Type{" +
|
||||
"id=" + id +
|
||||
", name='" + name + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -1,127 +0,0 @@
|
||||
package cn.allms.po;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "t_user")
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
private String nickname;
|
||||
private String username;
|
||||
private String password;
|
||||
private String email;
|
||||
private String avatar;
|
||||
private Integer type;
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date createTime;
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date updateTime;
|
||||
|
||||
@OneToMany(mappedBy = "user")
|
||||
private List<Blog> blogs = new ArrayList<>();
|
||||
|
||||
public User() {
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
public void setAvatar(String avatar) {
|
||||
this.avatar = avatar;
|
||||
}
|
||||
|
||||
public Integer getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(Integer type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Date getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public Date getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public void setUpdateTime(Date updateTime) {
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
|
||||
|
||||
public List<Blog> getBlogs() {
|
||||
return blogs;
|
||||
}
|
||||
|
||||
public void setBlogs(List<Blog> blogs) {
|
||||
this.blogs = blogs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "User{" +
|
||||
"id=" + id +
|
||||
", nickname='" + nickname + '\'' +
|
||||
", username='" + username + '\'' +
|
||||
", password='" + password + '\'' +
|
||||
", email='" + email + '\'' +
|
||||
", avatar='" + avatar + '\'' +
|
||||
", type=" + type +
|
||||
", createTime=" + createTime +
|
||||
", updateTime=" + updateTime +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -1,106 +0,0 @@
|
||||
package cn.allms.service;
|
||||
|
||||
import cn.allms.po.Blog;
|
||||
import cn.allms.vo.BlogQuery;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/10/3
|
||||
* @Description: com.yrp.po
|
||||
* @version: 1.0
|
||||
*/
|
||||
public interface BlogService {
|
||||
/**
|
||||
* 通过id查询单条博客
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
Blog getBlog(Long id);
|
||||
|
||||
/**
|
||||
* 通过id查询单条博客(前端使用)
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
Blog getAadConvertBlog(Long id);
|
||||
|
||||
|
||||
/**
|
||||
* 分页查询博客
|
||||
*
|
||||
* @param pageable
|
||||
* @param blog
|
||||
* @return
|
||||
*/
|
||||
Page<Blog> ListBlog(Pageable pageable, BlogQuery blog);
|
||||
|
||||
/**
|
||||
* 分页查询显示博客列表
|
||||
*
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
Page<Blog> ListBlog(Pageable pageable);
|
||||
|
||||
|
||||
Page<Blog> ListBlog(Long tagId, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 模糊查询分页显示博客列表
|
||||
*
|
||||
* @param pageable
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
Page<Blog> ListBlog(Pageable pageable, String query);
|
||||
|
||||
/**
|
||||
* 显示推荐的博客列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<Blog> listRecommendBlogTop(Integer size);
|
||||
|
||||
/**
|
||||
* 显示归档信息
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Map<String, List<Blog>> archiveBlog();
|
||||
|
||||
|
||||
Long countBlog();
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*
|
||||
* @param blog
|
||||
* @return
|
||||
*/
|
||||
Blog saveBlog(Blog blog);
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*
|
||||
* @param id
|
||||
* @param blog
|
||||
* @return
|
||||
*/
|
||||
Blog updateBlog(Long id, Blog blog);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
void deleteBlog(Long id);
|
||||
|
||||
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
package cn.allms.service;
|
||||
|
||||
|
||||
import cn.allms.po.Comment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 评论
|
||||
*/
|
||||
public interface CommentService {
|
||||
|
||||
/**
|
||||
* 通过id查询评论列表
|
||||
*
|
||||
* @param blogId
|
||||
* @return
|
||||
*/
|
||||
List<Comment> listCommentByBlogId(Long blogId);
|
||||
|
||||
/**
|
||||
* 保存评论信息
|
||||
*
|
||||
* @param comment
|
||||
* @return
|
||||
*/
|
||||
Comment saveComment(Comment comment);
|
||||
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
package cn.allms.service;
|
||||
|
||||
import cn.allms.po.Tag;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分类管理接口
|
||||
*/
|
||||
public interface TagService {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Tag saveTag(Tag tag);
|
||||
|
||||
|
||||
/**
|
||||
* 单个查询
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
Tag getTag(Long id);
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
Page<Tag> ListTag(Pageable pageable);
|
||||
|
||||
|
||||
List<Tag> ListTagTop(Integer size);
|
||||
|
||||
/**
|
||||
* 查询所有标签
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<Tag> ListTag();
|
||||
|
||||
List<Tag> ListTag(String ids);
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*
|
||||
* @param id
|
||||
* @param tag
|
||||
* @return
|
||||
*/
|
||||
Tag updateTag(Long id, Tag tag);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
void deleteTag(Long id);
|
||||
|
||||
/**
|
||||
* 通过分类名称
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Tag getTagByName(String name);
|
||||
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
package cn.allms.service;
|
||||
|
||||
import cn.allms.po.Type;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分类管理接口
|
||||
*/
|
||||
public interface TypeService {
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Type saveType(Type type);
|
||||
|
||||
|
||||
/**
|
||||
* 单个查询
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
Type getType(Long id);
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param pageable
|
||||
* @return
|
||||
*/
|
||||
Page<Type> ListType(Pageable pageable);
|
||||
|
||||
/**
|
||||
* 查询所有分类
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<Type> listType();
|
||||
|
||||
|
||||
List<Type> listTypeTop(Integer size);
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*
|
||||
* @param id
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
Type updateType(Long id, Type type);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
void deleteType(Long id);
|
||||
|
||||
/**
|
||||
* 通过分类名称查询分类
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Type getTypeByName(String name);
|
||||
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package cn.allms.service;
|
||||
|
||||
import cn.allms.po.User;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/9/28
|
||||
* @Description: com.yrp.service
|
||||
* @version: 1.0
|
||||
*/
|
||||
public interface Userservice {
|
||||
|
||||
/**
|
||||
* 用户登录检测
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
User checkUser(String username, String password);
|
||||
|
||||
}
|
||||
@ -1,168 +0,0 @@
|
||||
package cn.allms.service.impl;
|
||||
|
||||
import cn.allms.po.Blog;
|
||||
import cn.allms.vo.BlogQuery;
|
||||
import cn.allms.exception.NotFoundException;
|
||||
import cn.allms.dao.BlogRepository;
|
||||
import cn.allms.service.BlogService;
|
||||
import cn.allms.po.Type;
|
||||
import cn.allms.util.MarkdownUtils;
|
||||
import cn.allms.util.MyBeanUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.persistence.criteria.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/10/3
|
||||
* @Description: com.yrp.service.impl
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Service
|
||||
public class BlogServiceImpl implements BlogService {
|
||||
|
||||
@Autowired
|
||||
private BlogRepository blogRepository;
|
||||
|
||||
|
||||
@Override
|
||||
public Blog getBlog(Long id) {
|
||||
return blogRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Blog getAadConvertBlog(Long id) {
|
||||
Blog blog = blogRepository.findById(id).orElse(null);
|
||||
if (blog == null) {
|
||||
throw new NotFoundException("该博客不存在!");
|
||||
}
|
||||
Blog b = new Blog();
|
||||
BeanUtils.copyProperties(blog, b);
|
||||
b.setContent(MarkdownUtils.markdownToHtmlExtensions(b.getContent()));
|
||||
blogRepository.updateViews(id);
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Blog> ListBlog(Pageable pageable, BlogQuery blog) {
|
||||
return blogRepository.findAll(new Specification<Blog>() {
|
||||
/**
|
||||
*
|
||||
* @param root 要查询的对象
|
||||
* @param cq 查询的一个条件容器
|
||||
* @param cb 设置具体某一个条件的表达式(模糊查询)
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Predicate toPredicate(Root<Blog> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
|
||||
List<Predicate> predicates = new ArrayList<>();
|
||||
if (!"".equals(blog.getTitle()) && blog.getTitle() != null) {
|
||||
predicates.add(cb.like(root.<String>get("title"), "%" + blog.getTitle() + "%"));
|
||||
}
|
||||
if (blog.getTypeId() != null) {
|
||||
predicates.add(cb.equal(root.<Type>get("type").get("id"), blog.getTypeId()));
|
||||
}
|
||||
if (blog.isRecommend()) {
|
||||
predicates.add(cb.equal(root.<Boolean>get("recommend"), blog.isRecommend()));
|
||||
}
|
||||
cq.where(predicates.toArray(new Predicate[predicates.size()]));
|
||||
return null;
|
||||
}
|
||||
}, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Blog> ListBlog(Pageable pageable) {
|
||||
return blogRepository.findAll(pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Blog> ListBlog(Long tagId, Pageable pageable) {
|
||||
|
||||
return blogRepository.findAll(new Specification<Blog>() {
|
||||
@Override
|
||||
public Predicate toPredicate(Root<Blog> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
|
||||
Join join = root.join("tags");
|
||||
return cb.equal(join.get("id"), tagId);
|
||||
}
|
||||
}, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Blog> ListBlog(Pageable pageable, String query) {
|
||||
return blogRepository.findByQuery(query, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Blog> listRecommendBlogTop(Integer size) {
|
||||
Sort sort = Sort.by(Sort.Direction.DESC, "updateTime");
|
||||
Pageable pageable = PageRequest.of(0, size, sort);
|
||||
return blogRepository.findTop(pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<Blog>> archiveBlog() {
|
||||
List<String> years = blogRepository.findGroupYear();
|
||||
Map<String, List<Blog>> map = new HashMap<>();
|
||||
for (String year : years) {
|
||||
map.put(year, blogRepository.findByYear(year));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countBlog() {
|
||||
return blogRepository.count();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布博客
|
||||
* (如何是新增博客,需要添加创建时间和修改时间、以及初始化浏览量view = 0)
|
||||
* (如果是修改博客,需要添加修改时间)
|
||||
*
|
||||
* @param blog
|
||||
* @return
|
||||
*/
|
||||
@Transactional
|
||||
@Override
|
||||
public Blog saveBlog(Blog blog) {
|
||||
//博客新增
|
||||
return blogRepository.save(blog);
|
||||
}
|
||||
|
||||
/**
|
||||
* 所谓的修改其实是查询+保存
|
||||
*
|
||||
* @param id
|
||||
* @param blog
|
||||
* @return
|
||||
*/
|
||||
@Transactional
|
||||
@Override
|
||||
public Blog updateBlog(Long id, Blog blog) {
|
||||
Blog b = blogRepository.findById(id).orElse(null);
|
||||
//判断是否存在这条数据
|
||||
if (b == null) {
|
||||
throw new NotFoundException("该博客不存在");
|
||||
}
|
||||
b.setUpdateTime(new Date());
|
||||
//copy有值属性 不覆盖
|
||||
BeanUtils.copyProperties(blog, b, MyBeanUtils.getNullPropertyNames(blog));
|
||||
return blogRepository.save(b);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void deleteBlog(Long id) {
|
||||
blogRepository.deleteById(id);
|
||||
}
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
package cn.allms.service.impl;
|
||||
|
||||
import cn.allms.util.CommentUtil;
|
||||
import cn.allms.dao.CommentRepository;
|
||||
import cn.allms.po.Comment;
|
||||
import cn.allms.service.CommentService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/10/10
|
||||
* @Description: com.yrp.service.impl
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Service
|
||||
public class CommentServiceImpl implements CommentService {
|
||||
|
||||
@Autowired
|
||||
private CommentRepository commentRepository;
|
||||
|
||||
@Override
|
||||
public List<Comment> listCommentByBlogId(Long blogId) {
|
||||
Sort sort = Sort.by("createTime");
|
||||
List<Comment> comments = commentRepository.findByBlogIdAndParentCommentNull(blogId, sort);
|
||||
return CommentUtil.eachComment(comments);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public Comment saveComment(Comment comment) {
|
||||
//回复: 如果有父级,需要将父级set进来,之后在保存
|
||||
Long parentCommentId = comment.getParentComment().getId();
|
||||
System.out.println(parentCommentId);
|
||||
if (parentCommentId != -1) {
|
||||
comment.setParentComment(commentRepository.findById(parentCommentId).orElse(null));
|
||||
} else {
|
||||
//发布评论:
|
||||
comment.setParentComment(null);
|
||||
}
|
||||
comment.setCreateTime(new Date());
|
||||
return commentRepository.save(comment);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,96 +0,0 @@
|
||||
package cn.allms.service.impl;
|
||||
|
||||
|
||||
import cn.allms.po.Tag;
|
||||
import cn.allms.service.TagService;
|
||||
import cn.allms.exception.NotFoundException;
|
||||
import cn.allms.dao.TagRepository;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 标签实现
|
||||
*/
|
||||
@Service
|
||||
public class TagServiceImpl implements TagService {
|
||||
|
||||
@Autowired
|
||||
private TagRepository tagRepository;
|
||||
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public Tag saveTag(Tag tag) {
|
||||
return tagRepository.save(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag getTag(Long id) {
|
||||
return tagRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Tag> ListTag(Pageable pageable) {
|
||||
return tagRepository.findAll(pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Tag> ListTagTop(Integer size) {
|
||||
Sort sort = Sort.by(Sort.Direction.DESC, "blogs.size");
|
||||
Pageable pageable = PageRequest.of(0, size, sort);
|
||||
return tagRepository.findTop(pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Tag> ListTag() {
|
||||
return tagRepository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Tag> ListTag(String ids) {
|
||||
// todo
|
||||
return tagRepository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag updateTag(Long id, Tag tag) {
|
||||
Tag t = tagRepository.findById(id).orElse(null);
|
||||
if (t == null) {
|
||||
throw new NotFoundException("不存在该标签");
|
||||
}
|
||||
|
||||
BeanUtils.copyProperties(tag, t);
|
||||
return tagRepository.save(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteTag(Long id) {
|
||||
tagRepository.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag getTagByName(String name) {
|
||||
return tagRepository.findByName(name);
|
||||
}
|
||||
|
||||
/*将字符串转化为集合*/
|
||||
private List<Long> convertToList(String ids) {
|
||||
List<Long> list = new ArrayList<>();
|
||||
if (!"".equals(ids) && ids != null) {
|
||||
String[] idarray = ids.split(",");
|
||||
for (int i = 0; i < idarray.length; i++) {
|
||||
list.add(new Long(idarray[i]));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@ -1,83 +0,0 @@
|
||||
package cn.allms.service.impl;
|
||||
|
||||
import cn.allms.exception.NotFoundException;
|
||||
import cn.allms.dao.TypeRepository;
|
||||
import cn.allms.po.Type;
|
||||
import cn.allms.service.TypeService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/9/29
|
||||
* @Description: com.yrp.service.impl
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Service
|
||||
public class TypeServiceImpl implements TypeService {
|
||||
|
||||
@Autowired
|
||||
private TypeRepository typeRepository;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public Type saveType(Type type) {
|
||||
|
||||
return typeRepository.save(type);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public Type getType(Long id) {
|
||||
return typeRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public Page<Type> ListType(Pageable pageable) {
|
||||
return typeRepository.findAll(pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Type> listType() {
|
||||
return typeRepository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Type> listTypeTop(Integer size) {
|
||||
Sort sort = Sort.by(Sort.Direction.DESC, "blogs.size");
|
||||
Pageable pageable = PageRequest.of(0, size, sort);
|
||||
return typeRepository.findTop(pageable);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public Type updateType(Long id, Type type) {
|
||||
Type t = typeRepository.findById(id).orElse(null);
|
||||
if (t == null) {
|
||||
throw new NotFoundException("不存在该类型");
|
||||
}
|
||||
BeanUtils.copyProperties(type, t);
|
||||
return typeRepository.save(t);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void deleteType(Long id) {
|
||||
typeRepository.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getTypeByName(String name) {
|
||||
return typeRepository.findByName(name);
|
||||
}
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
package cn.allms.service.impl;
|
||||
|
||||
import cn.allms.po.User;
|
||||
import cn.allms.dao.UserRepository;
|
||||
import cn.allms.service.Userservice;
|
||||
import cn.allms.util.MD5Utils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/9/28
|
||||
* @Description: com.yrp.service.serviceimpl
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Service
|
||||
public class UserServiceImpl implements Userservice {
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Override
|
||||
public User checkUser(String username, String password) {
|
||||
System.out.println(username);
|
||||
System.out.println(password);
|
||||
User user = userRepository.findByUsernameAndPassword(username, MD5Utils.code(password));
|
||||
System.out.println(MD5Utils.code(password));
|
||||
return user;
|
||||
}
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
package cn.allms.util;
|
||||
|
||||
import cn.allms.po.Comment;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 评论格式化工具
|
||||
*/
|
||||
public class CommentUtil {
|
||||
/**
|
||||
* 循环每个顶级的评论节点
|
||||
*
|
||||
* @param comments
|
||||
* @return
|
||||
*/
|
||||
public static List<Comment> eachComment(List<Comment> comments) {
|
||||
List<Comment> commentsView = new ArrayList<>();
|
||||
for (Comment comment : comments) {
|
||||
Comment c = new Comment();
|
||||
BeanUtils.copyProperties(comment, c);
|
||||
commentsView.add(c);
|
||||
}
|
||||
//合并评论的各层子代到第一级子代集合中
|
||||
combineChildren(commentsView);
|
||||
return commentsView;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param comments root根节点,blog不为空的对象集合
|
||||
* @return
|
||||
*/
|
||||
public static void combineChildren(List<Comment> comments) {
|
||||
|
||||
for (Comment comment : comments) {
|
||||
List<Comment> replys1 = comment.getReplyComments();
|
||||
for (Comment reply1 : replys1) {
|
||||
//循环迭代,找出子代,存放在tempReplys中
|
||||
recursively(reply1);
|
||||
}
|
||||
//修改顶级节点的reply集合为迭代处理后的集合
|
||||
comment.setReplyComments(tempReplys);
|
||||
//清除临时存放区
|
||||
tempReplys = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
//存放迭代找出的所有子代的集合
|
||||
public static List<Comment> tempReplys = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 递归迭代,剥洋葱
|
||||
*
|
||||
* @param comment 被迭代的对象
|
||||
* @return
|
||||
*/
|
||||
public static void recursively(Comment comment) {
|
||||
tempReplys.add(comment);//顶节点添加到临时存放集合
|
||||
if (comment.getReplyComments().size() > 0) {
|
||||
List<Comment> replys = comment.getReplyComments();
|
||||
for (Comment reply : replys) {
|
||||
tempReplys.add(reply);
|
||||
if (reply.getReplyComments().size() > 0) {
|
||||
recursively(reply);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
package cn.allms.util;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* Created by limi on 2017/10/15.
|
||||
*/
|
||||
public class MD5Utils {
|
||||
|
||||
/**
|
||||
* MD5加密类
|
||||
*
|
||||
* @param str 要加密的字符串
|
||||
* @return 加密后的字符串
|
||||
*/
|
||||
public static String code(String str) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
md.update(str.getBytes());
|
||||
byte[] byteDigest = md.digest();
|
||||
int i;
|
||||
StringBuffer buf = new StringBuffer("");
|
||||
for (int offset = 0; offset < byteDigest.length; offset++) {
|
||||
i = byteDigest[offset];
|
||||
if (i < 0)
|
||||
i += 256;
|
||||
if (i < 16)
|
||||
buf.append("0");
|
||||
buf.append(Integer.toHexString(i));
|
||||
}
|
||||
//32位加密
|
||||
return buf.toString();
|
||||
// 16位的加密
|
||||
//return buf.toString().substring(8, 24);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(code("123"));
|
||||
}
|
||||
}
|
||||
@ -1,89 +0,0 @@
|
||||
package cn.allms.util;
|
||||
|
||||
import org.commonmark.Extension;
|
||||
import org.commonmark.ext.gfm.tables.TableBlock;
|
||||
import org.commonmark.ext.gfm.tables.TablesExtension;
|
||||
import org.commonmark.ext.heading.anchor.HeadingAnchorExtension;
|
||||
import org.commonmark.node.Link;
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.parser.Parser;
|
||||
import org.commonmark.renderer.html.AttributeProvider;
|
||||
import org.commonmark.renderer.html.AttributeProviderContext;
|
||||
import org.commonmark.renderer.html.AttributeProviderFactory;
|
||||
import org.commonmark.renderer.html.HtmlRenderer;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by limi on 2017/10/22.
|
||||
*/
|
||||
public class MarkdownUtils {
|
||||
|
||||
/**
|
||||
* markdown格式转换成HTML格式
|
||||
*
|
||||
* @param markdown
|
||||
* @return
|
||||
*/
|
||||
public static String markdownToHtml(String markdown) {
|
||||
Parser parser = Parser.builder().build();
|
||||
Node document = parser.parse(markdown);
|
||||
HtmlRenderer renderer = HtmlRenderer.builder().build();
|
||||
return renderer.render(document);
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加扩展[标题锚点,表格生成]
|
||||
* Markdown转换成HTML
|
||||
*
|
||||
* @param markdown
|
||||
* @return
|
||||
*/
|
||||
public static String markdownToHtmlExtensions(String markdown) {
|
||||
//h标题生成id
|
||||
Set<Extension> headingAnchorExtensions = Collections.singleton(HeadingAnchorExtension.create());
|
||||
//转换table的HTML
|
||||
List<Extension> tableExtension = Arrays.asList(TablesExtension.create());
|
||||
Parser parser = Parser.builder()
|
||||
.extensions(tableExtension)
|
||||
.build();
|
||||
Node document = parser.parse(markdown);
|
||||
HtmlRenderer renderer = HtmlRenderer.builder()
|
||||
.extensions(headingAnchorExtensions)
|
||||
.extensions(tableExtension)
|
||||
.attributeProviderFactory(new AttributeProviderFactory() {
|
||||
public AttributeProvider create(AttributeProviderContext context) {
|
||||
return new CustomAttributeProvider();
|
||||
}
|
||||
})
|
||||
.build();
|
||||
return renderer.render(document);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理标签的属性
|
||||
*/
|
||||
static class CustomAttributeProvider implements AttributeProvider {
|
||||
@Override
|
||||
public void setAttributes(Node node, String tagName, Map<String, String> attributes) {
|
||||
//改变a标签的target属性为_blank
|
||||
if (node instanceof Link) {
|
||||
attributes.put("target", "_blank");
|
||||
}
|
||||
if (node instanceof TableBlock) {
|
||||
attributes.put("class", "ui celled table");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
String table = "| hello | hi | 哈哈哈 |\n" +
|
||||
"| ----- | ---- | ----- |\n" +
|
||||
"| 斯维尔多 | 士大夫 | f啊 |\n" +
|
||||
"| 阿什顿发 | 非固定杆 | 撒阿什顿发 |\n" +
|
||||
"\n";
|
||||
String a = "[imCoding 爱编程](http://www.lirenmi.cn)";
|
||||
System.out.println(markdownToHtmlExtensions(a));
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
package cn.allms.util;
|
||||
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by limi on 2017/10/21.
|
||||
*/
|
||||
public class MyBeanUtils {
|
||||
|
||||
|
||||
/**
|
||||
* 获取所有的属性值为空属性名数组
|
||||
*
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
public static String[] getNullPropertyNames(Object source) {
|
||||
BeanWrapper beanWrapper = new BeanWrapperImpl(source);
|
||||
PropertyDescriptor[] pds = beanWrapper.getPropertyDescriptors();
|
||||
List<String> nullPropertyNames = new ArrayList<>();
|
||||
for (PropertyDescriptor pd : pds) {
|
||||
String propertyName = pd.getName();
|
||||
if (beanWrapper.getPropertyValue(propertyName) == null) {
|
||||
nullPropertyNames.add(propertyName);
|
||||
}
|
||||
}
|
||||
return nullPropertyNames.toArray(new String[nullPropertyNames.size()]);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
package cn.allms.vo;
|
||||
|
||||
/**
|
||||
* @Auther: 南迪叶先生:https://www.cnblogs.com/ye888/
|
||||
* @Date: 2019/10/3
|
||||
* @Description: com.yrp.vo
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class BlogQuery {
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String title;
|
||||
/**
|
||||
* 分类ID
|
||||
*/
|
||||
private Long typeId;
|
||||
/**
|
||||
* 是否提交
|
||||
*/
|
||||
private boolean recommend;
|
||||
|
||||
public BlogQuery() {
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public Long getTypeId() {
|
||||
return typeId;
|
||||
}
|
||||
|
||||
public void setTypeId(Long typeId) {
|
||||
this.typeId = typeId;
|
||||
}
|
||||
|
||||
public boolean isRecommend() {
|
||||
return recommend;
|
||||
}
|
||||
|
||||
public void setRecommend(boolean recommend) {
|
||||
this.recommend = recommend;
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,16 @@
|
||||
package cn.allms;
|
||||
package com.example.demorest;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* springboot启动器
|
||||
* @author josxy
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class MxBlogApplication {
|
||||
public class DemoRestApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MxBlogApplication.class, args);
|
||||
SpringApplication.run(DemoRestApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,164 @@
|
||||
package com.example.demorest.controller;
|
||||
|
||||
import com.example.demorest.entity.Book;
|
||||
import com.example.demorest.exception.InvalidRequestException;
|
||||
import com.example.demorest.exception.ResourceNoFoundException;
|
||||
import com.example.demorest.repository.BookRepository;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* rest 风格 api
|
||||
* <p>
|
||||
* GET /api/v1/books 所有书单
|
||||
* GET /api/v1/books/{id} 获取一条书单
|
||||
* POST /api/v1/books 新建一条书单
|
||||
* PUT /api/v1/books/{id} 更新一条书单,提供全部信息
|
||||
* PATCH /api/v1/books/{id} 更新一条书单,提供部分信息
|
||||
* DELETE /api/v1/books/{id} 删除一条书单
|
||||
* DELETE /API/v1/books 删除所有书单
|
||||
*
|
||||
* @author Echo
|
||||
* @version 1.0
|
||||
* @date 2019-01-05 21:59
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/v1")
|
||||
public class BookController {
|
||||
private final BookRepository bookRepository;
|
||||
|
||||
@Autowired
|
||||
public BookController(BookRepository bookRepository) {
|
||||
this.bookRepository = bookRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有书单
|
||||
* GET /api/v1/books 所有书单
|
||||
*
|
||||
* @return http 响应
|
||||
*/
|
||||
@GetMapping("/books")
|
||||
public HttpEntity<?> books() {
|
||||
return new ResponseEntity<>(bookRepository.findAll(), HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个书单 * GET /api/v1/books/{id} 获取一条书单 * * @param id id
|
||||
*
|
||||
* @return http 响应
|
||||
*/
|
||||
@GetMapping("/books/{id}")
|
||||
public HttpEntity<?> booksOne(@PathVariable Long id) {
|
||||
return new ResponseEntity<>(bookRepository.findById(id).orElseThrow(() ->
|
||||
new ResourceNoFoundException(String.format("Book by id %s not found!", id))),
|
||||
HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个书单
|
||||
* POST /api/v1/books 新建一条书单
|
||||
*
|
||||
* @param book 书单
|
||||
* @return http 响应
|
||||
*/
|
||||
@PostMapping("/books")
|
||||
public HttpEntity<?> booksAdd(@Valid @RequestBody Book book, BindingResult bindingResult) {
|
||||
if (bindingResult.hasErrors()) {
|
||||
throw new InvalidRequestException("Invalid parameter", bindingResult);
|
||||
}
|
||||
return new ResponseEntity<>(bookRepository.save(book), HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新一个书单,提供一个书单的全部信息
|
||||
* PUT /api/v1/books/{id} 更新一条书单,提供全部信息
|
||||
*
|
||||
* @param id 更新的id
|
||||
* @param book 更新后的书单
|
||||
* @return http 响应
|
||||
*/
|
||||
@PutMapping("/books/{id}")
|
||||
public HttpEntity<?> booksPut(@Valid @PathVariable Long id, @RequestBody Book book, BindingResult bindingResult) {
|
||||
Book exist = bookRepository.findById(id).orElseThrow(() ->
|
||||
new ResourceNoFoundException(String.format("Book by id %s not found!", id)));
|
||||
if (bindingResult.hasErrors()) {
|
||||
throw new InvalidRequestException("Invalid parameter", bindingResult);
|
||||
}
|
||||
book.setId(exist.getId());
|
||||
return new ResponseEntity<>(bookRepository.save(book), HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新一个书单,提供一个书单的部分信息
|
||||
* PATCH /api/v1/books/{id} 更新一条书单,提供部分信息
|
||||
*
|
||||
* @param id 更新的id
|
||||
* @param book 更新后的书单
|
||||
* @return http 响应
|
||||
*/
|
||||
@PatchMapping("/books/{id}")
|
||||
public HttpEntity<?> booksPatch(@PathVariable Long id, @RequestBody Book book) {
|
||||
Book exist = bookRepository.findById(id).orElseThrow(() ->
|
||||
new ResourceNoFoundException(String.format("Book by id %s not found!", id)));
|
||||
BeanWrapper beanWrapper = new BeanWrapperImpl(book);
|
||||
PropertyDescriptor[] propertyDescriptors = beanWrapper.getPropertyDescriptors();
|
||||
List<String> nullPropertyNames = new ArrayList<>();
|
||||
for (PropertyDescriptor pd :
|
||||
propertyDescriptors) {
|
||||
if (beanWrapper.getPropertyValue(pd.getName()) == null) {
|
||||
nullPropertyNames.add(pd.getName());
|
||||
}
|
||||
}
|
||||
BeanUtils.copyProperties(book, exist, nullPropertyNames.toArray(new String[nullPropertyNames.size()]));
|
||||
return new ResponseEntity<>(bookRepository.save(exist), HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一个书单
|
||||
* DELETE /api/v1/books/{id} 删除一条书单
|
||||
*
|
||||
* @param id id
|
||||
* @return http 响应
|
||||
*/
|
||||
@DeleteMapping("/books/{id}")
|
||||
public HttpEntity<?> booksDeleteOne(@PathVariable Long id) {
|
||||
Book exist = bookRepository.findById(id).orElseThrow(() ->
|
||||
new ResourceNoFoundException(String.format("Book by id %s not found!", id)));
|
||||
bookRepository.deleteById(exist.getId());
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除所有书单
|
||||
* DELETE /API/v1/books 删除所有书单
|
||||
*
|
||||
* @return http 响应
|
||||
*/
|
||||
@DeleteMapping("/books")
|
||||
public HttpEntity<?> booksDeleteAll() {
|
||||
List<Book> books = bookRepository.findAll();
|
||||
if (books.isEmpty()) {
|
||||
throw new ResourceNoFoundException("Not found books!");
|
||||
}
|
||||
bookRepository.deleteAll();
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
}
|
||||
47
src/main/java/com/example/demorest/entity/Book.java
Normal file
@ -0,0 +1,47 @@
|
||||
package com.example.demorest.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.validation.constraints.Digits;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 书单对象
|
||||
* @author xieYj
|
||||
* @date 2021/5/12 13:57
|
||||
*/
|
||||
@Entity
|
||||
@Data
|
||||
public class Book {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(insertable = false, length = 20, nullable = false)
|
||||
private Long id;
|
||||
|
||||
@NotBlank(message = "书名不能为空")
|
||||
@Column(columnDefinition = "varchar(50) comment '书名'")
|
||||
private String name;
|
||||
|
||||
@NotBlank(message = "作者不能为空")
|
||||
@Column(columnDefinition = "varchar(25) comment '作者'")
|
||||
private String author;
|
||||
|
||||
@Column(columnDefinition = "varchar(255) comment '描述'")
|
||||
public String description;
|
||||
|
||||
/**
|
||||
* status 非空
|
||||
*/
|
||||
@NotNull(message = "status 不能为空")
|
||||
@ColumnDefault("1")
|
||||
@Column(columnDefinition = "tinyint(1) comment '是否存在,false|0不存在,true|1已存在'")
|
||||
public Boolean status;
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package com.example.demorest.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.validation.Errors;
|
||||
|
||||
/**
|
||||
* 无效的参数请求异常
|
||||
*
|
||||
* @author xieYj
|
||||
* @date 2021/5/12 16:22
|
||||
*/
|
||||
public class InvalidRequestException extends RuntimeException {
|
||||
@Getter
|
||||
private Errors errors;
|
||||
|
||||
public InvalidRequestException(String message, Errors errors) {
|
||||
super(message);
|
||||
this.errors = errors;
|
||||
}
|
||||
|
||||
public InvalidRequestException(Errors errors) {
|
||||
this.errors = errors;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.example.demorest.exception;
|
||||
|
||||
/**
|
||||
* 资源找不到异常
|
||||
*
|
||||
* @author xieYj
|
||||
* @date 2021/5/12 16:24
|
||||
*/
|
||||
public class ResourceNoFoundException extends RuntimeException {
|
||||
public ResourceNoFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package com.example.demorest.handle;
|
||||
|
||||
import com.example.demorest.exception.InvalidRequestException;
|
||||
import com.example.demorest.exception.ResourceNoFoundException;
|
||||
import com.example.demorest.resource.ErrorResource;
|
||||
import com.example.demorest.resource.FieldResource;
|
||||
import com.example.demorest.resource.InvalidErrorResource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 书单API全局异常处理
|
||||
*
|
||||
* @author xieYj
|
||||
* @date 2021/5/12 16:31
|
||||
*/
|
||||
@RestControllerAdvice(basePackages = "com.example.demorest.controller")
|
||||
public class ApiExceptionHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@ExceptionHandler(ResourceNoFoundException.class)
|
||||
public HttpEntity<?> handleNotFound(ResourceNoFoundException e) {
|
||||
ErrorResource errorResource = new ErrorResource(e.getMessage());
|
||||
logger.error(errorResource.toString());
|
||||
return new ResponseEntity<>(errorResource, HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
@ExceptionHandler(InvalidRequestException.class)
|
||||
public HttpEntity<?> handleInvalidRequest(InvalidRequestException e) {
|
||||
Errors errors = e.getErrors();
|
||||
List<FieldResource> fieldResources = new ArrayList<>();
|
||||
List<FieldError> fieldErrors = errors.getFieldErrors();
|
||||
for (FieldError fieldError : fieldErrors) {
|
||||
fieldResources.add(
|
||||
new FieldResource(fieldError.getObjectName(),
|
||||
fieldError.getField(),
|
||||
fieldError.getCode(),
|
||||
fieldError.getDefaultMessage())
|
||||
);
|
||||
}
|
||||
InvalidErrorResource invalidErrorResource = new InvalidErrorResource(e.getMessage(), fieldResources);
|
||||
logger.error(invalidErrorResource.toString());
|
||||
return new ResponseEntity<>(invalidErrorResource, HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public HttpEntity<?> handleException(Exception e) {
|
||||
logger.error(e.getMessage());
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.example.demorest.repository;
|
||||
|
||||
import com.example.demorest.entity.Book;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* 书单仓储层,jpa实现
|
||||
* @author xieYj
|
||||
* @date 2021/5/12 15:19
|
||||
*/
|
||||
@Repository
|
||||
public interface BookRepository extends JpaRepository<Book, Long> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.example.demorest.resource;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* 资源错误
|
||||
*
|
||||
* @author xieYj
|
||||
* @date 2021/5/12 16:27
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
@Getter
|
||||
public class ErrorResource {
|
||||
private String message;
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.example.demorest.resource;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* 字段错误
|
||||
*
|
||||
* @author josxy
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
@Getter
|
||||
public class FieldResource {
|
||||
/**
|
||||
* 实体对象
|
||||
*/
|
||||
private String resource;
|
||||
/**
|
||||
* 字段
|
||||
*/
|
||||
private String field;
|
||||
/**
|
||||
* 代码
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 具体信息
|
||||
*/
|
||||
private String message;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.example.demorest.resource;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* 资源错误信息封装
|
||||
* @author xieYj
|
||||
* @date 2021/5/12 16:29
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ToString
|
||||
@Getter
|
||||
public class InvalidErrorResource {
|
||||
private String message;
|
||||
private Object errors;
|
||||
}
|
||||
@ -1,24 +1,21 @@
|
||||
# 项目端口
|
||||
server:
|
||||
port: 9420
|
||||
|
||||
#数据库驱动mysql
|
||||
spring:
|
||||
application:
|
||||
name: restful-api
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://127.0.0.1:3306/mx-blog?useUnicode=true&characterEncoding=utf-8&useSSL=false
|
||||
url: jdbc:p6spy:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf-8&useSSL=false
|
||||
username: root
|
||||
password: 123456
|
||||
platform: mysql
|
||||
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
|
||||
jpa:
|
||||
# 关闭jpa自带的show sql
|
||||
show-sql: false
|
||||
open-in-view: false
|
||||
#加上这句会执行import.sql
|
||||
generate-ddl: true
|
||||
hibernate:
|
||||
ddl-auto: create
|
||||
show-sql: false
|
||||
|
||||
#日志打印
|
||||
logging:
|
||||
level:
|
||||
root: info
|
||||
cn.allms: debug
|
||||
file:
|
||||
name: log/blog-dev.log
|
||||
path: classpath:logback/logback-spring.xml
|
||||
server:
|
||||
servlet:
|
||||
context-path: /api
|
||||
port: 8001
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
#thymeleaf模板
|
||||
spring:
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf-8
|
||||
username: root
|
||||
password: 123456
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: none
|
||||
show-sql: true
|
||||
|
||||
#日志打印
|
||||
logging:
|
||||
level:
|
||||
root: warn
|
||||
com.yrp: info
|
||||
file:
|
||||
name: log/-blogpro.log
|
||||
|
||||
# 服务端口
|
||||
server:
|
||||
port: 9420
|
||||
19
src/main/resources/application-prod.yml
Normal file
@ -0,0 +1,19 @@
|
||||
spring:
|
||||
application:
|
||||
name: restful-api
|
||||
datasource:
|
||||
url: jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf-8&useSSL=false
|
||||
username: root
|
||||
password: 123456
|
||||
platform: mysql
|
||||
jpa:
|
||||
show-sql: false
|
||||
open-in-view: false
|
||||
#加上这句会执行import.sql
|
||||
generate-ddl: false
|
||||
hibernate:
|
||||
ddl-auto: update
|
||||
server:
|
||||
servlet:
|
||||
context-path: /api
|
||||
port: 8080
|
||||
@ -1,19 +1,3 @@
|
||||
#thymeleaf模板
|
||||
spring:
|
||||
thymeleaf:
|
||||
mode: HTML
|
||||
profiles:
|
||||
active: dev
|
||||
messages:
|
||||
basename: i18n/message
|
||||
|
||||
#博客头像
|
||||
comment:
|
||||
v2exUrl: https://sdn.geekzu.org/avatar/
|
||||
avatar: /images/avatar.png
|
||||
|
||||
# 随机图片
|
||||
random:
|
||||
pictures:
|
||||
- "https://api.rainss.cn/random.php?t="
|
||||
- "https://api.rainss.cn/acgimgurl/acgurl.php?t="
|
||||
active: prod
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
###########################\u524D\u53F0\u9875\u9762########################
|
||||
# \u9876\u90E8\u5BFC\u822A\u680F\u4FE1\u606F
|
||||
index.home=\u9996\u9875
|
||||
index.type=\u5206\u7C7B
|
||||
index.tag=\u6807\u7B7E
|
||||
index.archive=\u5F52\u6863
|
||||
index.aboutme=\u7AD9\u957F\u4FE1\u606F
|
||||
#\u5E95\u90E8\u5BFC\u822A\u680F\u4FE1\u606F
|
||||
index.email=\u90AE\u7BB1:qfmx520@163.com
|
||||
index.qq=QQ:745719461
|
||||
index.about=\u4F5C\u8005\u662F\u4E00\u540Dspringboot\u7231\u597D\u8005,\u662F\u4E00\u540D\u6B63\u5728\u52AA\u529B\u594B\u6597\u7684\u5B66\u751F,\u4E3B\u8981\u5B66\u4E60JavaEE\u5F00\u53D1,Web\u524D\u7AEF\u7B49\u6280\u672F.\u4F5C\u8005\u662F\u4E2A\u559C\u6B22\u65C5\u884C\u7684\u5B69\u5B50,\u76EE\u6807\u662F\u6E38\u904D\u5168\u4E16\u754C\uFF01
|
||||
index.copyright=copy @ 2020 - 2021 \u4f5c\u8005:\u6d45\u67ab\u6c90\u96ea \u6b64\u7ad9\u4ec5\u4f9b\u4e2a\u4eba\u6240\u6709 \u5982\u6709\u7591\u95ee\u8054\u7cfb\u4f5c\u8005
|
||||
#\u4E8C\u7EF4\u7801\u626B\u7801\u9605\u8BFB\u5730\u5740
|
||||
blog.serurl=127.0.0.1:80
|
||||
@ -1,14 +0,0 @@
|
||||
###########################\u524D\u53F0\u9875\u9762########################
|
||||
# \u9876\u90E8\u5BFC\u822A\u680F\u4FE1\u606F
|
||||
index.home=Home
|
||||
index.type=Type
|
||||
index.tag=Tag
|
||||
index.archive=Archive
|
||||
index.aboutme=About Me
|
||||
#\u5E95\u90E8\u5BFC\u822A\u680F\u4FE1\u606F
|
||||
index.email=Email:qfmx520@163.com
|
||||
index.qq=QQ:745719461
|
||||
index.about=The author is a springboot enthusiast, a struggling student who mainly studies JavaEE development,Web front end and other technologies.
|
||||
index.copyright=copy @ 2020 - 2021 \u4f5c\u8005:\u6d45\u67ab\u6c90\u96ea \u6b64\u7ad9\u4ec5\u4f9b\u4e2a\u4eba\u6240\u6709 \u5982\u6709\u7591\u95ee\u8054\u7cfb\u4f5c\u8005
|
||||
#\u4E8C\u7EF4\u7801\u626B\u7801\u9605\u8BFB\u5730\u5740
|
||||
blog.serurl=172.20.10.6:8080
|
||||
@ -1,14 +0,0 @@
|
||||
###########################\u524D\u53F0\u9875\u9762########################
|
||||
# \u9876\u90E8\u5BFC\u822A\u680F\u4FE1\u606F
|
||||
index.home=\u9996\u9875
|
||||
index.type=\u5206\u7C7B
|
||||
index.tag=\u6807\u7B7E
|
||||
index.archive=\u5F52\u6863
|
||||
index.aboutme=\u7AD9\u957F\u4FE1\u606F
|
||||
#\u5E95\u90E8\u5BFC\u822A\u680F\u4FE1\u606F
|
||||
index.email=\u90AE\u7BB1:qfmx520@163.com
|
||||
index.qq=QQ:745719461
|
||||
index.about=\u4F5C\u8005\u662F\u4E00\u540Dspringboot\u7231\u597D\u8005,\u662F\u4E00\u540D\u6B63\u5728\u52AA\u529B\u594B\u6597\u7684\u5B66\u751F,\u4E3B\u8981\u5B66\u4E60JavaEE\u5F00\u53D1,Web\u524D\u7AEF\u7B49\u6280\u672F.\u4F5C\u8005\u662F\u4E2A\u559C\u6B22\u65C5\u884C\u7684\u5B69\u5B50,\u76EE\u6807\u662F\u6E38\u904D\u5168\u4E16\u754C\uFF01
|
||||
index.copyright=copy @ 2020 - 2021 \u4f5c\u8005:\u6d45\u67ab\u6c90\u96ea \u6b64\u7ad9\u4ec5\u4f9b\u4e2a\u4eba\u6240\u6709 \u5982\u6709\u7591\u95ee\u8054\u7cfb\u4f5c\u8005
|
||||
#\u4E8C\u7EF4\u7801\u626B\u7801\u9605\u8BFB\u5730\u5740
|
||||
blog.serurl=172.20.10.6:8080
|
||||
24
src/main/resources/import.sql
Normal file
@ -0,0 +1,24 @@
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (1, '孟宁', '本书从理解计算机硬件的核心工作机制(存储程序计算机和函数调用堆栈)和用户态程序如何通过系统调用陷入内核(中断异常)入手,通过上下两个方向双向夹击的策略,并利用实际可运行程序的反汇编代码从实践的角度理解操作系统内核,分析Linux内核源代码,从系统调用陷入内核、进程调度与进程切换开始,最后返回到用户态进程。', '庖丁解牛Linux内核分析', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (2, '孙亮', '大数据时代为机器学习的应用提供了广阔的空间,各行各业涉及数据分析的工作都需要使用机器学习算法。本书围绕实际数据分析的流程展开,着重介绍数据探索、数据预处理和常用的机器学习算法模型。本书从解决实际问题的角度出发,介绍回归算法、分类算法、推荐算法、排序算法和集成学习算法。在介绍每种机器学习算法模型时,书中不但阐述基本原理,而且讨论模型的评价与选择。为方便读者学习各种算法,本书介绍了R语言中相应的软件包并给出了示例程序。', '实用机器学习', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (3, '托马斯·哈斯尔万特', '本书以基础的统计学知识和假设检验为重点,简明扼要地讲述了Python在数据分析、可视化和统计建模中的应用。主要包括Python的简单介绍、研究设计、数据管理、概率分布、不同数据类型的假设检验、广义线性模型、生存分析和贝叶斯统计学等从入门到高级的内容。', 'Python统计分析', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (4, '甘迪文', '《Windows黑客编程技术详解》介绍的是黑客编程的基础技术,涉及用户层下的Windows编程和内核层下的Rootkit编程。本书分为用户篇和内核篇两部分,用户篇包括11章,配套49个示例程序源码;内核篇包括7章,配套28个示例程序源码。本书介绍的每个技术都有详细的实现原理,以及对应的示例代码(配套代码均支持32位和64位Windows 7、Windows 8.1及Windows 10系统),旨在帮助初学者建立起黑客编程技术的基础。', 'Windows黑客编程技术详解', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (5, '科里•奥尔索夫', '本书作者是一名自学成才的程序员,经过一年的自学,掌握了编程技能并在eBay找到了一份软件工程师的工作。本书是作者结合个人经验写作而成,旨在帮助读者从外行成长为一名专业的Python程序员。', 'Python编程无师自通——专业程序员的养成', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (6, '威廉·史密斯', '本书由浅入深地详细讲解了计算机存储使用的多种数据结构。本书首先讲解了初级的数据结构(如表、栈、队列和堆等),具体包括它们的工作原理、功能实现以及典型的应用程序等;然后讨论了数据结构,如泛型集合、排序、搜索和递归等;最后介绍了如何在日常应用中使用这些数据结构。', '程序员学数据结构', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (7, '张鑫旭', '本书从前端开发人员的需求出发,以“流”为线索,从结构、内容到美化装饰等方面,全面且深入地讲解前端开发人员必须了解和掌握的大量的CSS知识点。同时,作者结合多年的从业经验,通过大量的实战案例,详尽解析CSS的相关知识与常见问题。作者还为本书开发了专门的配套网站,进行实例展示、问题答疑。', 'CSS世界', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (8, '理查德·格里姆斯', '作为一门广为人知的编程语言,C++已经诞生30多年了,这期间也出现并流行过许多种编程语言,但是C++是经得起考验的。如此经典的编程语言,值得每一位编程领域的新人认真学习,也适合有经验的程序员细细品味。', 'C++编程自学宝典', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (9, '萨沙·戈德斯汀', '本书详细解释了影响应用程序性能的Windows、CLR和物理硬件的内部结构,并为读者提供了衡量代码如何独立于外部因素执行操作的知识和工具。书中提供了大量的C#代码示例和技巧,将帮助读者zui大限度地提高算法和应用程序的性能,提高个人竞争优势,使用更低的成本获取更多的用户。', '.NET性能优化', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (10, '李伟', '《C++模板元编程实战:一个深度学习框架的初步实现》以一个深度学习框架的初步实现为例,讨论如何在一个相对较大的项目中深入应用元编程,为系统性能优化提供更多的可能。', 'C++模板元编程实战:一个深度学习框架的初步实现', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (11, 'Ben Klemens 克莱蒙', '本书展现了传统C语言教科书所不具有相关技术。全书分', 'C程序设计新思维(第2版)', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (12, '王云', '本书遵循由浅入深、循序渐进的原则,讲解单片机开发经典案例。本书以YL51单片机开发板为平台,通过案例逐个讲解开发板上各个器件模块的使用及其编程方法,包括单片机最小系统、数码管显示原理、中断与定时器、数模\\模数转换工作原理、LCD液晶显示、串行口通信、步进电机驱动原理、PWM脉宽调制与直流电机等内容。', '51单片机C语言程序设计教程', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (13, '胡振波', '本书是一本介绍通用CPU设计的入门书,以通俗的语言系统介绍了CPU和RISC-V架构,力求为读者揭开CPU设计的神秘面纱,打开计算机体系结构的大门。', '手把手教你设计CPU——RISC-V处理器篇', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (14, '克劳斯·福勒', '本书旨在通过实际的Python 3.0代码示例展示Python与数学应用程序的紧密联系,介绍将Python中的各种概念用于科学计算的方法。', 'Python 3.0科学计算指南', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (15, '路彦雄', '《文本上的算法 深入浅出自然语言处理》结合-作者多年学习和从事自然语言处理相关工作的经验,力图用生动形象的方式深入浅出地介绍自然语言处理的理论、方法和技术。本书抛弃掉繁琐的证明,提取出算法的核心,帮助读者尽快地掌握自然语言处理所必需的知识和技能。', '文本上的算法——深入浅出自然语言处理', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (16, '胡世杰', '本书从云存储的需求出发讲述对象存储的原理,循序渐进地建立起一个分布式对象存储的架构,并且将软件实现出来。全书共8章,分别涉及对象存储简介、可扩展分布式系统、元数据服务、数据校验和去重、数据冗余处理、断点续传、数据压缩和数据维护等。本书选择用来实现分布式对象存储软件的编程语言是当前流行的Go语言。', '分布式对象存储——原理、架构及Go语言实现', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (17, '徐子珊', '《趣题学算法》适于作为程序员的参考书,高校各专业学生学习“数据结构”“算法设计分析”“程序设计”等课程的扩展读物,也可以作为上述课程的实验或课程设计的材料,还可以作为准备参加国内或国际程序设计赛事的读者的赛前训练材料。', '趣题学算法', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (18, '鲁什迪·夏姆斯', '现如今,数据科学已经成为一个热门的技术领域,它涵盖了人工智能的各个方面,例如数据处理、信息检索、机器学习、自然语言处理、数据可视化等。而Java作为一门经典的编程语言,在数据科学领域也有着杰出的表现。', 'Java数据科学指南', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (19, '罗炳森', '结构化查询语言(Structured Query Language,SQL)是一种功能强大的数据库语言。它基于关系代数运算,功能丰富、语言简洁、使用方便灵活,已成为关系数据库的标准语言。', 'SQL优化核心思想', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (20, '弗兰克·D.卢娜', 'Direct3D是微软公司DirectX SDK集成开发包中的重要组成部分,是编写高性能3D图形应用程序的渲染库,适用于多媒体、娱乐、即时3D动画等广泛和实用的3D图形计算领域。', 'DirectX 12 3D 游戏开发实战', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (21, '巴阿尔丁•阿扎米', 'Kibana是广泛地应用在数据检索和数据可视化领域的ELK中的一员。本书专门介绍Kibana,通过不同的用例场景,带领读者全面体验Kibana的可视化功能。', 'Kibana数据可视化', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (22, '郝佳', '《Spring源码深度解析(第2版)》从核心实现、企业应用和Spring Boot这3个方面,由浅入深、由易到难地对Spring源码展开了系统的讲解,包括Spring 整体架构和环境搭建、容器的基本实现、默认标签的解析、自定义标签的解析、bean的加载、容器的功能扩展、AOP、数据库连接JDBC、整合MyBatis、事务、SpringMVC、远程服务、Spring消息、Spring Boot体系原理等内容。', 'Spring源码深度解析(第2版)', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (23, 'Jon Bentley', '书的内容围绕程序设计人员面对的一系列实际问题展开。作者JonBentley以其独有的洞察力和创造力,引导读者理解这些问题并学会解决方法,而这些正是程序员实际编程生涯中到关重要的。', '编程珠玑(第2版•修订版)', 1);
|
||||
INSERT INTO spring.book (id, author, description, name, status) VALUES (24, 'Mickey W. Mantle', '这是一本系统阐述面对混乱而容易失控的技术开发团队时,如何管理、建设和强化团队,成功交付开发成果的大作。两位作者Mickey W. Mantle和Ron Lichty以合起来近70年的开发管理经验为基础,通过深刻的观察和分析,找到了软件开发管理的核心问题——人的管理,并围绕如何真正理解程序员、找到合适的程序员、与程序员沟通这几个核心话题,一步步展开,扩展到如何以人为本地进行团队建设、管理和项目管理。', '告别失控:软件开发团队管理必读', 1);
|
||||
@ -1,44 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<configuration>
|
||||
<!--包含Spring boot对logback日志的默认配置-->
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
|
||||
<property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
|
||||
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
|
||||
|
||||
<!--重写了Spring Boot框架 org/springframework/boot/logging/logback/file-appender.xml 配置-->
|
||||
<appender name="TIME_FILE"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<encoder>
|
||||
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||
</encoder>
|
||||
<file>${LOG_FILE}</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i</fileNamePattern>
|
||||
<!--保留历史日志一个月的时间-->
|
||||
<maxHistory>30</maxHistory>
|
||||
<!--
|
||||
Spring Boot默认情况下,日志文件10M时,会切分日志文件,这样设置日志文件会在100M时切分日志
|
||||
-->
|
||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||
<maxFileSize>10MB</maxFileSize>
|
||||
</timeBasedFileNamingAndTriggeringPolicy>
|
||||
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
<appender-ref ref="TIME_FILE" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
<!--
|
||||
1、继承Spring boot logback设置(可以在appliaction.yml或者application.properties设置logging.*属性)
|
||||
2、重写了默认配置,设置日志文件大小在100MB时,按日期切分日志,切分后目录:
|
||||
|
||||
my.2017-08-01.0 80MB
|
||||
my.2017-08-01.1 10MB
|
||||
my.2017-08-02.0 56MB
|
||||
my.2017-08-03.0 53MB
|
||||
......
|
||||
-->
|
||||
10
src/main/resources/spy.properties
Normal file
@ -0,0 +1,10 @@
|
||||
driverlist=com.mysql.cj.jdbc.Driver
|
||||
module.log=com.p6spy.engine.logging.P6LogFactory
|
||||
appender=com.p6spy.engine.spy.appender.Slf4JLogger
|
||||
#自定义日志格式
|
||||
logMessageFormat=com.p6spy.engine.spy.appender.CustomLineFormat
|
||||
#格式:%(currentTime)|%(executionTime)|%(category)|connection%(connectionId)|%(sqlSingleLine)
|
||||
customLogMessageFormat=%(category)|conn%(connectionId)|%(sqlSingleLine)
|
||||
databaseDialectDateFormat=yyyy-MM-dd HH:mm:ss
|
||||
databaseDialectTimestampFormat=yyyy-MM-dd HH:mm:ss
|
||||
dateformat=yyyy-MM-dd HH:mm:ss
|
||||
3625
src/main/resources/static/css/animate.css
vendored
@ -1,196 +0,0 @@
|
||||
body{
|
||||
/*background: url("../images/leaves.png");*/
|
||||
background: url("../images/bg.png");
|
||||
/*background: url("../images/green_dust_scratch_@2X.png");*/
|
||||
/*background: url("../images/dust_scratches.png");*/
|
||||
/*background: url("../images/gravel.png");*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********内边距5个级别*********/
|
||||
.m-padding-lr-responsive{
|
||||
padding-left: 4em !important;
|
||||
padding-right: 4em !important;
|
||||
}
|
||||
|
||||
.m-padded-mini{
|
||||
padding:0.2em !important;
|
||||
}
|
||||
.m-padded-tiny{
|
||||
padding:0.3em !important;
|
||||
}
|
||||
.m-padded{
|
||||
padding:1em !important;
|
||||
}
|
||||
.m-padded-tb-mini{
|
||||
padding-top: 0.2em !important;
|
||||
padding-bottom: 0.2em !important;
|
||||
}
|
||||
.m-padded-tb-tiny{
|
||||
padding-top: 0.3em !important;
|
||||
padding-bottom: 0.3em !important;
|
||||
}
|
||||
.m-padded-tb-small{
|
||||
padding-top: 0.5em !important;
|
||||
padding-bottom: 0.5em !important;
|
||||
}
|
||||
.m-padded-tb{
|
||||
padding-top: 1em !important;
|
||||
padding-bottom: 1em !important;
|
||||
}
|
||||
.m-padded-tb-large{
|
||||
padding-top: 2em !important;
|
||||
padding-bottom: 2em !important;
|
||||
}
|
||||
.m-padded-tb-big{
|
||||
padding-top: 3em !important;
|
||||
padding-bottom: 3em !important;
|
||||
}
|
||||
.m-padded-tb-huge{
|
||||
padding-top: 4em !important;
|
||||
padding-bottom: 4em !important;
|
||||
}
|
||||
.m-padded-tb-massive{
|
||||
padding-top: 5em !important;
|
||||
padding-bottom: 5em !important;
|
||||
}
|
||||
|
||||
/**********外边距5个级别*********/
|
||||
.m-margin-tb-tiny{
|
||||
margin-top: 0.3em !important;
|
||||
margin-bottom: 0.3em !important;
|
||||
}
|
||||
|
||||
.m-margin-top-small{
|
||||
margin-top: 0.5em !important;
|
||||
}
|
||||
.m-margin-top{
|
||||
maring-top: 1em !important;
|
||||
}
|
||||
.m-margin-right{
|
||||
margin-right: 1em !important;
|
||||
}
|
||||
.m-margin-left{
|
||||
margin-left: 1em !important;
|
||||
}
|
||||
.m-margin-left-big{
|
||||
margin-left: 3em !important;
|
||||
}
|
||||
.m-margin-top-large{
|
||||
margin-top: 2em !important;
|
||||
}
|
||||
.m-margin{
|
||||
margin: 1em 1em !important;
|
||||
}
|
||||
.m-margin-bottom-mini{
|
||||
margin-bottom: 0.2em !important;
|
||||
}
|
||||
.m-margin-bottom-small{
|
||||
margin-bottom: 0.5em !important;
|
||||
}
|
||||
/**********Test**********/
|
||||
|
||||
/*字体粗细*/
|
||||
.m-text-thin{
|
||||
font-weight: 300 !important;
|
||||
}
|
||||
/*字间距*/
|
||||
.m-text-spaced{
|
||||
letter-spacing: 1px !important;
|
||||
}
|
||||
/*行间距*/
|
||||
.m-text-lined{
|
||||
line-height: 1.8 !important;
|
||||
}
|
||||
/*字体样式组合*/
|
||||
.m-text{
|
||||
font-weight: 300 !important;
|
||||
letter-spacing: 1px !important;
|
||||
line-height: 1.8 !important;
|
||||
}
|
||||
/*设置字体颜色*/
|
||||
.m-black{
|
||||
color: #333 !important;
|
||||
}
|
||||
.m-teal{
|
||||
color: #00B5AD !important;
|
||||
}
|
||||
/*透明度*/
|
||||
.m-opacity-min{
|
||||
opacity: 0.8 !important;
|
||||
}
|
||||
/*透明度*/
|
||||
.m-opacity-tiny{
|
||||
opacity: 0.6 !important;
|
||||
}
|
||||
/******* display*******/
|
||||
.m-inline-blok{
|
||||
display: inline-block !important;
|
||||
}
|
||||
/********position****/
|
||||
.m-right-top{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
.m-fixed{
|
||||
/*绝对定位*/
|
||||
position: fixed !important;
|
||||
z-index: 10 !important;
|
||||
}
|
||||
.m-right-button{
|
||||
bottom: 0 !important;
|
||||
right: 0 !important;
|
||||
}
|
||||
.m-container{
|
||||
max-width: 72em !important;
|
||||
margin: auto !important;
|
||||
}
|
||||
|
||||
.m-container-small{
|
||||
max-width: 60em !important;
|
||||
margin: auto !important;
|
||||
}
|
||||
/***mobile***/
|
||||
|
||||
.m-mobile-show{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.m-mobile-wide{
|
||||
|
||||
}
|
||||
/***shadow****/
|
||||
.m-shadow-small{
|
||||
/*适配浏览器*/
|
||||
-webkit-box-shadow:0 4px 8px rgba(0,0,0,0.2)!important;
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.2)!important;
|
||||
|
||||
}
|
||||
/*手机端*/
|
||||
@media screen and (max-width:768px){
|
||||
.m-mobile-hide{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.m-mobile-show{
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.m-padding-lr-responsive{
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
.m-mobile-clear{
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
.m-mobile-wide{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
11
src/main/resources/static/css/semantic.min.css
vendored
@ -1,335 +0,0 @@
|
||||
@charset "utf-8";
|
||||
|
||||
.typo p {
|
||||
font-size: 16px;
|
||||
font-weight: 300;
|
||||
line-height: 1.8;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
.typo li {
|
||||
font-weight: 300;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
/* 重设 HTML5 标签, IE 需要在 js 中 createElement(TAG) */
|
||||
.typo article, aside, details, figcaption, figure, footer, header, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* HTML5 媒体文件跟 img 保持一致 */
|
||||
.typo audio, canvas, video {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* 要注意表单元素并不继承父级 font 的问题 */
|
||||
.typo button, input, select, textarea {
|
||||
font: 300 1em/1.8 PingFang SC, Lantinghei SC, Microsoft Yahei, Hiragino Sans GB, Microsoft Sans Serif, WenQuanYi Micro Hei, sans-serif;
|
||||
}
|
||||
|
||||
.typo button::-moz-focus-inner,
|
||||
.typo input::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* 去掉各Table cell 的边距并让其边重合 */
|
||||
.typo table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
/* 去除默认边框 */
|
||||
.typo fieldset, img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* 块/段落引用 */
|
||||
.typo blockquote {
|
||||
position: relative;
|
||||
color: #999;
|
||||
font-weight: 400;
|
||||
border-left: 1px solid #1abc9c;
|
||||
padding-left: 1em;
|
||||
margin: 1em 3em 1em 2em;
|
||||
}
|
||||
|
||||
@media only screen and ( max-width: 640px ) {
|
||||
.typo blockquote {
|
||||
margin: 1em 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Firefox 以外,元素没有下划线,需添加 */
|
||||
.typo acronym, abbr {
|
||||
border-bottom: 1px dotted;
|
||||
font-variant: normal;
|
||||
}
|
||||
|
||||
/* 添加鼠标问号,进一步确保应用的语义是正确的(要知道,交互他们也有洁癖,如果你不去掉,那得多花点口舌) */
|
||||
.typo abbr {
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
/* 一致的 del 样式 */
|
||||
.typo del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.typo address, caption, cite, code, dfn, em, th, var {
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* 去掉列表前的标识, li 会继承,大部分网站通常用列表来很多内容,所以应该当去 */
|
||||
.typo ul, ol {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
/* 对齐是排版最重要的因素, 别让什么都居中 */
|
||||
.typo caption, th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.typo q:before,.typo q:after {
|
||||
content: '';
|
||||
}
|
||||
|
||||
/* 统一上标和下标 */
|
||||
.typo sub,.typo sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.typo :root sub,.typo :root sup {
|
||||
vertical-align: baseline; /* for ie9 and other modern browsers */
|
||||
}
|
||||
|
||||
.typo sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
.typo sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
/* 让链接在 hover 状态下显示下划线 */
|
||||
.typo a {
|
||||
color: #1abc9c;
|
||||
}
|
||||
|
||||
.typo a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.typo a {
|
||||
border-bottom: 1px solid #1abc9c;
|
||||
}
|
||||
|
||||
.typo a:hover {
|
||||
border-bottom-color: #555;
|
||||
color: #555;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* 默认不显示下划线,保持页面简洁 */
|
||||
.typo ins,.typo a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* 专名号:虽然 u 已经重回 html5 Draft,但在所有浏览器中都是可以使用的,
|
||||
* 要做到更好,向后兼容的话,添加 class="typo-u" 来显示专名号
|
||||
* 关于 <u> 标签:http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-u-element
|
||||
* 被放弃的是 4,之前一直搞错 http://www.w3.org/TR/html401/appendix/changes.html#idx-deprecated
|
||||
* 一篇关于 <u> 标签的很好文章:http://html5doctor.com/u-element/
|
||||
*/
|
||||
.typo u,.typo .typo-u {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* 标记,类似于手写的荧光笔的作用 */
|
||||
.typo mark {
|
||||
background: #fffdd1;
|
||||
border-bottom: 1px solid #ffedce;
|
||||
padding: 2px;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
/* 代码片断 */
|
||||
.typo pre,.typo code,.typo pre tt {
|
||||
font-family: Courier, 'Courier New', monospace;
|
||||
}
|
||||
|
||||
.typo pre {
|
||||
background: #f8f8f8;
|
||||
border: 1px solid #ddd;
|
||||
padding: 1em 1.5em;
|
||||
display: block;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/* 一致化 horizontal rule */
|
||||
.typo hr {
|
||||
border: none;
|
||||
border-bottom: 1px solid #cfcfcf;
|
||||
margin-bottom: 0.8em;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
/* 底部印刷体、版本等标记 */
|
||||
.typo small,.typo .typo-small,
|
||||
/* 图片说明 */
|
||||
.typo figcaption {
|
||||
font-size: 0.9em;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.typo strong,.typo b {
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* 可拖动文件添加拖动手势 */
|
||||
.typo [draggable] {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.typo .clearfix:before,.typo .clearfix:after {
|
||||
content: "";
|
||||
display: table;
|
||||
}
|
||||
|
||||
.typo .clearfix:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.typo .clearfix {
|
||||
zoom: 1;
|
||||
}
|
||||
|
||||
/* 强制文本换行 */
|
||||
.typo .textwrap,.typo .textwrap td,.typo .textwrap th {
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.typo .textwrap-table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
/* 提供 serif 版本的字体设置: iOS 下中文自动 fallback 到 sans-serif */
|
||||
.typo .serif {
|
||||
font-family: Palatino, Optima, Georgia, serif;
|
||||
}
|
||||
|
||||
/* 保证块/段落之间的空白隔行 */
|
||||
.typo p, .typo pre, .typo ul, .typo ol, .typo dl, .typo form, .typo hr, .typo table,
|
||||
.typo-p, .typo-pre, .typo-ul, .typo-ol, .typo-dl, .typo-form, .typo-hr, .typo-table, blockquote {
|
||||
margin-bottom: 1.2em
|
||||
}
|
||||
|
||||
.typo h1,.typo h2,.typo h3,.typo h4,.typo h5,.typo h6 {
|
||||
font-family: PingFang SC, Verdana, Helvetica Neue, Microsoft Yahei, Hiragino Sans GB, Microsoft Sans Serif, WenQuanYi Micro Hei, sans-serif;
|
||||
font-weight: 100;
|
||||
color: #000;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
/* 标题应该更贴紧内容,并与其他块区分,margin 值要相应做优化 */
|
||||
.typo h1, .typo h2, .typo h3, .typo h4, .typo h5, .typo h6,
|
||||
.typo-h1, .typo-h2, .typo-h3, .typo-h4, .typo-h5, .typo-h6 {
|
||||
margin-top: 1.2em;
|
||||
margin-bottom: 0.6em;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.typo h1, .typo-h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.typo h2, .typo-h2 {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
.typo h3, .typo-h3 {
|
||||
font-size: 1.6em;
|
||||
}
|
||||
|
||||
.typo h4, .typo-h4 {
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
.typo h5, .typo h6, .typo-h5, .typo-h6 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/* 在文章中,应该还原 ul 和 ol 的样式 */
|
||||
.typo ul, .typo-ul {
|
||||
margin-left: 1.3em;
|
||||
list-style: disc;
|
||||
}
|
||||
|
||||
.typo ol, .typo-ol {
|
||||
list-style: decimal;
|
||||
margin-left: 1.9em;
|
||||
}
|
||||
|
||||
.typo li ul, .typo li ol, .typo-ul ul, .typo-ul ol, .typo-ol ul, .typo-ol ol {
|
||||
margin-bottom: 0.8em;
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
.typo li ul, .typo-ul ul, .typo-ol ul {
|
||||
list-style: circle;
|
||||
}
|
||||
|
||||
/* 同 ul/ol,在文章中应用 table 基本格式 */
|
||||
.typo table th, .typo table td, .typo-table th, .typo-table td, .typo table caption {
|
||||
border: 1px solid #ddd;
|
||||
padding: 0.5em 1em;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.typo table th, .typo-table th {
|
||||
background: #fbfbfb;
|
||||
}
|
||||
|
||||
.typo table thead th, .typo-table thead th {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
|
||||
.typo table caption {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* 去除 webkit 中 input 和 textarea 的默认样式 */
|
||||
.typo-input, .typo-textarea {
|
||||
-webkit-appearance: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.typo-em, .typo em, legend, caption {
|
||||
color: #000;
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
/* 着重号,只能在少量(少于100个字符)且全是全角字符的情况下使用 */
|
||||
.typo-em {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.typo-em:after {
|
||||
position: absolute;
|
||||
top: 0.65em;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
content: "・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・";
|
||||
}
|
||||
|
||||
/* Responsive images */
|
||||
.typo img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 162 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 425 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Editor.md
|
||||
*
|
||||
* @file editormd.logo.css
|
||||
* @version v1.5.0
|
||||
* @description Open source online markdown editor.
|
||||
* @license MIT License
|
||||
* @author Pandao
|
||||
* {@link https://github.com/pandao/editor.md}
|
||||
* @updateTime 2015-06-09
|
||||
*/
|
||||
|
||||
/*! prefixes.scss v0.1.0 | Author: Pandao | https://github.com/pandao/prefixes.scss | MIT license | Copyright (c) 2015 */
|
||||
@font-face {
|
||||
font-family: 'editormd-logo';
|
||||
src: url("../fonts/editormd-logo.eot?-5y8q6h");
|
||||
src: url(".../fonts/editormd-logo.eot?#iefix-5y8q6h") format("embedded-opentype"), url("../fonts/editormd-logo.woff?-5y8q6h") format("woff"), url("../fonts/editormd-logo.ttf?-5y8q6h") format("truetype"), url("../fonts/editormd-logo.svg?-5y8q6h#icomoon") format("svg");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
.editormd-logo,
|
||||
.editormd-logo-1x,
|
||||
.editormd-logo-2x,
|
||||
.editormd-logo-3x,
|
||||
.editormd-logo-4x,
|
||||
.editormd-logo-5x,
|
||||
.editormd-logo-6x,
|
||||
.editormd-logo-7x,
|
||||
.editormd-logo-8x {
|
||||
font-family: 'editormd-logo';
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
font-size: inherit;
|
||||
line-height: 1;
|
||||
display: inline-block;
|
||||
text-rendering: auto;
|
||||
vertical-align: inherit;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
.editormd-logo:before,
|
||||
.editormd-logo-1x:before,
|
||||
.editormd-logo-2x:before,
|
||||
.editormd-logo-3x:before,
|
||||
.editormd-logo-4x:before,
|
||||
.editormd-logo-5x:before,
|
||||
.editormd-logo-6x:before,
|
||||
.editormd-logo-7x:before,
|
||||
.editormd-logo-8x:before {
|
||||
content: "\e1987";
|
||||
/*
|
||||
HTML Entity 󡦇
|
||||
example: <span class="editormd-logo">󡦇</span>
|
||||
*/
|
||||
}
|
||||
|
||||
.editormd-logo-1x {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.editormd-logo-lg {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.editormd-logo-2x {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.editormd-logo-3x {
|
||||
font-size: 3em;
|
||||
}
|
||||
|
||||
.editormd-logo-4x {
|
||||
font-size: 4em;
|
||||
}
|
||||
|
||||
.editormd-logo-5x {
|
||||
font-size: 5em;
|
||||
}
|
||||
|
||||
.editormd-logo-6x {
|
||||
font-size: 6em;
|
||||
}
|
||||
|
||||
.editormd-logo-7x {
|
||||
font-size: 7em;
|
||||
}
|
||||
|
||||
.editormd-logo-8x {
|
||||
font-size: 8em;
|
||||
}
|
||||
|
||||
.editormd-logo-color {
|
||||
color: #2196F3;
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
/*! Editor.md v1.5.0 | editormd.logo.min.css | Open source online markdown editor. | MIT License | By: Pandao | https://github.com/pandao/editor.md | 2015-06-09 */
|
||||
/*! prefixes.scss v0.1.0 | Author: Pandao | https://github.com/pandao/prefixes.scss | MIT license | Copyright (c) 2015 */@font-face{font-family:editormd-logo;src:url(../fonts/editormd-logo.eot?-5y8q6h);src:url(.../fonts/editormd-logo.eot?#iefix-5y8q6h)format("embedded-opentype"),url(../fonts/editormd-logo.woff?-5y8q6h)format("woff"),url(../fonts/editormd-logo.ttf?-5y8q6h)format("truetype"),url(../fonts/editormd-logo.svg?-5y8q6h#icomoon)format("svg");font-weight:400;font-style:normal}.editormd-logo,.editormd-logo-1x,.editormd-logo-2x,.editormd-logo-3x,.editormd-logo-4x,.editormd-logo-5x,.editormd-logo-6x,.editormd-logo-7x,.editormd-logo-8x{font-family:editormd-logo;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;font-size:inherit;line-height:1;display:inline-block;text-rendering:auto;vertical-align:inherit;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.editormd-logo-1x:before,.editormd-logo-2x:before,.editormd-logo-3x:before,.editormd-logo-4x:before,.editormd-logo-5x:before,.editormd-logo-6x:before,.editormd-logo-7x:before,.editormd-logo-8x:before,.editormd-logo:before{content:"\e1987"}.editormd-logo-1x{font-size:1em}.editormd-logo-lg{font-size:1.2em}.editormd-logo-2x{font-size:2em}.editormd-logo-3x{font-size:3em}.editormd-logo-4x{font-size:4em}.editormd-logo-5x{font-size:5em}.editormd-logo-6x{font-size:6em}.editormd-logo-7x{font-size:7em}.editormd-logo-8x{font-size:8em}.editormd-logo-color{color:#2196F3}
|
||||