SpringBoot3框架,Web开发(下)

模板引擎

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

Thymeleaf

Thymeleaf 是一个现代的服务器端 Java 模板引擎,适用于 Web 和独立 环境

格式:

<!DOCTYPE html>
<html xmlns:th="[<http://www.thymeleaf.org>](<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>

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. 默认效果
    1. 所有的模板页面在 classpath:/templates/下面找
    2. 找后缀名为.html的页面

Thymeleaf基础语法

核心用法

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

  • th:text:标签体内文本值渲染
    • th:utext:不会转义,显示为html原本的样子。即会识别html语法
  • th:属性:标签指定属性渲染
  • th:attr:标签任意属性渲染,可以指定多个属性,语法为:例如,要指定src和style属性,th:attr=”src=${imgUrl},style=${style}”
  • th:if th:each...:其他th指令
    • th:if:可以传入布尔类型的值,true表示该标签生效,false表示该标签不生效

    • 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>
      
    • th:each :遍历操作,语法:th:each=”元素名 : ${集合}”或者th:each=”元素名,迭代状态 : ${集合}”,迭代状态有以下取值:

      • index:当前遍历元素的索引,从0开始
      • count:当前遍历元素的索引,从1开始
      • size:需要遍历元素的总数量
      • current:当前正在遍历的元素对象
      • even/odd:是否偶数/奇数行
      • first:是否第一个元素
      • last:是否最后一个元素
      <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>
      

      使用状态信息直接在表中加一列 stats.迭代状态 (也是使用${stats.迭代状态})就可以在表中显示出每一行(集合中的每个元素)的状态信息

表达式

  • ${}:变量取值,使用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生成工具

这些工具类中有一系列函数可以调用,见官网文档

一些其他操作

文本操作:

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

布尔操作:

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

比较运算:

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

条件运算:

  • if-then: (if)?(then)
  • if-then-else: (if)?(then):(else)
  • default: (value)?:(defaultValue)

行内写法:

使用[[...]] or [(...)] 在行内使用其要引入的数据

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

属性优先级

OrderFeatureAttributes
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

变量选择

使用th:object属性指定一个对象,再使用*{}获取其对象的属性,例:

<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>

Thymeleaf模板布局

  • 定义模板: th:fragment
  • 引用模板:~{templatename(模板名)::selector(片段名)}
  • 插入模板:th:insertth: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>

devtools

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

修改页面后;ctrl+F9刷新效果;

java代码的修改,如果devtools热启动了,可能会引起一些bug,难以排查

国际化

实现步骤

  1. Spring Boot 在类路径根下查找messages资源绑定文件。文件名为:messages.properties
  2. 多语言可以定义多个消息文件,命名为messages_区域代码.properties。如:
    1. messages.properties:默认
    2. messages_zh_CN.properties:中文环境
    3. 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;
    }

