開發Thymeleaf應用
簡介
Thymeleaf屬於視圖顯示技術、模板技術。
模板文件(模板表達式)+模板數據=HTML結果(性能比JSP文件要高)
JSP文件(EL+JSTL+其他標籤)+模板數據=HTML結果
JSP-->Servlet-->.Class-->HTML結果
模板和JSP區別:
- 模板生成HTML界面效率高,JSP效率低
- 模板學習和使用簡單,JSP複雜
使用
- 在pom.xml中定義thymeleaf包、web包
- 在application.properties配置tomcat端口
- 定義啓動類,main啓動
- 定義HelloController,將數據放入Model或ModelAndView
-
在src\main\resources\templates目錄下定義html模板
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
</dependencies>
server.port=8888
@SpringBootApplication
public class MyBootApplication {
public static void main(String[] args) {
SpringApplication.run(MyBootApplication.class, args);
}
}
@Controller
public class HelloController {
@RequestMapping("/hello/say1")
public ModelAndView say1() {
ModelAndView mav = new ModelAndView();
mav.setViewName("hello");
mav.getModel().put("msg", "hello");
return mav;
}
}
<!DOCTYPE html>
<html xmlns="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1 th:text="${msg}">xxx</h1>
</body>
</html>
運行之後網頁源碼,就相當於把msg信息拿到了xxx的位置。
循環的是HelloController中添加的集合。
each標籤循環
用於判斷標籤的變量初始化
只顯示爲ture的一個p標籤。
SpringBoot靜態資源
SpringBoot預定義了以下幾個目錄,用於存放靜態資源,例如jpg、css、js、html、mp4等。
- META-INF/resources 優先級最高
- resources
- static
- public 優先級最低
如果需要自定義靜態資源目錄,可以採用Java配置。
package cn.xdl.config
@Configuration
public class MyResourceConfiguration implements WebMvcConfigurer{
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String[] locations = {
"classpath:/mystatic/",
"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"};
registry.addResourceHandler("/**")
.addResourceLocations(locations);
}
}
1.定義攔截器實現組件
package cn.xdl.interceptor
@Component
public class SomeInterceptor implements HandlerInterceptor{
public boolean preHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler)
throws Exception {
System.out.println("------執行攔截器preHandle方法-------");
Object user = request.getSession().getAttribute("user");
if(user==null){
//指定響應界面
response.sendRedirect("/login");
return false;
}
return true;
}
}
2.配置攔截器組件
package cn.xdl.config
@Configuration
public class MyInterceptorConfiguration implements WebMvcConfigurer{
@Autowired
private SomeInterceptor some;
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(some)
.addPathPatterns("/hello/say1");
}
}
運行測試:
對登錄進行攔截,需要指定響應界面login.html
在攔截器組件定義中進行session判斷,響應界面需要從一個Controller中獲取。
再次測試:運行自動跳到界面。
SpringBoot異常處理
SpringBoot底層提供了一個BasicErrorController組件,有兩個/error處理方法,一個返回JSON,一個返回HTML。啓動自動配置後,ErrorMvcAutoConfiguration組件會創建Controller對象納入Spring容器中。 當請求處理髮生異常後,框架會採用轉發方式調用/error處理。
全局處理方式
自定義一個ErrorController,繼承AbstractErrorController父類,定義/error請求處理方法。
@Controller
@RequestMapping("/error")
public class MyErrorController extends AbstractErrorController{
public MyErrorController(ErrorAttributes errorAttributes) {
super(errorAttributes);
// TODO Auto-generated constructor stub
}
@Override
public String getErrorPath() {
// TODO Auto-generated method stub
return "/error";
}
//一般請求
@RequestMapping(produces={"text/html"})
public ModelAndView errorHtml(){
ModelAndView mav = new ModelAndView();
mav.setViewName("myerror");// /templates/myerror.html
mav.getModel().put("error", "自定義錯誤消息");
return mav;
}
//ajax請求
@RequestMapping
@ResponseBody
public Map<Object,Object> error(){
Map<Object,Object> map = new HashMap<>();
map.put("error", "自定義錯誤消息");
return map;
}
}
寫一個myerror.html頁面
測試:
局部處理方法
採用SpringMVC中的@ExceptionHandler
@Controller
public class ExceptionController {
//訪問的時候,網址後數字爲正常,其他字符爲異常
@RequestMapping("/exception/{id}")
public String execute(@PathVariable("id")String id){
int i = Integer.parseInt(id);
return "hello";//return 到 hello.html頁面
}
//局部處理的實現方法
@ExceptionHandler//處理當前Controller異常
public ModelAndView handleException(Exception ex){
ModelAndView mav = new ModelAndView();
mav.setViewName("myerror2");
mav.getModel().put("error", ex);
return mav;
}
}
自定義反json
正常:
錯誤自動調用全局:
再寫個myerror2頁面,體現特殊局部處理:
SpringBoot AOP (spring-boot-starter-aop)
AOP簡介
面向切面編程,Aspect Oriented Programming
OOP Object Oriented Programming
AOP編程以OOP爲基礎,將通用業務從原有業務組件抽離出來獨立封裝,之後再通過配置作用回去。
目的:實現業務解耦。
- 切入什麼功能?(切面組件)
- 給誰切入功能?(切入點表達式)
- 什麼時機切入?(通知類型)
案例:日誌記錄,記錄調用Controller組件類型、方法、時間、執行時間
- 記錄controller調用信息
- 給所有controller方法切入,within(cn.xdl.controller..*)
- 方法執行後切入,環繞通知 @Around
package cn.xdl.aop;
import java.lang.reflect.Method;
import java.util.Date;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.RequestMapping;
@Component
@Aspect
public class LogBean {
@Around("within(cn.xdl.controller..*)")
public Object exec(ProceedingJoinPoint pjp) throws Throwable{
//前置邏輯
StopWatch watch = new StopWatch();
watch.start();
Object obj = pjp.proceed();//調用目標組件方法
watch.stop();
//後置邏輯,記錄日誌
String targetClass = pjp.getTarget().getClass().getName();
String methodName = pjp.getSignature().getName();
//根據組件和方法名獲取method對象
String uri = "";
Method[] methods = pjp.getTarget().getClass().getMethods();
for(Method m:methods){
//獲取執行的Method對象
if(m.getName().equals(methodName)){
//根據Method對象獲取前面的@RequestMapping註解對象
RequestMapping mapping =
m.getAnnotation(RequestMapping.class);
uri = mapping.value()[0];
}
}
System.out.println("調用的組件:"+targetClass
+" 方法名:"+methodName+" 映射請求:"+uri
+" 調用時間:"+new Date()+" 執行時間:"+watch.getTotalTimeMillis());
return obj;
}
}
結果: