Springboot5 開發(fā)常用技術(shù)整合--筆記1-thymeleaf&異常處理

前言

記錄學(xué)習(xí)過程中中途碰到問題及解決辦法和查找相關(guān)資料的。
現(xiàn)在公司比較流行SpringCloud或阿里的dobbo,這2個(gè)技術(shù)都需要Springboot,因?yàn)镾pringboot在微服務(wù)的基礎(chǔ)。
Beetl模板與thymeleaf模板各有什么優(yōu)勢(shì),應(yīng)該用哪種呢?留后期調(diào)研。

微框架,與Spring4一起誕生,比如SpringMVC中的@RestController,使用它可以在web頁(yè)面直接放回一個(gè)json到web頁(yè)面或app
Springboot可以快速上手,整合了一下子項(xiàng)目(開源框架或第三方開源庫(kù))
Springboot可以依賴很少的配置,就可以十分快速的搭建并運(yùn)行項(xiàng)目。

這里主要采用的基礎(chǔ)項(xiàng)目
Spring Boot 2多模塊 Spring Boot 項(xiàng)目--之多模塊重構(gòu)
項(xiàng)目下載地址

https://yunpan.#/surl_yFtZK2c74HC (提取碼:a184)

涉及到的知識(shí)點(diǎn)

  • 構(gòu)建Springboot項(xiàng)目
  • Springboot接口返回json及jackson使用
  • Springboot熱部署
  • Springboot資源屬性配置
  • Springboot模板引擎--thymeleaf
  • springboot異常處理

Springboot特點(diǎn)

  • 基于Spring,使開發(fā)者快速入門,門檻很低。spring的全家桶提供了非常強(qiáng)大的功能。
  • Springboot可以創(chuàng)建獨(dú)立運(yùn)行的應(yīng)用,而不依賴與容器。
  • 不需要打包成war包,可以放入tomcat中直接運(yùn)行
  • Springboot提供manven極簡(jiǎn)配置,不用在看過多的xml(默認(rèn)配置),切點(diǎn)是會(huì)引入狠多你不需要的包
  • Springboot提供可視化的相關(guān)功能,方便監(jiān)控,比如性能,應(yīng)用的健康程度。
  • Springboot微微服務(wù)SpringCloud鋪路,SpringBoot可以整合很多各式各樣的框架來構(gòu)建微服務(wù),比如dubbo,thrift

構(gòu)建Springboot項(xiàng)目(參考之前的文章)

Spring Boot 1第一個(gè)項(xiàng)目-helloWorld

#官方地址
https://spring.io/

SpringBoot接口返回json及Jackson的基本演繹

Jackson快速入門-csdn

#添加數(shù)據(jù)web api方式返回POST
localhost:8080/person/saveApi?name=牽手生活22&age=18&password=123456
#獲取模擬數(shù)據(jù)返回GET
localhost:8080/person/getUserDemo

先看看實(shí)現(xiàn)的效果時(shí)什么樣的,實(shí)現(xiàn)中功能修改了2個(gè)文件User.java、UserController.java,并增加了Api接口外的類IYounghareJsonResult.java(來自github的LeeJSONResult.java)

saveApi 以api的方式返回--沒有jackson
saveApi 以api的方式返回--沒有jackson

修改的User.java實(shí)體如下

public class User {
    private int id;
    private String name;
    private int age;  //年齡
    @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss a",locale = "zh",timezone = "GMT+8")
    private  Date birthday;  //出生年月

    @JsonIgnore //json返回時(shí),忽略
    private String password; //密碼

    @JsonInclude(JsonInclude.Include.NON_NULL)  //當(dāng)數(shù)據(jù)為空時(shí)不返回
    private String desc;  //描述


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", birthday=" + birthday +
                ", password='" + password + '\'' +
                ", desc='" + desc + '\'' +
                '}';
    }

}

UserController.java增加了saveApi接口


@RestController  //表示是一個(gè)Rest接口  ==@Controller+ @ResponseBody(方法位置)
public class UserController {

    private  final UserRepostory userRepostory;  //沒有初始化,這里采用構(gòu)造器注入的方式

    @Autowired
    public UserController(UserRepostory userRepostory){
        this.userRepostory = userRepostory;

    }

