SpringBoot3---核心特性---2、Web开发III(模板引擎、国际化、错误处理)

在这里插入图片描述
                       星光下的赶路人star的个人主页

                      夏天就是吹拂着不可预期的风

文章目录

  • 1、模板引擎
    • 1.1 Thymeleaf
    • 1.2 基础语法
    • 1.3 属性设置
    • 1.4 遍历
    • 1.5 判断
    • 1.6 属性优先级
    • 1.7 行内写法
    • 1.8 变量选择
    • 1.9 模板布局
    • 1.10 devtools
  • 2、国家化
  • 3、错误处理
    • 3.1 默认机制
    • 3.2 自定义错误响应
    • 3.3 最佳实战

1、模板引擎

  • 由于SpringBoot使用了嵌入式Servlet容器。所以JSP默认是不能使用的。
  • 如果需要服务端页面渲染,优先考虑使用模板引擎。

在这里插入图片描述
模板引擎页面默认放在src/main/resources/templates
SpringBoot包含以下模板引擎的自动配置

  • FreeMarker
  • Groovy
  • Thymeleaf
  • Mustache

Thymeleaf官网:https://www.thymeleaf.org/

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>Good Thymes Virtual Grocery</title>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<link rel="stylesheet" type="text/css" media="all" th:href="@{/css/gtvg.css}" />
</head>
<body>
	<p th:text="#{home.welcome}">Welcome to our grocery store!</p>
</body
</html>

1.1 Thymeleaf

导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

自动配置原理
1、开启了org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration 自动配置。
2、属性绑定在ThymeleafProperties中,对应配置文件spring.thymeleaf内容
3、所以的模板页面默认在classpath:/templates文件夹下
4、默认效果

    • a、所有的模板页面在/classpath:/templates/下面找
    • b、找后缀名为.html的页面

1.2 基础语法

1、核心用法
th:xxx:动态渲染指定的html标签属性值、或者th指令(遍历、判断等)

  • th:text:标签体内文本值渲染
    • thutext:不会转义,显示为html原本的样子
  • th:属性:标签指定属性渲染
  • th:attr:标签任意属性渲染
  • th:if、th:each、…:其他th指令
  • 例如
<p th:text="${content}">原内容</p>
<a th:href="${url}">登录</a>
<img src="../../images/gtvglogo.png" 
     th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />

表达式:用来动态取值

  • ${}:变量取值:使用model共享给页面的值都直接用${}
  • @{}:url路径
  • #{}:国际化消息
  • ~{}:片段引用
  • *{}:变量选择:需要配置th:object不到对象

系统工具&内置对象:详细文档
● param:请求参数对象
● session:session对象
● application:application对象
● #execInfo:模板执行信息
● #messages:国际化消息
● #uris:uri/url工具
● #conversions:类型转换工具
● #dates:日期工具,是java.util.Date对象的工具类
● #calendars:类似#dates,只不过是java.util.Calendar对象的工具类
● #temporals: JDK8+ java.time API 工具类
● #numbers:数字操作工具
● #strings:字符串操作
● #objects:对象操作
● #bools:bool操作
● #arrays:array工具
● #lists:list工具
● #sets:set工具
● #maps:map工具
● #aggregates:集合聚合工具(sum、avg)
● #ids:id生成工具

2、语法示例
表达式:

  • 变量取值:${…}
  • url取值:@{…}
  • 国际化消息:#{…}
  • 变量选择:*{…}
  • 片段引用:~{…}

常见:

  • 文本:‘one text’,‘another one’…
  • 数字:0,34,…
  • 布尔:true,false
  • null:null
  • 变量名:one,sometext,main,…

文本操作:

  • 拼串:+
  • 文本替换:|The name is ${name}|

布尔操作

  • 二进制运算:and,or
  • 取反:!,not

比较运算

  • 比较:>,<,<=,>=(gt,lt,ge,le)
  • 等值运算:=,!=

条件运算

  • if-then :(if)?(then)
  • if-then-else:(if)?(then):(else)

特殊操作

  • 无操作

所有以上都可以嵌套组合

'User is of type ' + (${user.isAdmin()} ? 'Administrator' : (${user.type} ?: 'Unknown'))

