springboot如何使用Thymeleaf和一些相關操作


一、Thymeleaf簡介

Thymeleaf模板引擎主要用來做視圖的展示。在springboot中默認支持thymeleaf,來替代原來ssm項目中的jsp。相較於jsp或其他的模板引擎,thymeleaf有如下特點:

1)動靜結合,thymeleaf 既可以在有后台交互的情況下運行,也可以在不與后台交互的情況下運行,方便前后端開發人員協同開發;

2)多方言的支持,支持spring的標准方言,可以和springboot完美整合;

 

二、Thymeleaf 使用

1)在pom.xml文件中導入依賴;

<!--        thymeleaf 模板依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

2) 在templates 目錄下新建html頁面,並加入thymeleaf的命名空間即可使用,Thymeleaf的命名空間為:xmlns:th="http://www.thymeleaf.org"

3)引入命名空間之后,我們便可以使用thymeleaf的語法來展示數據;

 

三、Thymeleaf 的語法

Thyemeleaf的使用與jsp中的jstl和el表達式使用方法相似;

Thymeleaf 表達式:用來取值,寫在thymeleaf屬性標簽中。

1) ${} :從域中取值,與el表達式類似;

注意:當對象不存在的情況下,去獲取對象的屬性的話,會拋出異常;

所以取值的時候,如果可能存在不存在的情況,需在對象后添加?判斷對象是否存在;

默認從request域中取值;

 常見的內置對象:

1)session: 從session中獲取值,類似jsp中的${session} == ${sessionScope}

2)request:  httpServletRequest對象,${request} == ${pageContext.request.} 

3)servletContext: ServletContext對象(application域)

4)ctx : 上下文對象

5)vars: 上下文變量

6)local: 上下文的語言環境;

 

2) *{} :選擇變量表達式,需要配合th:object 屬性標簽一起使用。th:object可以綁定一個對象,*{屬性名} 去獲取綁定的對象的屬性;

3) #{} :獲取國際化消息表達式;

4) ~{} :代碼塊表達式,用來加載代碼片段。 需配合 th:replace    th:insert     th:include 三個屬性標簽使用。類似 <%@include >;

<body>
<!--  insert 插入代碼片段 ,包含最外層的標簽  ~{模板名稱::代碼片段名稱}
       </head><header>
            <div>頭部導航欄</div>
            <ul>
                <li>首頁</li>
                <li>文章</li>
            </ul>
        </header></div>
 -->
<div th:insert="~{admin/common::head}">
    原來內容
</div>

<table>
    <tr>
        <td>序號</td>
        <td>用戶名</td>
        <td>密碼</td>
        <td>狀態</td>
        <td>創建時間</td>
        <td>操作</td>
    </tr>
<!--
       for(: xx)
        th:each="遍歷出來的單個對象,iterStat(狀態對象):要遍歷的集合
-->
    <tr th:object="${admin}" th:each="admin,iterStat:${adminPageInfo.list}">
        <td th:text="${iterStat.count}">序號</td>
        <td th:text="*{account}">用戶名</td>
        <td th:text="*{password}">密碼</td>
        <td>
<!--          th:if  判斷標簽是否顯示  -->
            <span th:if="*{status eq '0'}" style="color: coral">正常</span>
            <span th:if="*{status eq '1'}" style="color: red">注銷</span>
        </td>
        <td th:text="*{createtime}">創建時間</td>
        <td>
<!--          @{} 中鏈接地址需要傳值的,通過在鏈接地址后面添加(key=value,key2=value2)的形式添加  -->
            <a th:href="@{/admin/edit(id=*{id})}">修改</a>
            <a th:href="@{/admin/delete(id=*{id})}">刪除</a>
        </td>
    </tr>
</table>

<!--   替換內容,將引入的標簽,替換掉現有標簽 ,
     標簽內容全部過來
       <footer>
            <div>版權所有,翻版必究</div>
        </footer>
 -->
