11

微服务架构Day03-SpringBoot之web开发配置

 3 years ago
source link: http://www.cnblogs.com/chova/p/14400157.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

概述

  • SpringBoot开发:
    1.创建SpringBoot应用,选中需要的场景模块。
    2.SpringBoot已经默认将场景模块配置好,只需要在配置文件中指定少量的配置(数据库地址,用户名,密码)就可以运行起来。
    3.只需要编写业务逻辑代码。
  • 需要掌握 自动配置原理 :这个场景中SpringBoot默认配置好了什么,能不能修改,能修改哪些配置,能不能扩展。
XxxAutoConfiguration:帮我们给容器中自动配置组件
XxxProperties:配置类,封装配置文件中的内容

SpringBoot对静态资源(static-location)的映射规则

@ConfigurationProperties(
    prefix = "spring.resources",
    ignoreUnknownFields = false
)
  • ResourceProperties可以设置和资源有关的参数,缓存时间等。
/* 
  * ResourceHandlerRegistry存储用于通过Spring MVC服务静态资源的资源处理程序的注册
  * 允许设置为在Web浏览器中高效加载而优化的缓存头
  * 可以在Web应用的目录下,类路径等位置之外的位置提供资源
  */
 public void addResourceHandlers(ResourceHandlerRegistry registry) { 
            if (!this.resourceProperties.isAddMappings()) {
                logger.debug("Default resource handling disabled");
            } else {
                Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
                CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
                if (!registry.hasMappingForPattern("/webjars/**")) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

                String staticPathPattern = this.mvcProperties.getStaticPathPattern();
                if (!registry.hasMappingForPattern(staticPathPattern)) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

            }
        }
  • 所有/web.jars/**中的资源都在classpath:/META-INF/resources/webjars/中寻找。
  • web.jars:以jar包的方式引入静态资源: https://www.webjars.org/
  • 访问时,只需要写web.jars下面资源的名称。

/**:访问当前项目的任何资源(静态资源的文件夹)

classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
/	# 当前项目的根路径
@Bean
        public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext) {
            return new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
        }

配置欢迎页的映射:

  • 欢迎页:静态资源文件夹下的所有index.xml页面,被 /** 映射。
@Configuration
        @ConditionalOnProperty(
            value = {"spring.mvc.favicon.enabled"},
            matchIfMissing = true
        )

		/* 
		 * ResourceLoaderAware是一个标记接口
		 * 用于通过ApplicationContext上下文注入ResourceLoader
		 * 有setResourceLoader()方法
		 */
        public static class FaviconConfiguration implements ResourceLoaderAware {
            private final ResourceProperties resourceProperties;
            /* 
             * ResourceLoader用于返回Resource对象和ClassLoader对象
             * 		- getResource(String location)方法根据提供的location参数返回相应的Resource对象
             * 		- getClassLoader()方法则返回加载这些Resource的ClassLoader
             */
            private ResourceLoader resourceLoader;

            public FaviconConfiguration(ResourceProperties resourceProperties) {
                this.resourceProperties = resourceProperties;
            }

            public void setResourceLoader(ResourceLoader resourceLoader) {
                this.resourceLoader = resourceLoader;
            }

			/* 
			 * SimpleUrlHandlerMapping是SpringMVC中适应性最强的Handler Mapping类
			 * 允许明确指定URL模式和Handler的映射关系.有两种声明方式:
			 * 		- prop:
			 * 		  - key: URL模式
			 * 		  — value: Handler的ID或者名字
			 * 		- value:
			 * 		  - 等号左边是URL模式
			 * 		  - 等号右边是HandlerID或者名字  
			 */
            @Bean
            public SimpleUrlHandlerMapping faviconHandlerMapping() {
                SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
                mapping.setOrder(-2147483647);
                mapping.setUrlMap(Collections.singletonMap("**/favicon.ico", this.faviconRequestHandler()));
                return mapping;
            }

配置喜欢的图标(标签的图标):

  • 标签图标:所有的 **/favicon.ico 都是在静态文件夹资源下。

模板引擎

  • jsp,velocity,freemarker,thymeleaf
优点 缺点 jsp 1. 功能强大,可以写 Java 代码
2. 支持 jsp 标签 - jsp tag
3. 支持表达式语言 - EL 表达式
4. 官方标准,使用广泛,丰富的第三方 jsp 标签库
5. 性能良好 ,jsp 编译成 class 文件执行,有很好的性能表现 1. jsp没有明显的缺点
2. 由于可以编写Java代码,使用不当容易破坏MVC结构 velocity 1. 不编写 Java 代码,实现严格的 MVC 分离
2. 性能良好,比 jsp 优越
3. 使用表达式语言 - EL 表达式 1. 不是官方标准
2. 使用范围小,第三方标签库较少
3. 对 jsp 标签的支持不够友好 freemarker 1. 不编写 Java 代码,实现严格的 MVC 分离
2. 性能非常好
3. 对 jsp 标签支持良好
4. 内置大量常用功能,使用非常方便
5. 宏定义(类似 jsp 标签)非常方便
6. 使用表达式语言 - EL 表达式 1.不是官方标准
2. 使用范围小,第三方标签库较少 thymeleaf 1. 静态 html 嵌入标签属性,浏览器可以直接打开模板文件,便于后端联调
2. SpringBoot 框架推荐模板 1.模板必须符合 xml 规范
2. 需要加入 js 脚本
  • freemarker:
    • freemarker 是一个用 Java 语言编写的模板引擎,基于模板生成文本来输出
    • freemarkerWeb 容器无关,也就是说,在 Web 运行时,并不知道是 Servlet 还是 HTTP
    • 不仅可以用作表现层的实现技术,而且还可以用于生成 XML,JSP,Java
    • 目前企业中主要使用 freemarker 做静态页面或页面展示
    • 选择freemarker的原因:
      • 性能: 就性能而言 ,velocity 是最好的,其次是 jsp, 普通的页面 freemarker 性能最差.但是在复杂页面,比如包含大量判断,日期金额格式化的页面上 ,freemarker 的性能比使用 tageljsp
      • 宏定义比 jsp tag 方便
      • 内置大量常用功能. 比如html过滤,日期金额格式化等等,使用方便
      • 支持 jsp 标签
      • 可以实现严格等 mvc 分离
  • freemarker与velocity比较:
    • velocity:
      • velocity优于freemarker在于有广泛的第三方支持以及庞大的用户社区
      • velocity的性能是最好的
    • freemarker:
      • freemarker比velocity简单,因为velocity必须编写一些自定义的toolbox以及一遍一遍重复的编写一些比较通用的模版代码
      • velocity的做法使得在velocity的模版中大量的与Java对象交互,违背了简单的原则,尽管也可以将代码转入控制器中实现
      • freemarker能做到,而velocity无法做到的:
        • 日期和数字的支持:
          • 比较和格式化显示日期或者时间值
          • 执行运算和比较,对任意数量的类型,包括精度类型,而不仅仅是整数
        • 国际化:
          • 格式数字区域,各种各样的内置和自定义数字格式模式
          • 格式日期地区和时区,各种各样的内置和定制的日期格式模式
          • 标识符,即变量名可以包含非英语字母一样的重音字母,阿拉伯字母,汉字等
        • 循环处理:
          • 退出循环
          • 访问控制变量外循环机构的内部循环
          • 得知当前是否到了循环的结束位置
        • 模版级别的数组处理:
          • 使用 [i] 的语法来访问数组元素,包括原始的和非原始的指数
          • 获取数组的长度
        • 宏定义:
          • 宏调用可以通过位置或名称进行参数传递
          • 宏的参数可以设定默认值,在调用宏时如果没有指定该参数,则使用默认值代替
          • 通过 < @myMacro >body< / @myMacro > 可以支持宏的嵌套
          • 通过文本表达的 “宏的名称” 来直接调用某个宏
          • 宏允许先使用再定义
          • 宏可以定义局部变量
        • 命名空间:
          • 使用多个名称空间的变数. 这个在建立 “宏库”
        • 内置与Java语言无关的字符串,列表,Map的操作方法
        • 能提示模版中的拼写错误以及其他错误
          • 当访问一个不存在的变量时,freemarker在执行模版时会报错
          • 通过配置,可以指定freemarker在发生此类错误时停止执行,还是忽略该错误,同时freemarker会在日志中记录此问题
          • 输入错误的指令名称,freemarker将抛出一个异常
        • 更高级的文本输出工具:
          • 将模版块封装在一组标记中,这样可以应用HTML转义或者XML转义(或者freemarker表达式的其他转换)到 ${foo} 块中
          • freemarker具有模版块的转换器,会在渲染时经过转换过滤器.内置的转换器包括空格压缩器,HTML和XML溢出器. 也可以实现自定义的转换器,即如果生成Java源代码,则可以编写Java代码pretty-printer转换并插入到模版中.同时转换也可以嵌套
          • 使用内置的 flush-directive 显式刷新输出写入器
          • 使用内置的 stop-directive 停止渲染
        • 文本处理:
          • 支持Java的特殊字符处理,比如 \b, \t, \n, \f, \r, \ ", \ ', \ , 以及unicode的 \xXXXX
          • 除了通常的字符串,数字,布尔常量,也可以自定义列表和地图文字以及内部模版
        • 高级的空格删除:
          • freemarker将删除一些多余的空格,跳格,换行等字符
          • 提供相关指令来删除多余的空格
        • 与其他技术集成:
          • 提供 JSP 标签库以便在 JSP 中嵌入 freemarker 模版
          • 直接和Python对象一起使用
        • 更强大的XML转换功能
        • 模版元程序:
          • 捕捉到输出任意部分范本背景变量
          • 任意解释的范围变量,类似一个模版定义

thymeleaf

thymeleaf基本概念

  • thymeleaf 是一个 XML,XHTML,HTML5 模板引擎,可用于 Web 与非 Web 应用
  • thymeleaf主要目标: 提供一个可被浏览器正确显示的,格式良好的模板创建方式,可以用于静态建模
  • 可以使用thymeleaf创建经过验证的XML与HTML模板:
    • 相对于编写逻辑代码,开发者只需将标签属性添加到模板中即可
    • 这些标签就会在文档对象模型 DOM 上执行预先制定好的逻辑
  • thymeleaf具有良好的扩展性:
    • 可以使用 thymeleaf 自定义模板属性集合,用来计算自定义表达式并使用自定义逻辑
    • 这样 thymeleaf 可以作为模板引擎框架

引入thymeleaf依赖

  • 引入SpringBoot中的thymeleaf依赖:
<properties>	
			<!-- 切换thymeleaf版本 -->
			<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
			<!-- 布局功能支持程序-thymeleaf3==layout2  thymeleaf2==layout1 -->
			<thymeleaf-layout-dialect.version>2.1.1</thymeleaf-layout-dialect.version>	
		</properties>
		<dependency>	
			<!-- 引入thymeleaf依赖 -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

thymeleaf使用和语法

@ConfigurationProperties(
    prefix = "spring.thymeleaf"
)
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";
    private Charset encoding;
  • 将html页面放在classpath:/templates/中,thymeleaf就能自动渲染了。
  • Thymeleaf的使用
    1.导入thymeleaf的名称空间
<html xmlns:th="http://www.thymeleaf.org">

2.使用thymeleaf语法:

  • th:text - 改变当前元素里面的文本内容
  • th:任意html属性 - 改变原生属性的值
thymeleaf jsp 片段包含 th:insert
th:replace include 遍历 th:each c:forEach 条件判断 th:if
th:unless
th:switch
th:case c:if 声明变量 th:object
th:with c:set 任意属性修改 th:attr
th:attrprepend(前面)
th:attrappend(后面) 修改指定属性默认值 th:value
th:href
th:src 修改标签体文本内容 th:text(转义)
th:utext(不转义) 声明片段 th:fragment 移除声明片段 th:remove
  • 表达式
Simple expressions:						(表达式语法)
Variable Expressions: ${...}			(获取变量值-OGNL)
					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.
					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: *{...}		(选择表达式,和${}在用法上大体一致)
								补充:配合th:object="${session.user}"
								<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>
Which is exactly equivalent to:
								<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)