1.3 属性设置

  1. th:href=“@{/product/list}”
  2. th:attr=“class=${active}”
  3. th:attr=“src=@{/images/gtvglogo.png},title=${logo},alt=#{logo}”
  4. th:checked=“${user.active}”
<p th:text="${content}">原内容</p>
<a th:href="${url}">登录</a>
<img src="../../images/gtvglogo.png" 
     th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />

1.4 遍历

语法:th:each=“元素名,迭代状态:${集合}”

<tr th:each="prod : ${prods}">
  <td th:text="${prod.name}">Onions</td>
  <td th:text="${prod.price}">2.41</td>
  <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>

<tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'">
  <td th:text="${prod.name}">Onions</td>
  <td th:text="${prod.price}">2.41</td>
  <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>

iterStat有以下属性:
● ndex:当前遍历元素的索引,从0开始
● count:当前遍历元素的索引,从1开始
● size:需要遍历元素的总数量
● current:当前正在遍历的元素对象
● even/odd:是否偶数/奇数行
● first:是否第一个元素
● last:是否最后一个元素

1.5 判断

th:if

<a
  href="comments.html"
  th:href="@{/product/comments(prodId=${prod.id})}"
  th:if="${not #lists.isEmpty(prod.comments)}"
  >view</a

th:switch

<div th:switch="${user.role}">
  <p th:case="'admin'">User is an administrator</p>
  <p th:case="#{roles.manager}">User is a manager</p>
  <p th:case="*">User is some other thing</p>
</div>

1.6 属性优先级

  • 判断
  • 遍历
  • 判断
<ul>
  <li th:each="item : ${items}" th:text="${item.description}">Item description here...</li>
</ul>

Order Feature Attributes
1 片段包含 th:insert th:replace
2 遍历 th:each
3 判断 th:if th:unless th:switch th:case
4 定义本地变量 th:object th:with
5 通用方式属性修改 th:attr th:attrprepend th:attrappend
6 指定属性修改 th:value th:href th:src …
7 文本值 th:text th:utext
8 片段指定 th:fragment
9 片段移除 th:remove

1.7 行内写法

[[…]] or [(…)]

<p>Hello, [[${session.user.name}]]!</p>

1.8 变量选择

<div th:object="${session.user}">
  <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
  <p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
  <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
</div>

等同于

<div>
  <p>Name: <span th:text="${session.user.firstName}">Sebastian</span>.</p>
  <p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>
  <p>Nationality: <span th:text="${session.user.nationality}">Saturn</span>.</p>
</div

1.9 模板布局

  • 定义模板:th:fragment
  • 引用模板:~{templatename::selector}
  • 插入模板:th:insert、th:replace
<footer th:fragment="copy">&copy; 2011 The Good Thymes Virtual Grocery</footer>

<body>
  <div th:insert="~{footer :: copy}"></div>
  <div th:replace="~{footer :: copy}"></div>
</body>
<body>
  结果:
  <body>
    <div>
      <footer>&copy; 2011 The Good Thymes Virtual Grocery</footer>
    </div>

    <footer>&copy; 2011 The Good Thymes Virtual Grocery</footer>
  </body>
</body>

1.10 devtools

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
      </dependency>

修改页面后;ctrl+F9刷新效果;
java代码的修改,如果devtools热启动了,可能会引起一些bug,难以排查

2、国家化

国际化的自动配置参照MessageSourceAutoConfiguration

实现步骤:
1、Spring Boot在类路径根下查找messages资源绑定文件。文件名为:message.properties.
2、多语言可以定义多个消息文件,命名为message_区域代码.properties。如:

  • messages.properties:默认
  • messages_zh_CN.properties:中文环境
  • messages_en_US.properties:英文环境

3、在程序中自动注入MessageSource组件,获取国际化的配置项值
4、在页面中可以使用表达式#{}获取国际化的配置项值

    @Autowired  //国际化取消息用的组件
    MessageSource messageSource;
    @GetMapping("/haha")
    public String haha(HttpServletRequest request){

        Locale locale = request.getLocale();
        //利用代码的方式获取国际化配置文件中指定的配置项的值
        String login = messageSource.getMessage("login", null, locale);
        return login;
    }

