项目地址: https://gitee.com/sicauliuyang/blog
后台: Spring Boot + JPA + thymeleaf框架
数据库: MySQL
前端UI: Semantic UI框架
编辑器 Markdown
内容排版 typo.css
动画 animate.css
代码高亮 prism
目录生成 Tocbot
滚动侦测 waypoints
平滑滚动 jquery.scrollTo
二维码生成 qrcode.js
application.yml:
spring:
thymeleaf:
mode: HTML
profiles:
active: dev # 启动开发配置文件
applicatioin-dev.yml:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
username: root
password: 123456
jpa:
hibernate:
# 每次运行程序,没有表格会新建表格,表内有数据不会清空,只会更新
ddl-auto: update
# 在控制台显示sql语句
show-sql: true
logging:
level:
root: info
cn.edu.bupt.blog: debug
file:
name: log/blog-dev.log
server:
port: 8082
application-pro.yml:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
username: root
password: 123456
jpa:
hibernate:
# 每次运行程序,没有表格会新建表格,表内有数据不会清空,只会更新
ddl-auto: none
# 在控制台显示sql语句
show-sql: true
logging:
level:
root: info
cn.edu.bupt.blog: debug
file:
name: log/blog-dev.log
server:
port: 8081
在资源文件夹下创建日志配置文件
logback-spring.xml
<configuration>
<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" />
<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}.%ifileNamePattern>
<maxHistory>30maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MBmaxFileSize>
timeBasedFileNamingAndTriggeringPolicy>
rollingPolicy>
appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="TIME_FILE" />
root>
configuration>
在template/error文件夹下定义常见的错误页面,如下。springboot项目出现错误时可以调用对应错误页面。
404.html
500.html
统一处理异常
/**
* 拦截所有controller抛出的异常
*/
@ControllerAdvice
public class ControllerExceptionHandle {
// 获取日志日志对象
private final Logger logger = LoggerFactory.getLogger(ControllerExceptionHandle.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.getClass());
// 当代码错误引发的异常类与注解标记的类一直,则抛出异常
if(AnnotationUtils.findAnnotation(this.getClass(), ResponseStatus.class) != null) {
throw e;
}
ModelAndView mav = new ModelAndView();
mav.addObject("url",request.getRequestURL());
mav.addObject("excepation",e);
// 跳转到对应页面
mav.setViewName("error/error");
return mav;
}
}
上面统一处理异常代码中 相应状态码如下
定义异常类
/**
* 资源找不到
*/
@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);
}
}
当抛出NotFoundException ,统一异常处理类会抛出该异常,这时由springboot框架自己处理。再到template/error文件夹下寻找404.html页面,如果有调用该页面。
th:utext: 对于显示的字符串不转义,th:remove=“tag” 移除html标签
在错误页面添加这点代码,方便在代码中检查
创建aop切面类
/**
* 记录日志类
* 通过aspect
*/
@Aspect // 标记这是一个切面类
/**
* 泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),
* 我们就可以使用@Component来标注这个类
*/
@Component
public class LogAspect {
// 用于控制台日志输出
private final Logger logger = LoggerFactory.getLogger(this.getClass());
// 定义切点,用于扫描:cn.edu.bupt.blog.web 的所有类的所有方法
@Pointcut("execution(* cn.edu.bupt.blog.web.*.*(..))")
public void log() {
}
// 界面点之前执行
@Before("log()")
public void doBefore(JoinPoint joinPoint) {
// 获取HttpServletRequest
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String url = request.getRequestURL().toString();
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 doAfterReturning(Object result) {
logger.info("Return ------ {}",result );
}
// 请求日志对象
private class RequestLog{
private String url;
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) +
'}';
}
}
}
doAfterReturning:最后执行
th:value 和 th:text 的区别
th:value 和input相关
th:text 和div相关
在js中,使用[[${内容}]] 来显示后台返回的内容
Service/DAO层命名约定:
@Service用于标注业务层组件
@Controller用于标注控制层组件(如struts中的action)
@Repository用于标注数据访问组件,即DAO组件.
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
jpql 用法
jpa 用法