<div th:replace="~{admin/common::footerDiv}">
    <span>原來內容</span>
</div>
<!--   include 加載代碼片段,
   不包含最外面的標簽
         <div>
            <div>版權所有,翻版必究</div>
        </div>
     -->
<div th:include="~{admin/common::footerDiv}">
    <span>原來內容</span>
</div>
</body>

5) @{} :用來定義鏈接url地址。 比如 img src  a href <script > <link>等;

 

四、Thymeleaf 屬性標簽

編寫在html標簽上,替代原有的html標簽屬性,以達到動態展示數據。

Thymelaef屬性標簽都是以th:開頭。幾乎涵蓋了html標簽中所有的屬性。

常見的標簽:

1) th:text :設置當前標簽 的文本內容;

2) th:value : 設置當前元素的value值;

3) th:utext: 設置當前元素的html內容;

4) th:title ;

5) th:if :相當於<c:if> 用來做判斷,如果表達式為false,則當前標簽不顯示;

6) th:each :相當於<c:foreach> ,用來遍歷數據;

7) th:object : 聲明變量,配合*{} 一起使用;

8) th:fragment :用來定義一個代碼片段,以供th:insert replace include 調用;

9) th:insert : 將代碼片段的所有內容(包含最外層的標簽)插入到使用th:insert的html標簽中。 <div th:insert=”~{}”></div>;

10) th:replace : 將代碼片段替換掉使用th:insert的html標簽;

11) th:include :將代碼片段的內容(不包含最外層的標簽)插入到使用th:insert的html標簽中;

 

五、Thymeleaf 函數

 Thymeleaf 函數寫在表達式中,用來對數據進行數據格式話,字符串操作,集合操作等

 常用的函數:

1) #strings: 字符串操作函數,跟java中string的api類似。 跟jstl el 表達式中 fn:函數標簽類似。

2) #dates :用來對日期進行操作,日期的格式化,獲取日期的年月日,創建日期等

3) #numbers: 用來對數值進行格式化,保留指定小數位,分隔符展示等

4) #arrays 數組的操作,獲取數組長度,是否包含某個元素等等。。。

5) #maps: map集合操作

6) 。。。

測試代碼:

@Controller
public class FunctionController {

    @GetMapping("/function")
    public String function(ModelMap modelMap){
        modelMap.put("name","james");
        modelMap.put("birthday",new Date());
        modelMap.put("arrayData",new String[]{"james","yao","yi"});
        return "function.html";
    }
}

function.html界面:

<body>
     <h1>字符函數</h1>
     長度:<span><div th:text="${#strings.length(name)}"></div></span></br>
     首字母大寫:<span><div th:text="${#strings.capitalize(name)}"></div></span></br>
     contains:<span><div th:text="${#strings.contains(name,'jam')}"></div></span></br>
     isEmpty:<span><div th:text="${#strings.isEmpty(name)}"></div></span></br>
     substring:<span><div th:text="${#strings.substring(name,0,2)}"></div></span></br>

<h1>日期函數</h1>
     不格式化:<span th:text="${birthday}"></span><br/>
format 指定格式:<span th:text="${#dates.format(birthday,'yyyy-MM-dd HH:mm:ss')}"></span><br/>
format不指定格式:<span th:text="${#dates.format(birthday)}"></span><br/>
year:<span th:text="${#dates.year(birthday)}"></span><br/>
month:<span th:text="${#dates.month(birthday)}"></span><br/>
dayOfWeekName:<span th:text="${#dates.dayOfWeekName(birthday)}"></span><br/>
創建日期:<span th:text="${#dates.createToday()}"></span><br/>