3、错误处理

3.1 默认机制

错误处理的自动配置都在ErrorMvcAutoConfiguration中,两大核心机制:

  • SpringBoot会自适应处理错误,响应页面或JSON数据
  • SpringMVC的错位处理机制依然保留,MVC处理不了,才会交给Boot进行处理

在这里插入图片描述

  • 发送错误以后,转发给/error路径,SpringBoot在底层写好应该BasicErrorController,专门处理这个请求
	@RequestMapping(produces = MediaType.TEXT_HTML_VALUE) //返回HTML
	public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
		HttpStatus status = getStatus(request);
		Map<String, Object> model = Collections
			.unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML)));
		response.setStatus(status.value());
		ModelAndView modelAndView = resolveErrorView(request, response, status, model);
		return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
	}

	@RequestMapping  //返回 ResponseEntity, JSON
	public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
		HttpStatus status = getStatus(request);
		if (status == HttpStatus.NO_CONTENT) {
			return new ResponseEntity<>(status);
		}
		Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));
		return new ResponseEntity<>(body, status);
	}
  • 错误页面是这么解析的
//1、解析错误的自定义视图地址
ModelAndView modelAndView = resolveErrorView(request, response, status, model);
//2、如果解析不到错误页面的地址,默认的错误页就是 error
return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);

容器中专门有一个错误视图解析器

@Bean
@ConditionalOnBean(DispatcherServlet.class)
@ConditionalOnMissingBean(ErrorViewResolver.class)
DefaultErrorViewResolver conventionErrorViewResolver() {
    return new DefaultErrorViewResolver(this.applicationContext, this.resources);
}

SpringBoot解析自定义错误页的默认规则

	@Override
	public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
		ModelAndView modelAndView = resolve(String.valueOf(status.value()), model);
		if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
			modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);
		}
		return modelAndView;
	}

	private ModelAndView resolve(String viewName, Map<String, Object> model) {
		String errorViewName = "error/" + viewName;
		TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName,
				this.applicationContext);
		if (provider != null) {
			return new ModelAndView(errorViewName, model);
		}
		return resolveResource(errorViewName, model);
	}

	private ModelAndView resolveResource(String viewName, Map<String, Object> model) {
		for (String location : this.resources.getStaticLocations()) {
			try {
				Resource resource = this.applicationContext.getResource(location);
				resource = resource.createRelative(viewName + ".html");
				if (resource.exists()) {
					return new ModelAndView(new HtmlResourceView(resource), model);
				}
			}
			catch (Exception ex) {
			}
		}
		return null;
	}

容器中有一个默认的名为error的view;提供了默认白页功能

@Bean(name = "error")
@ConditionalOnMissingBean(name = "error")
public View defaultErrorView() {
    return this.defaultErrorView;
}

封装了JSON格式的错误信息

	@Bean
	@ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)
	public DefaultErrorAttributes errorAttributes() {
		return new DefaultErrorAttributes();
	}

规则:
1、解析一个错误页
(1)如果发生了500、404、503、403这些错误

  • 如果有模板引擎,默认在classpath:/templates/error/精确码.html
  • 如果没有模板引擎,在静态资源文件夹下找精确码.html
    (2)如果匹配不到精确码.html这些精确的错误页,就去找5xx.html,4xx.html模糊匹配
  • 如果有模板引擎,默认在classpath:/template/error/5xx.html
  • 如果没有模板引擎,在静态资源目录下找5xx.html

2、如果模板引擎路径templates下有error.html页面,就直接去渲染

3.2 自定义错误响应

1、自定义json响应
使用@ControllerAdvice+@ExceptionHandler进行统一异常处理

2、自定义页面响应
根据boot的错误页面规则,自定义页面模板

3.3 最佳实战

  • 前后分离
    • 后台发生的所有错误,@ControllerAdvice+@Exceptionhandler进行统一异常处理
  • 服务端页面渲染
    • 不可预知的一些,HTTP码表示的服务器或客户端错误
      • 给classpath:/templates/error/下面,放常用精确的错误码页面。500.html,404.html
    • 发生业务错误
      • 核心业务,每一种错误,都应该代码控制,跳转到自己定制的错误页
      • 通用业务,classpath:/templates/error.html页面,显示错误信息