错误处理

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

    1. SpringBoot 会自适应处理错误响应页面JSON数据
    1. SpringMVC的错误处理机制依然保留,MVC处理不了,才会交给boot进行处理
  1. 发生错误以后,到了SpringBoot,转发给/error路径,SpringBoot在底层写好一个 BasicErrorController的组件,专门处理这个请求
  2. 再通过与客户端的内容协商,选择返回json数据还是选择返回具体页面
    1. 如果是返回json则将信息转化为json形式返回
    2. 如果是返回页面,会找解析错误的自定义视图地址,如果找不到,默认的错误也就是error页
  3. 如果模板引擎路径templates下有 error.html页面,就直接渲染
  4. 容器中有一个错误视图解析器
    1. 如果发生了500、404、503、403 这些错误
      1. 如果有模板引擎,默认在 classpath:/templates/error/**精确码.html**
      2. 如果没有模板引擎,在静态资源文件夹下找 精确码.html
    2. 如果匹配不到精确码.html这些精确的错误页,就去找5xx.html4xx.html模糊匹配
      1. 如果有模板引擎,默认在 classpath:/templates/error/5xx.html
      2. 如果没有模板引擎,在静态资源文件夹下找 5xx.html

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

建议错误处理:

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

错误信息页面可以使用一些model数据用行内写法[[ ]]和变量取值${}(对这些错误的信息的model数据变量取值)加在页面上

可用的model数据:

  • timestamp:错误的时间信息
  • status:状态码
  • error:错误类型
  • trace:错误堆信息
  • message:错误信息
  • path:错误对应的路径

嵌入式容器

Servlet容器:管理、运行Servlet组件(Servlet、Filter、Listener)的环境,一般指服务器

自动配置原理

  • SpringBoot 默认嵌入Tomcat作为Servlet容器。
  • 自动配置类ServletWebServerFactoryAutoConfigurationEmbeddedWebServerFactoryCustomizerAutoConfiguration
  • 自动配置类开始分析功能。xxxxAutoConfiguration
  1. ServletWebServerFactoryAutoConfiguration 自动配置了嵌入式容器场景
  2. 绑定了ServerProperties配置类,所有和服务器有关的配置 server
  3. ServletWebServerFactoryAutoConfiguration 导入了 嵌入式的三大服务器 TomcatJettyUndertow
    1. 导入 TomcatJettyUndertow 都有条件注解。系统中有这个类才行(也就是导了包)
    2. 都给容器中 ServletWebServerFactory放了一个 web服务器工厂(造web服务器的)
    3. web服务器工厂 都有一个功能,getWebServer获取web服务器
    4. TomcatServletWebServerFactory 创建了 tomcat。
  4. ServletWebServerApplicationContextioc容器,启动的时候会调用创建web服务器
  5. Spring**容器刷新(启动)**的时候,会预留一个时机,用来刷新子容器。onRefresh() ,刷新子容器时会调用 onRefresh()

总结:

  • Web场景的Spring容器启动,在onRefresh的时候,会调用创建web服务器的方法。
  • Web服务器的创建是通过WebServerFactory搞定的。容器中又会根据导了什么包条件注解,启动相关的 服务器配置,默认EmbeddedTomcat会给容器中放一个 TomcatServletWebServerFactory,导致项目启动,自动创建出Tomcat
  • 修改server下的相关配置就可以修改服务器参数

全面接管SpringMVC(全手动)

全面接管SpringMVC即使用全手动模式配置SpringMVC,实现WebMvcConfiger接口,再在配置类上加上@EnableWebMvc注解,再手动配置SpringMvc

WebMvcAutoConfiguration

WebMvcAutoConfiguration是web场景的自动配置类,会自动导入一些配置:

  • 支持RESTful的filter:HiddenHttpMethodFilter
  • 支持非POST请求,请求体携带数据:FormContentFilter
  • 导入EnableWebMvcConfiguration:导入了HandlerAdapter,HandlerMapping,一些解析器等组件
  • WebMvcAutoConfigurationAdapter配置生效,会导入一些视图解析器,内容协商解析器,过滤器,静态资源链等相关的mvc底层组件

@EnableWebMvc

  1. @EnableWebMvc给容器中导入 DelegatingWebMvcConfiguration组件,他是 WebMvcConfigurationSupport
  2. WebMvcAutoConfiguration有一个核心的条件注解, @ConditionalOnMissingBean(WebMvcConfigurationSupport.class),容器中没有WebMvcConfigurationSupportWebMvcAutoConfiguration才生效.
  3. @EnableWebMvc 导入 WebMvcConfigurationSupport 导致 WebMvcAutoConfiguration 失效。导致禁用了默认行为

但是建议使用手自一体方式

Web新特性

ProblemDetails

  1. ProblemDetailsExceptionHandler是一个@ControllerAdivce,集中处理系统的异常
  2. ProblemDetailsExceptionHandler只能处理springmvc的一些指定异常
  3. ProblemDetails默认是关闭的

开启ProblemDetails返回, 使用新的MediaType

Content-Type: application/problem+json+ 额外扩展返回,例:

{
    "type": "about:blank",
    "title": "Method Not Allowed",
    "status": 405,
    "detail": "Method 'POST' is not supported.",
    "instance": "/list"
}

函数式Web

步骤:

  1. 给容器中放一个Bean:RouterFunction<ServerResponse>
    1. 核心四大对象:
      1. RouterFunction:定义路由信息(请求内容,接收请求的handler)
      2. RequestPredicate:定义请求(请求方式,请求参数)
      3. ServerRequest:封装请求完整信息
      4. ServerResponse:封装响应完整信息
  2. 先定义路由信息,再定义请求,最后封装完整请求和响应的信息,例:
@Configuration(proxyBeanMethods = false)
public class MyRoutingConfiguration {

    private static final RequestPredicate ACCEPT_JSON = accept(MediaType.APPLICATION_JSON);

    @Bean
    public RouterFunction<ServerResponse> routerFunction(MyUserHandler userHandler) {
        return route()
                .GET("/{user}", ACCEPT_JSON, userHandler::getUser)
                .GET("/{user}/customers", ACCEPT_JSON, userHandler::getUserCustomers)
                .DELETE("/{user}", ACCEPT_JSON, userHandler::deleteUser)
                .build();
    }

}
@Component
public class MyUserHandler {

    public ServerResponse getUser(ServerRequest request) {
        ...//具体业务
        return ServerResponse.ok().build();
    }

    public ServerResponse getUserCustomers(ServerRequest request) {
        ...//要获取请求的信息可以使用request对象的一系列方法
        return ServerResponse.ok().body(...);//在body中的对象,会以json形式返回
    }

    public ServerResponse deleteUser(ServerRequest request) {
        ...
        return ServerResponse.ok().build();
    }

}

  • 20
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二狗mao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值