    @PostMapping("/person/save")
    //@RequestBody  ==采用@RestController 不再需要這個(gè)
    public User save(@RequestParam String name,@RequestParam int age,@RequestParam String password){

        User user = new User();
        user.setName(name);
        user.setAge(age);
        user.setPassword(password);

        user.setBirthday(new Date());

        user.setDesc(null);

        if (userRepostory.save(user)){
            System.out.printf("用戶對(duì)象:%s 保存成功\n",user);
        }
        return user;
    }


    @PostMapping("/person/saveApi")
    public IYounghareJSONResult saveApi(@RequestParam String name,@RequestParam int age){

        User user = new User();
        user.setName(name);
        user.setAge(age);

        user.setBirthday(new Date());

        user.setDesc(null);

        if (userRepostory.save(user)){
            System.out.printf("用戶對(duì)象:%s 保存成功\n",user);
        }
        //return user;
        return IYounghareJSONResult.ok(user);
    }

    @GetMapping("/person/getUserDemo")
    //@RequestBody  ==采用@RestController 不再需要這個(gè)
    public User getUserDemo(){

        User user = new User();
        user.setName("牽手");
        user.setAge(18);
        user.setPassword("123456");

        user.setBirthday(new Date());

        user.setDesc(null);


        return user;
    }

}




Get模擬User數(shù)據(jù)返回

IYounghareJsonResult.java 工具類代碼


/**
 *
 * @Title: LeeJSONResult.java
 * @Package com.lee.utils
 * @Description: 自定義響應(yīng)數(shù)據(jù)結(jié)構(gòu)
 *              這個(gè)類是提供給門戶,ios,安卓,微信商城用的
 *              門戶接受此類數(shù)據(jù)后需要使用本類的方法轉(zhuǎn)換成對(duì)于的數(shù)據(jù)類型格式(類,或者list)
 *              其他自行處理
 *              200:表示成功
 *              500:表示錯(cuò)誤,錯(cuò)誤信息在msg字段中
 *              501:bean驗(yàn)證錯(cuò)誤,不管多少個(gè)錯(cuò)誤都以map形式返回
 *              502:攔截器攔截到用戶token出錯(cuò)
 *              555:異常拋出信息
 * Copyright: Copyright (c) 2016
 * Company:Nathan.Lee.Salvatore
 *
 * @author leechenxiang
 * @date 2016年4月22日 下午8:33:36
 * @version V1.0
 */

public class IYounghareJSONResult {

    // 定義jackson對(duì)象
    private static final ObjectMapper MAPPER = new ObjectMapper();

    // 響應(yīng)業(yè)務(wù)狀態(tài)
    private Integer status;

    // 響應(yīng)消息
    private String msg;

    // 響應(yīng)中的數(shù)據(jù)
    private Object data;

    private String ok;  // 不使用

    public static IYounghareJSONResult build(Integer status, String msg, Object data) {
        return new IYounghareJSONResult(status, msg, data);
    }

    public static IYounghareJSONResult ok(Object data) {
        return new IYounghareJSONResult(data);
    }

    public static IYounghareJSONResult ok() {
        return new IYounghareJSONResult(null);
    }

    public static IYounghareJSONResult errorMsg(String msg) {
        return new IYounghareJSONResult(500, msg, null);
    }

    public static IYounghareJSONResult errorMap(Object data) {
        return new IYounghareJSONResult(501, "error", data);
    }

    public static IYounghareJSONResult errorTokenMsg(String msg) {
        return new IYounghareJSONResult(502, msg, null);
    }

    public static IYounghareJSONResult errorException(String msg) {
        return new IYounghareJSONResult(555, msg, null);
    }

    public IYounghareJSONResult() {

    }

//    public static LeeJSONResult build(Integer status, String msg) {
//        return new LeeJSONResult(status, msg, null);
//    }

    public IYounghareJSONResult(Integer status, String msg, Object data) {
        this.status = status;
        this.msg = msg;
        this.data = data;
    }

    public IYounghareJSONResult(Object data) {
        this.status = 200;
        this.msg = "OK";
        this.data = data;
    }