页面,JSON,可用的Model数据如下
在这里插入图片描述

在这里插入图片描述
                      您的支持是我创作的无限动力

在这里插入图片描述
                      希望我能为您的未来尽绵薄之力

在这里插入图片描述
                      如有错误,谢谢指正;若有收获,谢谢赞美

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/62730.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nginx+flask+uwsgi部署遇到的坑

文章目录 1.环境&#xff1a;2.uwsgi_conf.ini具体配置内容3.nginx 具体配置4.具体命令(注意使用pip3命令安装)5.服务异常排查 1.环境&#xff1a; centos8 uWSGI 2.0.22 gmssl 3.2.2 nginx version: nginx/1.18.0 项目目录&#xff1a; 2.uwsgi_conf.ini具体配置内容 [uws…

cocos creator 的input.on 不生效

序&#xff1a; 1、执行input.on的时候发现不生效 2、一直按控制台也打印不出来console.log 3、先收藏这篇&#xff0c;因为到时候cocos要开发serveApi的时候&#xff0c;你得选一款趁手的后端开发并且&#xff0c;对习惯用ts写脚本的你来说&#xff0c;node是入门最快&#xf…

IDEA中怎么使用git下载项目到本地,通过URL克隆项目(giteegithub)

点击 新建>来自版本控制的项目 点击后会弹出这样一个窗口 通过URL拉取项目代码 打开你要下载的项目仓库 克隆>复制 gitee github也是一样的 返回IDEA 将刚刚复制的URL粘贴进去选择合适的位置点击克隆 下载完成

深挖 Threads App 帖子布局,我进一步加深了对CSS网格布局的理解

当我遇到一个新产品时&#xff0c;我首先想到的是他们如何实现CSS。当我遇到Meta的Threads时也不例外。我很快就探索了移动应用程序&#xff0c;并注意到我可以在网页上预览公共帖子。 这为我提供了一个深入挖掘的机会。我发现了一些有趣的发现&#xff0c;我将在本文中讨论。 …

24届近5年重庆邮电大学自动化考研院校分析

今天给大家带来的是重庆邮电大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、重庆邮电大学 学校简介 重庆邮电大学简称"重邮"&#xff0c;坐落于直辖市-重庆市&#xff0c;入选国家"中西部高校基础能力建设工程”、国家“卓越工程师教育培养计划…

java的StringBuffer类和StringBuilder类

目录 StringBufferStringBuffer简介StringBuffer类的继承关系StringBuffer类的底层实现创建StringBuffer对象StringBuffer类的常用方法 StringBuilderStringBuilder简介 StringBuffer StringBuffer简介 StringBuffer对象是一个字符序列可变的字符串(String类不可变)。它和Str…

Java中Integer方法

先进行专栏介绍 本专栏是自己学Java的旅途&#xff0c;纯手敲的代码&#xff0c;自己跟着黑马课程学习的&#xff0c;并加入一些自己的理解&#xff0c;对代码和笔记 进行适当修改。希望能对大家能有所帮助&#xff0c;同时也是请大家对我进行监督&#xff0c;对我写的代码进行…

springboot快速整合Memcached缓存技术

目录 Memcached基本介绍 Memcached安装 springboot技术整合 规范化定义配置属性 Memcached基本介绍 memcached是一套分布式的快取系统&#xff0c;与redis相似,当初是Danga Interactive为了LiveJournal所发展的&#xff0c;但被许多软件&#xff08;如MediaWiki&#xff…

道本科技受邀参加建筑产业互联网推动建筑产业现代化体系构建座谈会,以数字化产品为建筑行业注入新动能!

2023年7月底&#xff0c;道本科技作为中国建筑业协会合作伙伴&#xff0c;受邀参加了建筑产业互联网推动建筑产业现代化体系构建座谈会。在这次座谈会上&#xff0c;道本科技旗下产品“合规数”“合同智能审查”和“智合同范本库”被中国建筑&#xff08;中小企业&#xff09;产…

【笔记】第94期-冯永吉-《湖仓集一体关键技术解读》-大数据百家讲坛-厦大数据库实验室主办20221022

