Compare commits

...

7 Commits

Author SHA1 Message Date
xieYj
9167c8d652 update env and port 2021-05-12 17:18:53 +08:00
xieYj
0dcc3c12ec Merge remote-tracking branch 'origin/demo-restful' into demo-restful
# Conflicts:
#	src/test/java/com/example/demorest/DemoRestApplicationTests.java
2021-05-12 17:17:41 +08:00
xieYj
295b022762 init demo-restful 2021-05-12 17:16:54 +08:00
xieYj
e1c2edb92b init demo-restful 2021-05-12 17:16:03 +08:00
xieYj
6d4d53054d 1. 帖子作者发布帖子,帖子标题可以为空,帖子内容不能为空,且不少于16个汉字;
2. 帖子可以加入不多于五个话题,且话题不能重复加入;
3. 帖子标题和内容通过内容过滤后方能发布,如果未能通过内容过滤,则需要经过运营审核之后才能发布。
2021-05-11 18:14:32 +08:00
xieYj
a18783fca4 add: 多环境配置 2021-05-11 11:42:19 +08:00
xieYj
086ab27837 init project 2021-05-11 11:32:14 +08:00
506 changed files with 853 additions and 88549 deletions

20
.gitignore vendored
View File

@ -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/

View File

@ -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"]

View File

@ -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 服务器相关操作更佳熟练。对自己的代码有了更佳严格的要求、 有了不同的
代码和业务思想,巩固了后端技术栈的知识,对代程序编写有更加深刻的认识!
## 感谢
原作者Githubhttps://github.com/yerenping/blog

40
build.gradle Normal file
View 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

Binary file not shown.

View 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
View 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
View 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
View File

@ -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
View File

@ -0,0 +1 @@
rootProject.name = 'demo-rest'

View File

@ -1,15 +0,0 @@
package cn.allms;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* springboot启动器
*/
@SpringBootApplication
public class MxBlogApplication {
public static void main(String[] args) {
SpringApplication.run(MxBlogApplication.class, args);
}
}

View File

@ -1,97 +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();
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-----------");
}
//@AfterReturning(returning = "result",pointcut = "log()")
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) +
'}';
}
}
}

View File

@ -1,61 +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;
}
}

View File

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

View File

@ -1,31 +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;
}
}

View File

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

View File

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

View File

@ -1,74 +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;
}
}

View File

@ -1,78 +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
* @return
* @param model
*/
@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";
}
}

View File

@ -1,52 +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";
}
}

View File

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

View File

@ -1,169 +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());
}
}

View File

@ -1,72 +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";
}
}

View File

@ -1,127 +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";
}
}

View File

@ -1,123 +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";
}
}

View File

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

View File

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

View File

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

View File

@ -1,29 +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);
}

View File

@ -1,20 +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);
}

View File

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

View File

@ -1,38 +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;
}
}

View File

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

View File

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

View File

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

View File

@ -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 + '\'' +
'}';
}
}

View File

@ -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 + '\'' +
'}';
}
}

View File

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

View File

@ -1,97 +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);
}

View File

@ -1,27 +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);
}

View File

@ -1,66 +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);
}

View File

@ -1,64 +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);
}

View File

@ -1,20 +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);
}

View File

@ -1,167 +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);
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,68 +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);
}
}
}
}
}

View File

@ -1,46 +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"));
}
}

View File

@ -1,87 +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));
}
}

View File

@ -1,34 +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()]);
}
}

View File

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

View File

@ -0,0 +1,16 @@
package com.example.demorest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author josxy
*/
@SpringBootApplication
public class DemoRestApplication {
public static void main(String[] args) {
SpringApplication.run(DemoRestApplication.class, args);
}
}

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,20 +1,21 @@
#数据库驱动mysql
spring:
application:
name: restful-api
datasource:
driver-class-name: com.mysql.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: josxy
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: update
show-sql: true
#日志打印
logging:
level:
root: info
com.yrp: debug
file: log/blog-dev.log
ddl-auto: create
server:
port: 9420
servlet:
context-path: /api
port: 8001

View File

@ -1,22 +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: log/-blogpro.log
# 服务端口
server:
port: 9420

View 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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -1,18 +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

View File

@ -1,20 +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

View File

@ -1,17 +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

View 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 LanguageSQL是一种功能强大的数据库语言。它基于关系代数运算功能丰富、语言简洁、使用方便灵活已成为关系数据库的标准语言。', '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);

View File

@ -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
......
-->

View 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

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because one or more lines are too long

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 425 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

File diff suppressed because it is too large Load Diff

View File

@ -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 &#xe1987;
example: <span class="editormd-logo">&#xe1987;</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;
}

View File

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

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More