美文网首页
SpringBoot学习笔记(六)SpringBoot_Web开

SpringBoot学习笔记(六)SpringBoot_Web开

作者: 啊_6424 | 来源:发表于2019-03-06 17:11 被阅读0次

    一、Thymeleaf模板

    (一)简介

    SpringBoot项目是jar包形式,内嵌Tomcat,故不支持jsp
    静态的html太麻烦

    • 故SpringBoot推荐使用模板引擎(JSP,Velocity,Freemarker,Thymeleaf......)
    • 不同模板引擎之间的原理一样,但语法有差异
    • SpringBoot推荐使用Thymeleaf(语法更简单,功能更强大)


      原理图.png

    (二)引入Thymeleaf

    pom.xml

    //切换版本
    <properties>
       <thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
       <!--布局功能的支持程序thymeleaf3主程序layout2以上版本-->
       <thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
    </properties>
    .......
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    

    导入一些适配包时,一定要参考官方文档,避免出错


    (三)Thymeleaf语法

    官方文档:https://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.html

    语法教程::https://blog.csdn.net/u014042066/article/details/75614906

    public class ThymeleafProperties {
        private static final Charset DEFAULT_ENCODING;
        public static final String DEFAULT_PREFIX = "classpath:/templates/";
        public static final String DEFAULT_SUFFIX = ".html";
        private boolean checkTemplate = true;
        private boolean checkTemplateLocation = true;
        private String prefix = "classpath:/templates/";
        private String suffix = ".html";
        private String mode = "HTML";
    ........
    }
    

    即只要我们把HTML页面放在 classpath:/templates/,Thymeleaf就能自动渲染
    success.html

    <!DOCTYPE html>
    <!--导入Thymeleaf名称空间-->
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>成功!</h1>
        <!--th:text是设置文本内容-->
        <div th:text="${Hello}"></div>
    </body>
    </html>
    
    @Controller
    public class HelloController {
       //classpath:/templates/success.html
        //查出一些数据,在页面展示
        @RequestMapping("/success")
        public String success(Map<String,Object> map) {
            map.put("Hello","你好!");
            return "success";
        }
    }
    
    image.png

    浏览器访问即可


    image.png
    • th:任意html属性------替换原生属性


      image.png
    • 能写哪些表达式

    Simple expressions:

    Variable Expressions: ${...}  
    Selection Variable Expressions: *{...}
    Message Expressions: #{...}
    Link URL Expressions: @{...}
    Fragment Expressions: ~{...}
    

    Literals(字面量)

    Text literals: 'one text', 'Another one!',…
    Number literals: 0, 34, 3.0, 12.3,…
    Boolean literals: true, false
    Null literal: null
    Literal tokens: one, sometext, main,…
    

    Text operations:(文本操作)

    String concatenation: +
    Literal substitutions: |The name is ${name}|
    

    Arithmetic operations:(数学运算)

    Binary operators: +, -, *, /, %
    Minus sign (unary operator): -
    

    Boolean operations:(布尔运算)

    Binary operators: and, or
    Boolean negation (unary operator): !, not
    

    Comparisons and equality:(比较运算)

    Comparators: >, <, >=, <= (gt, lt, ge, le)
    Equality operators: ==, != (eq, ne)
    

    Conditional operators:(条件运算)(三元运算符)

    If-then: (if) ? (then)
    If-then-else: (if) ? (then) : (else)
    Default: (value) ?: (defaultvalue)
    

    Special tokens:

    No-Operation: _
    

    All these features can be combined and nested:

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

    ariable Expressions: ${...}

    1.获取对象的调用属性,调用方法
    2.使用内置的基本对象

    #ctx: the context object.
    #vars: the context variables.
    #locale: the context locale.
    #request: (only in Web Contexts) the HttpServletRequest object.
    #response: (only in Web Contexts) the HttpServletResponse object.
    #session: (only in Web Contexts) the HttpSession object.
    #servletContext: (only in Web Contexts) the ServletContext object.
    So we can do this:
    
    Established locale country: <span th:text="${#locale.country}">US</span>.
    

    3.使用内置的一些工具对象

    #execInfo: information about the template being processed.
    #messages: methods for obtaining externalized messages inside variables expressions, in the same way as they would be obtained using #{…} syntax.
    #uris: methods for escaping parts of URLs/URIs
    #conversions: methods for executing the configured conversion service (if any).
    #dates: methods for java.util.Date objects: formatting, component extraction, etc.
    #calendars: analogous to #dates, but for java.util.Calendar objects.
    #numbers: methods for formatting numeric objects.
    #strings: methods for String objects: contains, startsWith, prepending/appending, etc.
    #objects: methods for objects in general.
    #bools: methods for boolean evaluation.
    #arrays: methods for arrays.
    #lists: methods for lists.
    #sets: methods for sets.
    #maps: methods for maps.
    #aggregates: methods for creating aggregates on arrays or collections.
    #ids: methods for dealing with id attributes that might be repeated (for example, as a result of an iteration).
    

    Selection Variable Expressions: *{...}

    用法跟${...}一致,但以下一点值得注意:

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

    这种时候$跟*可以混合使用

    Message Expressions: #{...}

    获取国际化内容

    Link URL Expressions: @{...}

    定义url

    @{/order/process(execId=${execId},execType='FAST')}
    

    Fragment Expressions: ~{...}

    片段引用表达式

    <div th:insert="~{commons :: main}">...</div>
    

    二、SpringMVC自动配置原理

    官方文档:https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration

    Spring MVC Auto-configuration

    Spring Boot 自动配置好了SpringMVC

    以下是SpringBoot对SpringMVC的默认

    • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
      自动配置了ViewResolver(视图解析器:根据方法的返回值得到视图对象(View)视图对象决定如何渲染(转发?重定向?))
      ContentNegotiatingViewResolver :组合所有的视图解析器的
      如何定制:我们可以自己给容器添加一个视图解析器,让其自动组合进来
    • Support for serving static resources, including support for WebJars (covered later in this document)).
      静态资源文件夹路径,webjars
    • 自动注册了Converter, GenericConverter, and Formatter beans.
      Converter(转换器):类型转换使用,一般页面提交的都是String类型的数据,需要按需转为Boolean,Integer等类型
      Formatter (格式化器):按一定的格式转换为某一类型。如2017-07-03转为Date,2017/07/03转为Data
      定制:放在容器中即可
    • Support for HttpMessageConverters (covered later in this document).
      HttpMessageConverters:SpringMVC用来转换http请求和响应
      HttpMessageConverters是从容器中确定的,获取所有的HttpMessageConverters
      定制:将自己的组件注册到容器中(@Bean,@Component)
    • Automatic registration of MessageCodesResolver (covered later in this document).
      定义错误代码生成规则
    • Static index.html support.静态首页访问
    • Custom Favicon support (covered later in this document).
    • Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).
      我们可以配置一个ConfigurableWebBindingInitializer,来替换默认的

    If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.
    If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.

    扩展SpringMVC

    编写一个配置类(@Configuration),是WebMvcConfigurer类型,而且不能标注@EnableWebMvc
    可用下面两种方法扩展SpringMVC
    ①implements WebMvcConfigurer(官方推荐)

    ②extends WebMvcConfigurationSupport
    使用第一种方法是实现了一个接口,可以任意实现里面的方法,不会影响到Spring Boot自身的@EnableAutoConfiguration,(idea中Ctrl+O显示所有可实现方法列表)
    而使用第二种方法相当于覆盖了@EnableAutoConfiguration里的所有方法,每个方法都需要重写,比如,若不实现方法addResourceHandlers(),则会导致静态资源无法访问,实现的方法如下:

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/META-INF/resources/")
                .addResourceLocations("classpath:/resources/")
                .addResourceLocations("classpath:/static/")
                .addResourceLocations("classpath:/public/");
        super.addResourceHandlers(registry);
    }
    

    所以,第一种比较好

            @Bean
            @ConditionalOnBean({ViewResolver.class})
            @ConditionalOnMissingBean(
                name = {"viewResolver"},
                value = {ContentNegotiatingViewResolver.class}
            )
            public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
                ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
                resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));
                resolver.setOrder(-2147483648);
                return resolver;
            }
    

    原理

    • WebMvcAutoConfiguration是SpringMVC的自动配置类
    • 容器中所有的WebMvcConfigurer都会起作用
    • 我们的配置类也会被调用
      效果:SpringMVC的自动配置和我们的扩展配置都会起作用

    全面接管SpringMVC

    SpringBoot对SpringMVC的自动配置都不需要了,所有都是自己配。
    我们需要在配置类中添加@EnableWebMvc后自动配置就失效了
    原理:
    为什么写这个就失效了
    @EnableWebMvc的核心

    @Import({DelegatingWebMvcConfiguration.class})
    public @interface EnableWebMvc {
    }
    

    DelegatingWebMvcConfiguration.class

    @Configuration
    public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {...}
    

    WebMvcAutoConfiguration

    @Configuration
    @ConditionalOnWebApplication(
        type = Type.SERVLET
    )
    @ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
    //容器中没有这个组件的时候,这个自动配置类才生效
    @ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
    @AutoConfigureOrder(-2147483638)
    @AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
    public class WebMvcAutoConfiguration {....}
    

    所以,原因就是@EnableWebMvc将WebMvcConfigurationSupport组件导进来了,导入的WebMvcConfigurationSupport只是SpringMVC最基本的功能


    定制自己的解析器:

    @SpringBootApplication
    public class SpringBootDemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringBootDemoApplication.class, args);
        }
        @Bean
        public ViewResolver myViewResoler(){
            return new MyViewResoler();
        }
        public static class MyViewResoler implements ViewResolver{
    
            @Override
            public View resolveViewName(String s, Locale locale) throws Exception {
                return null;
            }
        }
    }
    测试一下
    
    image.png

    随便访问一个页面后,查看到了我们自己的视图解析器


    image.png

    org.springframework.boot.autoconfigure.web:web的所有自动场景

    如何修改SpringBoot的自动配置

    模式:

    • SpringBoot在自动配置很多组件的时候,会先看用户是否自己配置了(@Bean ,@Component)如果有就用用户配置的,如果没有就自动配置。如果有些组件可以有多个(ViewResolver),就将用户配置的和自动默认的组合起来。
    • SpringBoot中会有非常多的XXXConfigurer帮助我们进行扩展配置

    相关文章

      网友评论

          本文标题:SpringBoot学习笔记(六)SpringBoot_Web开

          本文链接:https://www.haomeiwen.com/subject/prsouqtx.html