<h1>數值函數</h1>
整數的格式化:<span th:text="${#numbers.formatInteger(100,5)}"></span><br/>
<!--     COMMA 逗號  POINT.WHITESPACE 空格-->
整數的格式化帶分隔符:<span th:text="${#numbers.formatInteger(100,5,'COMMA')}"></span><br/>
<!--     前兩個參數與整數一樣,第三個參數為保留的小數位,四舍五入-->
 小數的格式化:<span th:text="${#numbers.formatDecimal(100.94876,5,3)}"></span><br/>
 <!--     COMMA 逗號  POINT.WHITESPACE 空格-->
 小數的格式化帶分隔符:<span th:text="${#numbers.formatDecimal(100.94876,3,3,'COMMA')}"></span><br/>
百分比:<span th:text="${#numbers.formatPercent(0.783646,5,3)}"></span><br/>

<h1>數組函數arrays</h1>
數組長度:<span th:text="${#arrays.length(arrayData)}"></span><br/>
是否為空:<span th:text="${#arrays.isEmpty(arrayData)}"></span><br/>
是否包含:<span th:text="${#arrays.contains(arrayData,'james')}"></span><br/>

<h1>list集合函數</h1>
<!--     #lists #maps  #sets-->
<!--<span th:text="${#lists.contains()}"></span>-->
</body>

測試結果為:

 

六、Springboot中文件上傳下載

Springboot中文件上傳下載與springmvc 完全一致。

1)控制層代碼:

@Controller
public class FileController {

    @GetMapping("/toUpload")
    public String toUpload(){
        return "upload.html";
    }
    @PostMapping("/upload")
    public String upload(MultipartFile multipartFile, ModelMap modelMap) throws IOException {
//        if (multipartFile==null){ throw new FileNotFoundException(); }
        //獲取文件名
        String filename = multipartFile.getOriginalFilename();
        // 日期 時間戳+用戶ID
        //隨機一個uuid名稱
        String randName = UUID.randomUUID().toString();
        //a.png
        String fileType = filename.substring(filename.lastIndexOf("."));
        List<String> allowType= Arrays.asList(new String[]{".png",".jpg"});
        if (!allowType.contains(fileType)){//不允許的文件類型
            throw new NotAllowFileTypeException(" 001","上傳的格式不支持:"+fileType);
        }
        Date date = new Date();
        SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
        String today=sdf.format(date);
        String path="E:/headpic/"+ today;
        //創建文件對象用來指定保存的位置和名稱
        File file=new File(path,randName+fileType);
        //如果父目錄不存在,創建
        if (!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        //將文件保存到對應的目錄
        multipartFile.transferTo(file);
        modelMap.put("filePath",today+"/"+randName+fileType);
        modelMap.put("fileName",randName+fileType);
        return "upload.html";
    };

    @GetMapping("/download")
    public ResponseEntity<byte[]> download(String fielName,String filePath) throws IOException {
        File file=new File("E:/headpic/",filePath);
        if(!file.exists()|| !file.isFile()){
            throw new FileNotFoundException("未找到文件:"+filePath);
        }
        HttpHeaders httpHeaders=new HttpHeaders();
        //設為返回的數據類型為二進制流
        httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        //設置瀏覽器以附件形式打開下載
        httpHeaders.setContentDispositionFormData("attachment",fielName);
        byte[] bytes = FileCopyUtils.copyToByteArray(file);
        return new ResponseEntity<>(bytes,httpHeaders, HttpStatus.OK);
    }
}

2)后台upload.html頁面代碼為:

<body>
<form th:action="@{/upload}" method="post" enctype="multipart/form-data">
    請選擇文件:<input type="file" name="multipartFile">
    <input type="submit" value="上傳">
</form>
<a th:href="@{/download(fileName=*{fileName},filePath=*{filePath})}" th:text="${'點擊下載'+fileName}"></a>
</body>

3)要想實現文件的上傳和下載,必須要配置資源映射;

/**
 * springmvc相關配置類
 * WebMvcConfigurer 用來配置springmvc的配置項
 */
