項目概述
項目地址: https://gitee.com/sicauliuyang/blog
- 項目功能流程圖
- 技術組合
後臺: Spring Boot + JPA + thymeleaf框架
數據庫: MySQL
前端UI: Semantic UI框架
- 插件集成
框架搭建
引入spring boot模塊
- web
- Thymeleaf
- JPA
- MySQL
- Aspects
- DevTools
application.yml配置
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
<?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
......
-->
異常處理
- 定義錯誤頁面
在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:最後執行
thymeleaf 模板
-
th:value 和 th:text 的區別
th:value 和input相關
th:text 和div相關 -
在js中,使用[[${內容}]] 來顯示後臺返回的內容
項目經驗
命名約定
Service/DAO層命名約定:
- 獲取單個對象的方法用get做前綴。
- 獲取多個對象的方法用list做前綴。
- 獲取統計值的方法用count做前綴。
- 插入的方法用save(推薦)或insert做前綴。
- 刪除的方法用remove(推薦)或delete做前綴。
- 修改的方法用update做前綴。
註解
-
@Service用於標註業務層組件
-
@Controller用於標註控制層組件(如struts中的action)
-
@Repository用於標註數據訪問組件,即DAO組件.
-
@Component泛指組件,當組件不好歸類的時候,我們可以使用這個註解進行標註。
需要積累
-
jpql 用法
-
jpa 用法