https://www.bilibili.com/video/BV1714y1j7AU/?spm_id_from333.337.search-card.all.click&vd_sourcefa36a95b3c3fa4f32dd400f8cabddeaf

后端进阶之路——万字总结Spring Security与数据库集成实践(五)

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★前端炫酷代码分享 ★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ 解决算法&#xff0c;一个专栏就够了★ ★ 架…

JavaScript-DOM

目录 DOM 访问节点 节点信息 操作节点 DOM DOM&#xff1a;Document Object Model&#xff08; 文档对象模型&#xff09; 访问节点 使用 getElement系列方法访问指定节点 getElementById()、getElementsByName()、getElementsByTagName()根据层次关系访问节点 节点属性 属…

jmeter使用步骤

jmeter 使用步骤 1&#xff0c;进入jmeter目录中的bin目录&#xff0c;双击jmeter.bat 打开 2&#xff0c;右键test plan 创建线程组 3&#xff0c;配置线程组参数 4&#xff0c;右键刚刚创建的线程组&#xff0c;创建请求&#xff0c;填写请求地址 5&#xff0c;需要携带to…

AI让分子“起死回生”:拯救抗生素的新希望

生物工程师利用人工智能(AI)使分子“起死回生”[1]。 为实现这种分子“复活”,研究人员应用计算方法对来自现代人类(智人)和我们早已灭绝的远亲尼安德特人和丹尼索瓦人的蛋白质数据进行分析。这使研究人员能够鉴定出可以杀死致病细菌的分子&#xff0c;从而促进研发用于治疗人类…

11. 使用tomcat中碰到的一些问题

文章目录 问题一&#xff1a;Tomcat的startup.bat启动后出现乱码问题二&#xff1a;一闪而退之端口占用问题三&#xff1a;非端口问题的一闪而退问题四&#xff1a;服务器的乱码和跨域问题问题五: 在tomcat\webapps\下创建文件夹为什么tomcat重启就会丢失问题六&#xff1a;Tom…

大后台,小前台——组合式创新加速推进产教融合

2023年8月1日&#xff0c;由成都知了汇智科技有限公司组织召开的“2023产教融合项目推进闭门研讨会”于成都市高新区软件园G8区7楼正式举行&#xff0c;本次会议基于“产业链的用人需求、资本链的回报诉求、服务链的价值要求、教育链的延伸需求”进行交流探讨&#xff0c;形成稳…

区块链实验室(17) - FISCO BCOS的P2P网络层分析

首先启动FISCO BCOS的示例网络&#xff0c;即4个节点的强连通网络。每个节点与其余3个节点存在网络连接。 打开控制台&#xff0c;可以看到当前有21个区块。 其中1个节点的P2P端口是30301&#xff0c;监测这个节点的端口。 该端口的部分流量见下图所示。白底部分是某1秒钟接收到…

【雕爷学编程】Arduino动手做(184)---快餐盒盖,极低成本搭建机器人实验平台

吃完快餐粥&#xff0c;除了粥的味道不错之外&#xff0c;我对个快餐盒的圆盖子产生了兴趣&#xff0c;能否做个极低成本的简易机器人呢&#xff1f;也许只需要二十元左右 知识点&#xff1a;轮子&#xff08;wheel&#xff09; 中国词语。是用不同材料制成的圆形滚动物体。简…

Java源码解析-重点集合框架篇

Java 源码解析&#xff0c;集合篇 一&#xff1a;故事背景二&#xff1a;数据结构2.1 线性结构2.2 非线性结构 三&#xff1a;集合分类3.1 结构图 三&#xff1a;详细分析3.1 List3.1.1 ArrayList3.1.1.1 底层结构3.1.1.2 主要特点 3.1.2 LinkedList3.1.2.1 底层结构3.1.2.2 主…

简单易懂的Transformer学习笔记

1. 整体概述 2. Encoder 2.1 Embedding 2.2 位置编码 2.2.1 为什么需要位置编码 2.2.2 位置编码公式 2.2.3 为什么位置编码可行 2.3 注意力机制 2.3.1 基本注意力机制 2.3.2 在Trm中是如何操作的 2.3.3 多头注意力机制 2.4 残差网络 2.5 Batch Normal & Layer Narmal 2.…