@Configuration//配置類注解
public class WebConfig implements WebMvcConfigurer {
    /**
     * 配置資源映射,相當於xml中的 <resource></resource>
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
                .addResourceHandler("/headpic/**")//配置請求地址
                .addResourceLocations("file:E:/headpic/");//配置資源目錄
    }
}

4)最后我們的界面是這樣的;

 

七、Springboot全局異常處理

Spring3.2之后,可以通過@ControllerAdvice+@ExceptionHandler 這兩個注解來實現全局的異常處理。

@ControllerAdvice 加載類上面;

@ExceptionHandler 添加在異常處理的方法上面;

 

步驟:

1)寫一個全局異常處理的類,並添加@ControllerAdvice注解;

2)寫對應異常處理的方法,並在方法上添加@ExceptionHandler注解;

@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     * @ExceptionHandler:指定處理特定異常,當項目發生指定的異常時,便會進入此方法
     * @param e
     * @return
     */ @ExceptionHandler(FileNotFoundException.class)
    public Object handlerException(FileNotFoundException e){
        String message = e.getMessage();
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error/fileNotFound.html");
        modelAndView.addObject("msg",message);
        return modelAndView;
    }
    @ExceptionHandler(Exception.class)
    public ModelAndView handlerException(Exception e){
        String message = e.getMessage();
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error/fileNotFound.html");
        modelAndView.addObject("msg",message);
        return modelAndView;
    }
}

3)寫一個自定義異常的NotAllowFileTypeException.java類;

/**
 * 自定義異常
 */
public class NotAllowFileTypeException extends RuntimeException{
    private String code;
    public NotAllowFileTypeException(String message, String code){
        super(message);
        this.code=code;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
}

4)fileNotFound.html頁面;

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>文件找不到</title>
</head>
<body>
<h1>您查找的文件不存在</h1>
<div th:text="${msg}"></div>
</body>
</html>

5)我們現在先測試第一種情況,拋FileNotFoundException 的異常,是一個文件找不到的異常,我們還是在上一個文件上傳下載的頁面中來測試;

①、我們的方法時,先上傳圖片,然后再去那個文件夾中把所有圖片刪掉即可;

點擊鏈接下載,正常情況下,是可以下載的,但是

 

由於我們把文件夾中的圖片刪除了,文件夾里面就沒有圖片了,就會走fileNotFound.html頁面;拋出異常;

結果就是這樣的:

②我們再測試一個文件類型不對的異常,使用普通的異常Exception,當我們上傳.png,.jpg以外格式的圖片時,就會拋出異常;

點擊上傳,

 

八、Springboot中的攔截器

1)配置攔截器

/**
 * springmvc相關配置類
 * WebMvcConfigurer 用來配置springmvc的配置項
 */
@Configuration//配置類注解
public class WebConfig implements WebMvcConfigurer {
    /**
     * 配置springmvc攔截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())//添加攔截器對象
                .addPathPatterns("/**")//指定需要攔截的地址
                .excludePathPatterns("/admin/login","/admin/toLogin","/headpic/**")//指定放行的請求
                .order(1);//指定順序
    }
}

2)登錄攔截;

控制層:

//跳轉到登錄頁面
    @RequestMapping("/toLogin")
    public String toLogin(){
        return "/admin/login.html";
    }
    @PostMapping("/login")
    public String login(TAdmin tAdmin, HttpSession session,ModelMap modelMap){
        TAdmin tAdmin1=adminService.selectByAccount(tAdmin.getAccount());
        if (tAdmin1==null||!tAdmin.getPassword().equals(tAdmin1.getPassword())){
           //回傳登錄信息
            modelMap.put("admin",tAdmin);
            modelMap.put("msg","用戶名密碼不正確");
            return "/admin/login.html";
        }
        //將對象放session域中
        session.setAttribute("admin",tAdmin1);
        return "/admin/detail.html";
    }

登錄攔截器LoginInterceptor,java;

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        TAdmin admin = (TAdmin) request.getSession().getAttribute("admin");
        if (admin!=null){
            return true;
        }
        response.sendRedirect(request.getContextPath()+"/admin/toLogin");
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

這樣,攔截器的話,差不多就可以了;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM