Springboot 開發Thymeleaf應用 、靜態資源、攔截器、AOP

開發Thymeleaf應用

簡介

Thymeleaf屬於視圖顯示技術、模板技術。

模板文件(模板表達式)+模板數據=HTML結果(性能比JSP文件要高)

JSP文件(EL+JSTL+其他標籤)+模板數據=HTML結果

JSP-->Servlet-->.Class-->HTML結果

模板和JSP區別:

  • 模板生成HTML界面效率高,JSP效率低
  • 模板學習和使用簡單,JSP複雜

使用

  1. 在pom.xml中定義thymeleaf包、web包
  2. 在application.properties配置tomcat端口
  3. 定義啓動類,main啓動
  4. 定義HelloController,將數據放入Model或ModelAndView
  5. 在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爲基礎,將通用業務從原有業務組件抽離出來獨立封裝,之後再通過配置作用回去。

目的:實現業務解耦。

  1. 切入什麼功能?(切面組件)
  2. 給誰切入功能?(切入點表達式)
  3. 什麼時機切入?(通知類型)

案例:日誌記錄,記錄調用Controller組件類型、方法、時間、執行時間

  1. 記錄controller調用信息
  2. 給所有controller方法切入,within(cn.xdl.controller..*)
  3. 方法執行後切入,環繞通知 @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;
	}
	
}

結果:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章