    public Boolean isOK() {
        return this.status == 200;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    /**
     *
     * @Description: 將json結(jié)果集轉(zhuǎn)化為L(zhǎng)eeJSONResult對(duì)象
     *              需要轉(zhuǎn)換的對(duì)象是一個(gè)類
     * @param jsonData
     * @param clazz
     * @return
     *
     * @author leechenxiang
     * @date 2016年4月22日 下午8:34:58
     */
    public static IYounghareJSONResult formatToPojo(String jsonData, Class<?> clazz) {
        try {
            if (clazz == null) {
                return MAPPER.readValue(jsonData, IYounghareJSONResult.class);
            }
            JsonNode jsonNode = MAPPER.readTree(jsonData);
            JsonNode data = jsonNode.get("data");
            Object obj = null;
            if (clazz != null) {
                if (data.isObject()) {
                    obj = MAPPER.readValue(data.traverse(), clazz);
                } else if (data.isTextual()) {
                    obj = MAPPER.readValue(data.asText(), clazz);
                }
            }
            return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     *
     * @Description: 沒有object對(duì)象的轉(zhuǎn)化
     * @param json
     * @return
     *
     * @author leechenxiang
     * @date 2016年4月22日 下午8:35:21
     */
    public static IYounghareJSONResult format(String json) {
        try {
            return MAPPER.readValue(json, IYounghareJSONResult.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     *
     * @Description: Object是集合轉(zhuǎn)化
     *              需要轉(zhuǎn)換的對(duì)象是一個(gè)list
     * @param jsonData
     * @param clazz
     * @return
     *
     * @author leechenxiang
     * @date 2016年4月22日 下午8:35:31
     */
    public static IYounghareJSONResult formatToList(String jsonData, Class<?> clazz) {
        try {
            JsonNode jsonNode = MAPPER.readTree(jsonData);
            JsonNode data = jsonNode.get("data");
            Object obj = null;
            if (data.isArray() && data.size() > 0) {
                obj = MAPPER.readValue(data.traverse(),
                        MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
            }
            return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);
        } catch (Exception e) {
            return null;
        }
    }

    public String getOk() {
        return ok;
    }

    public void setOk(String ok) {
        this.ok = ok;
    }
}

代碼先保存,方便之后修改或提前
https://yunpan.#/surl_yFtcg3T5PvF (提取碼:7df9)


SpringBoot開發(fā)環(huán)境熱部署(可行我好像沒有熱部署成功)

開發(fā)環(huán)境中,如果修改某個(gè)文件,如修改User或、UserController需要重啟服務(wù)器
Springboot使用devtools進(jìn)行熱部署

idea中配置Springboot熱部署

在pom.xml文件中添加

<!-- 熱部署 -->
        <!-- devtools可以實(shí)現(xiàn)頁(yè)面熱部署(即頁(yè)面修改后會(huì)立即生效,
            這個(gè)可以直接在application.properties文件中配置spring.thymeleaf.cache=false來實(shí)現(xiàn)) -->
        <!-- 實(shí)現(xiàn)類文件熱部署(類文件修改后不會(huì)立即生效),實(shí)現(xiàn)對(duì)屬性文件的熱部署。 -->
        <!-- 即devtools會(huì)監(jiān)聽classpath下的文件變動(dòng),并且會(huì)立即重啟應(yīng)用(發(fā)生在保存時(shí)機(jī)),
            注意:因?yàn)槠洳捎玫奶摂M機(jī)機(jī)制,該項(xiàng)重啟是很快的 -->
        <!-- (1)base classloader (Base類加載器):加載不改變的Class,例如:第三方提供的jar包。 -->
        <!-- (2)restart classloader(Restart類加載器):加載正在開發(fā)的Class。 -->
        <!-- 為什么重啟很快,因?yàn)橹貑⒌臅r(shí)候只是加載了在開發(fā)的Class,沒有重新加載第三方的jar包。 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <!-- optional=true, 依賴不會(huì)傳遞, 該項(xiàng)目依賴devtools; 
                之后依賴boot項(xiàng)目的項(xiàng)目如果想要使用devtools, 需要重新引入 -->
            <optional>true</optional>
        </dependency>

修改application.properties 添加如下內(nèi)容(#開始的是注釋)

#熱部署生效
spring.devtools.restart.enabled=true
#設(shè)置重啟的目錄,添加哪個(gè)目錄的文件需要重啟
spring.devtools.restart.additional-paths=src/main/java
# 為amybatis設(shè)置,生成環(huán)境可以刪除
#restart.include.mapper=/mapper-[\\w-\\.]+jar
#restart.include.pagehelper=/pagehelper-[\\w-\\.]+jar
#排除哪個(gè)目錄的文件不需要重啟
#spring.devtools.restart.exclude=static/**,public/**
#classpath目錄下的WEB-INF文件夾內(nèi)容修改不重啟(靜態(tài)文件的修改不需要重啟)
#spring.devtools.restart.exclude=WEB-INF/**
idea設(shè)置熱部署

SpringBoot 資源文件屬性配置application.properties

在pom.xml文件中添加依賴

        <!--#資源文件屬性配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

我在使用@configurationProperties注解時(shí) idea彈出 Spring Boot Annotion processor not found in classpath

創(chuàng)建czgResource.properties資源文件、創(chuàng)建Resouce.java類、創(chuàng)建ResourceController.java類


添加類及資源文件

訪問路徑及效果

localhost:8080/resouce/getResouce
訪問的效果

czgResource.properties


com.younghare.opensource.name=牽手生活--簡(jiǎn)書
com.younghare.opensource.website=http://www.itdecent.cn/u/e09dc5872735
com.younghare.opensource.desc=筆記整理。分享是一種美德,牽手生活,攜手前行
# spring使用@Value標(biāo)簽讀取.properties文件的中文亂碼問題的解決 https://blog.csdn.net/J3oker/article/details/53839210

CzgResouce.java


@Configuration  //表示要引用資源文件的配置
@ConfigurationProperties(prefix="com.younghare.opensource")
@PropertySource(value= "classpath:czgResource.properties")

public class CzgResouce {
    private String name;
    private String webSite;



    private String desc;

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getWebSite() {
        return webSite;
    }

    public void setWebSite(String webSite) {
        this.webSite = webSite;
    }

}

ResourceController.java

@RestController  //表示是一個(gè)Rest接口  ==@Controller+ @ResponseBody(方法位置)
public class ResourceController {

    @Autowired
    private CzgResouce czgResouce;
    @RequestMapping("/resouce/getResouce")
    public IYounghareJSONResult getCzgResouce(){
        CzgResouce bean_Czg_resouce = new CzgResouce();
        BeanUtils.copyProperties(czgResouce, bean_Czg_resouce);
        return IYounghareJSONResult.ok(bean_Czg_resouce);

    }
}


SpringBoot 資源文件配置server以及tomcat及端口

Springboot默認(rèn)是使用tomcat,更多細(xì)節(jié)參考

SpringBoot配置屬性之Server

修改application.properties文件如下:

#####################################################
#
# Server 服務(wù)器端相關(guān)配置
#####################################################
#配置api端口
server.port=8081
#設(shè)定應(yīng)用的context-path,一般來說這個(gè)配置在正式發(fā)布的時(shí)候不配置
#server.servlet.context-path=/IYounghare
#錯(cuò)誤頁(yè)面,指定發(fā)生錯(cuò)誤時(shí),跳轉(zhuǎn)的URL -->BasicErrorController
server.error.path=/error
#session最大超時(shí)時(shí)間(分鐘),默認(rèn)30分鐘
server.servlet.session.timeout=60
#該服務(wù)器綁定IP地址,啟動(dòng)服務(wù)器時(shí)如果本機(jī)不是該IP地址則拋出異常,啟動(dòng)失敗,
#只有特殊需求的情況下才配置,具體根據(jù)各自的業(yè)務(wù)來設(shè)置

#####################################################
#
# Server --tomcat服務(wù)器端相關(guān)配置
#####################################################
#tomcat最大的線程數(shù),默認(rèn)200
#server.tomcat.max-threads=180
#tomcat的URI編碼
server.tomcat.uri-encoding=UTF-8
#存放tomcat的日志,dump等文件的臨時(shí)文件夾,默認(rèn)為系統(tǒng)的tmp文件夾
#如:c:\users\younghare\AppData\Local\Temp\
server.tomcat.accesslog.enabled=true
#server.tomcat.accesslog.pattern=
#accesslog目錄,默認(rèn)在basedir/logs
#server.tomcat.accesslog.directory=
#日志文件目錄
logging.path= D:/czg/czgTemp/springboot-tomcat-tmp
#日志文件名稱,默認(rèn)為spring.log
#logging.file= myapp.log
日志文件名及日志文件路徑

SpringBoot 整合模板引擎freemarker(略)、thyemleaf

在resources資源下創(chuàng)建templates文件夾


創(chuàng)建templates文件夾
整合thymeleaf

在pom.xml中添加依賴

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

在application.properties 添加thymeleaf的配置信息


#####################################################
#
#thymeleaf 靜態(tài)資源配置
#
#####################################################
#前綴,默認(rèn)文件夾
spring.thymeleaf.prefix=classpath:/templates/
#后綴時(shí).html
spring.thymeleaf.suffix=.html
#模式使用html5
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
#deprecated configuration property spring.thymeleaf.content-type 意思是這個(gè)屬性已經(jīng)過時(shí)不被使用
#spring.thymeleaf.content-type=text/html
#content-type 是text和html
spring.thymeleaf.servlet.content-type=text/html 
# 關(guān)閉緩存,即時(shí)刷新,上線生成環(huán)境需要改為true
spring.thymeleaf.cache=false

springboot集成themeleaf報(bào)Namespace 'th' is not bound

thymeleaf增加的文件

ThymeleafController.java

@Controller
@RequestMapping("th_czg") //設(shè)置訪問路徑
public class ThymeleafController {



    @RequestMapping("dynamicThymeleaf")
    public String dynamicThymeleaf(ModelMap map) {
        map.addAttribute("name", "thymeleaf-為什么進(jìn)不了這個(gè)斷點(diǎn)"); ////需要SpringMVC的依賴庫(kù)
        return "thymeleaf/dynamicThymeleaf/dynamicThymeleafDemo";
    }
    @RequestMapping("staticThymeleaf")
    public String staticThymeleaf() {
        return "thymeleaf/staticThymeleaf/thymeleafDemo";
    }
}

thymeleafDemo.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
Thymeleaf模板引擎--靜態(tài)demo
<h1>thymeleafDemo page</h1>

</body>
</html>

dynamicThymeleafDemo.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head >
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
Thymeleaf模板引擎

<!-- 注意: th 等thymeleaf表達(dá)式 ,在直接用瀏覽器打開該html文件時(shí),不會(huì)被加載,只有后臺(tái)有返回對(duì)應(yīng)的值時(shí)才有對(duì)應(yīng)的內(nèi)容-->

<h1 th:text="${name}">hello world~~~~~~~</h1>
</body>
</html>

測(cè)試地址

#測(cè)試靜態(tài)地址
http://localhost:8080/th_czg/staticThymeleaf
#加載動(dòng)態(tài)
http://localhost:8080/th_czg/dynamicThymeleaf
成功加載靜態(tài)thymeleaf
加載動(dòng)態(tài)thymeleaf失敗--需要查原因
Whitelabel Error Page
This application has no configured error view, so you are seeing this as a fallback.

Sun Mar 31 23:30:21 CST 2019
There was an unexpected error (type=Internal Server Error, status=500).
Failed to invoke handler method with resolved arguments: [0][type=org.springframework.validation.support.BindingAwareConcurrentModel][value={}] on public java.lang.String com.younghare.springBoothelloworld.controller.ThymeleafController.dynamicThymeleaf(org.springframework.ui.ModelMap)

網(wǎng)絡(luò)解決方案--好像也沒辦法解決----有哪位大神幫我留言一下
http://javaetmoi.com/2017/12/migration-spring-web-mvc-vers-spring-webflux/
【spring boot學(xué)習(xí)】Model&ModelMap&ModelAndView--csdn

在pom.xml中引入SpringMVC的支持,就解決了

        <!--添加springmvc的支持  public String test(ModelMap map)//需要SpringMVC的依賴庫(kù)-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

thymeleaf常用標(biāo)簽的使用方法

thymeleaf的簡(jiǎn)單用法-常用標(biāo)簽-csdm

  • 基本使用方式
  • 對(duì)象引用方式
  • 時(shí)間類型轉(zhuǎn)換
  • text 與utext
  • URL
  • 引入靜態(tài)資源文件js/css
  • 條件判斷 th:if 或th:unless
  • 循環(huán)th:each
  • th:swith與th:case

thymeleaf綜合例子test.html,來自github

#測(cè)試路徑
http://localhost:8080/th_czg/test
<!DOCTYPE html>
<html xmlns:th="http://www.w3.org/1999/xhtml">
<head lang="en">
    <meta charset="UTF-8" />
    <title></title>

    <!--    <script th:src="@{/static/js/test.js}"></script> -->

</head>
<body>

<div>
    用戶姓名:<input th:id="${user.name}" th:name="${user.name}" th:value="${user.name}"/>
    <br/>
    用戶年齡:<input th:value="${user.age}"/>
    <br/>
    用戶生日:<input th:value="${user.birthday}"/>
    <br/>
    用戶生日:<input th:value="${#dates.format(user.birthday, 'yyyy-MM-dd')}"/>
    <br/>
</div>

<br/>

<div th:object="${user}">
    用戶姓名:<input th:id="*{name}" th:name="*{name}" th:value="*{name}"/>
    <br/>
    用戶年齡:<input th:value="*{age}"/>
    <br/>
    用戶生日:<input th:value="*{#dates.format(birthday, 'yyyy-MM-dd hh:mm:ss')}"/>
    <br/>
</div>

<br/>

text 與 utext :<br/>
<span th:text="${user.desc}">abc</span>
<br/>
<span th:utext="${user.desc}">abc</span>
<br/>
<br/>

URL:<br/>
<a href="" th:href="@{http://www.imooc.com}">網(wǎng)站地址</a>
<br/>

<br/>
<form th:action="@{/th/postform}" th:object="${user}" method="post" th:method="post">
    <input type="text" th:field="*{name}"/>
    <input type="text" th:field="*{age}"/>
    <input type="submit"/>
</form>
<br/>

<br/>
<div th:if="${user.age} == 18">十八歲的天空</div>
<div th:if="${user.age} gt 18">你老了</div>
<div th:if="${user.age} lt 18">你很年輕</div>
<div th:if="${user.age} ge 18">大于等于</div>
<div th:if="${user.age} le 18">小于等于</div>
<br/>

<br/>
<select>
    <option >選擇框</option>
    <option th:selected="${user.name eq 'lee'}">lee</option>
    <option th:selected="${user.name eq 'imooc'}">imooc</option>
    <option th:selected="${user.name eq 'LeeCX'}">LeeCX</option>
</select>
<br/>

<br/>
<table>
    <tr>
        <th>姓名</th>
        <th>年齡</th>
        <th>年齡備注</th>
        <th>生日</th>
    </tr>
    <tr th:each="person:${userList}">
        <td th:text="${person.name}"></td>
        <td th:text="${person.age}"></td>
        <td th:text="${person.age gt 18} ? 你老了 : 你很年輕">18歲</td>
        <td th:text="${#dates.format(user.birthday, 'yyyy-MM-dd hh:mm:ss')}"></td>
    </tr>
</table>
<br/>

<br/>
<div th:switch="${user.name}">
    <p th:case="'lee'">lee</p>
    <p th:case="#{roles.manager}">普通管理員</p>
    <p th:case="#{roles.superadmin}">超級(jí)管理員</p>
    <p th:case="*">其他用戶</p>
</div>
<br/>

</body>
</html>

Springboot異常處理

Springboot配置全局的異常捕獲--web頁(yè)面跳轉(zhuǎn)

頁(yè)面跳轉(zhuǎn)形式
ajax形式
統(tǒng)一返回異常的形式

創(chuàng)建模擬異常的ErrorController.java


@Controller
@RequestMapping("err")
public class ErrorController {

    @RequestMapping("/error")
    public String error() {

        int a = 1 / 0;    //除零錯(cuò)誤

        return "thymeleaf/error";//不存在的地址
    }

    @RequestMapping("/ajaxerror")
    public String ajaxerror() {

        return "thymeleaf/ajaxerror";
    }

    @RequestMapping("/getAjaxerror")
    @ResponseBody
    public IYounghareJSONResult getAjaxerror() {

        int a = 1 / 0;

        return IYounghareJSONResult.ok();
    }
}
#故意除零異常
http://localhost:8080/err/error

springMVC出現(xiàn)Cannot resolve symbol 'HttpServletRequest

在pom.xml中引入SpringMVC的支持

        <!--添加springmvc的支持-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

訪問網(wǎng)頁(yè)http://localhost:8080//err/error 發(fā)現(xiàn)錯(cuò)誤如下圖

除零錯(cuò)誤提示

編寫我們自己的異常處理類IYounghareExceptionHandler.java
注意注解部分

@ControllerAdvice  //spring mvc提供了ControllerAdvice注解對(duì)異常進(jìn)行統(tǒng)一的處理,拿到這些異常信息后,可以做一些處理,比如提供一個(gè)統(tǒng)一的web界
public class IYounghareExceptionHandler {

    public static final String YOUNGHARE_ERROR_VIEW = "thymeleaf/error";

    @ExceptionHandler(value = Exception.class)
    public Object errorHandler(HttpServletRequest reqest,
                               HttpServletResponse response, Exception e) throws Exception {

        e.printStackTrace();

        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", e);
        mav.addObject("url", reqest.getRequestURL());  //發(fā)生錯(cuò)誤的地址
        mav.setViewName(YOUNGHARE_ERROR_VIEW);  //設(shè)置錯(cuò)誤頁(yè)面
        return mav;
    }

}

編寫自己的error.html提示頁(yè)面

<!DOCTYPE html>
<html xmlns:th="http://www.w3.org/1999/xhtml">
<head lang="en">
    <meta charset="UTF-8" />
    <title>捕獲全局異常</title>
</head>
<body>

攔截到了我們捕獲的異常,我們可以根據(jù)項(xiàng)目需要美化該頁(yè)面
<h1 style="color: red">發(fā)生錯(cuò)誤:</h1>
<div th:text="${url}"></div>
<div th:text="${exception.message}"></div>
</body>
</html>

Spring Boot 系列(八)@ControllerAdvice 攔截異常并統(tǒng)一處理

i自定義異常處理頁(yè)面的顯示效果
SpringBoot配置全局的異常捕獲 - ajax形式
測(cè)試地址:
http://localhost:8080//err/ajaxerror

在application.properties文件中為SpringMVC 設(shè)置static地址

#Spring Boot的默認(rèn)靜態(tài)資源的路徑為:===主要是js的文件如ajaxerror.js
#spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
#優(yōu)先級(jí)從從高到低。
spring.mvc.static-path-pattern=/static/**
在chrome中開發(fā)者選項(xiàng)中設(shè)置debug 斷點(diǎn)

到這里先把工程做個(gè)備份

https://yunpan.#/surl_yLKZ52FG45K (提取碼:1a6e)

統(tǒng)一異常處理

定義自己的異常處理類
用@ControllerAdvice+@ExceptionHandler(ServiceException.class) //要捕獲的異常類

統(tǒng)一異常處理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • SpringMVC原理分析 Spring Boot學(xué)習(xí) 5、Hello World探究 1、POM文件 1、父項(xiàng)目...
    jack_jerry閱讀 1,485評(píng)論 0 1
  • 原文鏈接:https://docs.spring.io/spring-boot/docs/1.4.x/refere...
    pseudo_niaonao閱讀 4,896評(píng)論 0 9
  • 在我搭建基于Spring Cloud的微服務(wù)體系應(yīng)用的時(shí)候所需要或者是常用的屬性配置文件,還有這些屬性的用途,此配...
    StrongManAlone閱讀 4,304評(píng)論 0 18
  • 一、SpringBoot簡(jiǎn)介 1.1 原有Spring優(yōu)缺點(diǎn)分析 1.1.1 Spring的優(yōu)點(diǎn)分析 Sprin...
    SingleXu閱讀 4,479評(píng)論 1 20
  • 昨天花300元買了個(gè)心心念念了一周的大大大榴蓮。 同事問道,"你能吃完么?" 我回答,"沒問題,上次兩天就吃完一個(gè)...
    林影2020閱讀 198評(píng)論 2 2

友情鏈接更多精彩內(nèi)容