<a href="details.html"
th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">view</a>
<!-- Will produce '/gtvg/order/details?orderId=3' (plus rewriting) -->
<a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>
<!-- Will produce '/gtvg/order/3/details' (plus rewriting) -->
<a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a>
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: _

SpringBoot对SpringMVC的web主要的自动配置

  • SpringBoot默认自动配置了SpringMVC
  • 自动配置了 ViewResolver-ContentNegotiatingViewResolver,BeanNameViewResolver (视图解析器:根据方法的返回值得到视图对象,视图对象决定转发、重定向)
    1. ContentNegotiatingViewResolver: 组合所有的视图解析器
    1.1:如何定制配置-在容器中添加一个定制的视图解析器,ContentNegotiatingViewResolver会自动将定制的视图解析器组合进来
  • 静态资源文件夹路径和 web.jars
  • 静态首页访问
  • favicon.ico
  • 自动注册Converter,GenericConverter,Formatter
    1. Converter :转换器,类型转换使用
    2. GenericConverter :通用转换器,多个源类型和目标类型之间进行转换。
    3. Formatter :格式化器-可以自己定制格式化转换器放在容器中即可以配置
  • HttpMessageConverter: SpringMVC用来转换Http请求和响应的。从容器中确定HttpMessageConverters值。可以自己将定制配置的HttpMessageConverter放在容器中即可配置。
  • MessageCodeResolver: 定义错误代码生成规则
  • ConfigurableWebBindingInitializer: 初始化web数据绑定器,绑定器把请求数据绑定.可以配置ConfigurableWebBindingInitializer添加到容器中替换默认的

如何修改SpringBoot的默认配置

  • SpringBoot 在自动配置很多组件时,先看容器中有没有已经配置 (@Bean,@Component) 好的组件,如果有,就用已经配置好的,如果没有,才自动配置;如果组件可以有多个,将已经配置的和默认配置的组合起来。

扩展MVC(不能标注@EnableWebMvc)

  • 编写一个配置类(@Configuration),继承WebMvcConfigurationSupport,不能标注@EnableWebMvc。既保留了所有的自动配置,也可以使用扩展的配置。在做配置时,会导入
@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})

EnableWebMvcConfiguration:

@Configuration
    public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {

DelegatingWebMvcConfiguration:

//
  @Autowired(
        required = false
    )
    public void setConfigurers(List<WebMvcConfigurer> configurers) {
        if (!CollectionUtils.isEmpty(configurers)) {
            this.configurers.addWebMvcConfigurers(configurers);
        }

    }

参考实现:

//将所有的WebMvcConfigurer相关的配置都调用一遍
 public void addViewControllers(ViewControllerRegistry registry) {
        Iterator var2 = this.delegates.iterator();

        while(var2.hasNext()) {
            WebMvcConfigurer delegate = (WebMvcConfigurer)var2.next();
            delegate.addViewControllers(registry);
        }

    }
  • 容器中所有的WebMvcConfigurer 都会起作用。配置的配置类也会被调用。这样Spring的自动配置和扩展配置都会起作用。

全面接管SpringMVC(@EnableWebMvc)—不推荐使用

  • 禁用SpringBoot对SpringMVC的自动配置,全面对SpringMVC进行配置。在配置类中标注@EnableWebMvc。所有的SpringMVC的默认配置都被禁用了。
  • @EnableWebMvc
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}

DelegatingWebMvcConfiguration:

@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})
  • @EnableWebMvc将WebMvcAutoConfigurationSupport导入进来,不包括SpringMVC的功能。
    总结:
  • 多多学习SpringBoot中的XxxConfigurer,进行扩展配置

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK