JAVA—Spring—SpringBoot—Spring Boot学习

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
全局流量管理 GTM,标准版 1个月
简介: typora-copy-images-to: images一.spring boot简介二.spring boot hello_world三.Spring Boot 主程序分析四.Spring Boot配置

1.yaml配置文件


以数据为中心,取代了xml配置文件,标记语言



server:

port: 8080


语法:


1.字面量:(字符串,数字,布尔)


直接写即可,字符串无需加引号


userName: zhangsan

password: 1111

isSure: true


加双引号表示不转义特殊字符


加单引号转义特殊字符


2.对象(map)


server:

port: 8081


行内式写法


server: {port: 8081}


3.数组(list)


server:

- t1: a1

- t2: a2

- t3: a3


行内式写法


server: [t1: a1, t2: a2]


2.@ConfigurationProperties


加载配置文件中的属性


配置在类上,(prefix="") 类名


配置的类必须是springboot组件(添加@Component)


@ConfigurationProperties 与 @Value的区别

@ConfigurationProperties

@Value

功能

批量注入配置文件中的属性

单个注入

松散绑定(驼峰等语法)

支持

不支持

spEL(Spring的el表达式)

不支持

支持

JSR303数据校验

支持

不支持

复杂的数据类型(Map,List)

支持

不支持


业务不负责,只获取某个配置文件的属性时使用@Value


如果是bean类 注入值就使用@ConfigurationProperties


@PropertySource


加载某一个配置文件


@PropertySource(value={"classpath:***.properties"})


yml配置文件使用这种方法注入不生效


@ImportResource


修饰在主程序类上,引入spring的配置文件


@ImportResource(locations={"classpath:beans.xml"})


@Bean


@Configuration

public class Myconfig {


   @Bean

   public HelloService helloService(){

       return new HelloService();

   }

}


使用@Bean注解注入组件,代替了spring 使用配置文件注入组件的方式


配置类注入的组件,名称就是方法名


3.profile切换环境


多配置文件 可以创建多个application-{profile}.properties/yml文件


如application-dev.properties


.properties文件


spring.profiles.active=dev


激活dev命名的配置文件


.yml文件


server:

 port: 18082

spring:

 profiles:

   active: test

---

server:

 port: 8083

spring:

 profiles: test


使用---分割多文档块,每一个文档块就是一个配置环境


同样使用


spring:

 profiles:

   active: test


激活哪个环境的配置


除了 spring.profiles.active=dev 之外可以使用命令行方式制定激活哪个配置文件


命令行方式


--spring.profiles.active=dev


虚拟机参数


-Dspring.profiles.active=dev


经过测试.properties配置文件的优先级要高于.yml的优先级


4.springboot配置文件优先级


file:/config/ >>> file:/ >>> classpath:/config/ >>>classpath:/


高优先级会覆盖低优先级


配置项目的访问路径


server:

 servlet:

   context-path: /boot


配置之后访问项目的根路径就修改了


修改默认配置文件位置


spring:

 config:

  location:


外部配置文件加载顺序(优先级由高到低)


1.命令行参数


java -jar ***.jar --server.port = 8089


代替配置文件中的server.port


2.带profile的配置文件


##### jar包外部的配置文件


jar包内部的配置文件


3.不带profile的配置文件


##### jar包外部的配置文件


jar包内部的配置文件


4.@Configuration注解类上的@PropertySource引入的配置文件


具体可以看官网文档


5.自动配置的原理


  1. 加载主程序时,开启@EnableAutoConfiguration自动配置功能
  2. @EnableAutoConfiguration详细剖析:




protected static final String PATH = "META-INF/" + "spring-autoconfigure-metadata.properties";


private AutoConfigurationMetadataLoader() {

}


public static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {

return loadMetadata(classLoader, PATH);

}


static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {

try {

  Enumeration urls = (classLoader != null) ? classLoader.getResources(path)

    : ClassLoader.getSystemResources(path);

  Properties properties = new Properties();

  while (urls.hasMoreElements()) {

  properties.putAll(PropertiesLoaderUtils.loadProperties(new UrlResource(urls.nextElement())));

  }

  return loadMetadata(properties);

}

catch (IOException ex) {

  throw new IllegalArgumentException("Unable to load @ConditionalOnClass location [" + path + "]", ex);

}

}


把autoConfig包类路径下的"META-INF/spring-autoconfigure-metadata.properties"文件读取出来后转为一个properties


再看一下META-INF/spring-autoconfigure-metadata.properties的内容


![1571987704850](E:\张尧\  zy_Typora笔记\images\1571987704850.png)


都是***AutoConfiguration自动配置类,用这些类才能实现自动配置功能


以简单的HTTPEncodingAutoConfiguration类做例子


@Configuration //注解类,也可注入容器

@EnableConfigurationProperties({HttpProperties.class}) //启用@ConfigurationProperties注解

@ConditionalOnWebApplication( //判断是否是web应用 是的话当前配置类 才生效

   type = Type.SERVLET

)

@ConditionalOnClass({CharacterEncodingFilter.class}

                CharacterEncodingFilter  SpringMVC中进行乱码处理的过滤器

                  ) //判断是否存在这个类

@ConditionalOnProperty( //判断配置文件是是否存在"spring.http.encoding"这个属性

   prefix = "spring.http.encoding",

   value = {"enabled"},

   matchIfMissing = true //如果不存在,也生效

)

public class HttpEncodingAutoConfiguration {

   private final Encoding properties;


Spring底层注解 @Conditional注解 根据不同的条件判断条件是否满足,如果满足,配置类才生效


HTTPProperties.class


@ConfigurationProperties(prefix = "spring.http")//从配置文件中获取属性绑定Bean

public class HttpProperties {


/**

 * Whether logging of (potentially sensitive) request details at DEBUG and TRACE level

 * is allowed.

 */

private boolean logRequestDetails;


当自动配置类生效的时候,就会从对应的***properties中获取对应的属性,例如(HttpProperties),而HttpProperties中的属性又是通过@ConfigurationProperties(prefix="")从配置文件中获取到的


自动配置类必须满足条件才能生效


查看哪些自动配置类生效的方法:


开启Spring Boot的debug模式,启动后打印自动配置报告


debug=true


Positive matches:(启动的自动配置类)

-----------------


  CodecsAutoConfiguration matched:

     - @ConditionalOnClass found required class 'org.springframework.http.codec.CodecConfigurer' (OnClassCondition)


  CodecsAutoConfiguration.JacksonCodecConfiguration matched:

     - @ConditionalOnClass found required class 'com.fasterxml.jackson.databind.ObjectMapper' (OnClassCondition)

......

         

     

       Negative matches:(未启用的自动配置类)

-----------------


  ActiveMQAutoConfiguration:

     Did not match:

        - @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)


  AopAutoConfiguration:

     Did not match:

        - @ConditionalOnClass did not find required class 'org.aspectj.lang.annotation.Aspect' (OnClassCondition)


  ArtemisAutoConfiguration:

     Did not match:


五.springboot的日志

日志门面(日志框架的抽象层)

日志实现框架

JCL SLF4J JBOSS_LOGGING

log4j, logback,JUL, Log4j2


1.springboot 使用的是SLF4J +logback


2.SLF4J使用


统一日志到slf4j:



将其他日志框架排除


用slf4j的中间包替换,


  1. springboot底层已经引入了中间包,如果要引入其他框架的话必须排查引入框架的默认日志依赖,否则可能会引起jar包冲突

导出slf4j其他实现包


3.使用方法


  1. 日志记录器

Logger logger = LoggerFactory.getLogger(getClass());

  1. 日志级别
    日志级别(由低到高) trace

logger.trace("trace日志");

logger.debug("debug日志");

logger.info("info日志");

logger.warn("warn日志");

logger.error("error日志");

  1. springboot默认输入info级别,只会输出info级别上的日志
  2. 调整日志级别
    注意如果不加com.zy会报错

logging:

 level:

   com:

     zy: trace

  1. 指定日志文件的生成,位置
    logging.file生成日志文件的名字,可以指定全路径,如不指定,在项目目录下生成
    logging.path指定生成日志文件的路径,无法指定日志文件的名称,默认日志文件名称为spring.log

logging:

#  file: springbootlog.log

 path: /springboot/testlog

  1. 日志文件的格式
    %d表示时间{yyyy-MM-dd HH:mm:ss.SSS}
    %thread 表示线程名
    %-5level 日志的级别从左到右显示5个字符宽度
    %logger{50}表示记录器logger的名字(类的全路径)最长50个字符,否则按照据点分割
    %msg 日志消息
    %n 换行

logging:

#控制台输出日志的格式

 pattern:

   console: '%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n'

#日志文件输出日志的格式

   file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} ========== %msg%n"

  1. 指定自定义日志配置文件
    对应的日志框架只要在类路径下直接放对应的配置文件即可
    如果加了spring后缀,就可以使用高级功能--根据环节激活不同的配置文件
    例如:
    logback.xml:直接被日志框架识别
    logback-spring.xml:日志框架不直接加载日志的配置项 根据配置激活的当前环境来激活不同的springprofile
    在配置文件里这样区别,springboot就会根据是不是dev环境来加载不同的配置文件

Logging System

Customization

Logback

logback-spring.xml, logback-spring.groovy, logback.xml or logback.groovy

Log4j2

Log4j2-spring.xml or log4j2.xml

JDK(JUL)

logging.properties

日志格式

日志格式

  1. 切换日志框架
    直接切换实现jar


六.springBoot web开发


1.springboot对静态资源的映射规则


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

               }


           }

       }


  1. 访问/webjars/*,都去classpath:/META-INF/resources/webjars/找资源
  1. webjars:以jar包的方式引入静态资源 如jquery等jar

org.webjar

   jquery

   3.3.1


  1. 可以设置跟静态资源相关的属性,如缓存时间等

@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)

public class ResourceProperties {

  1. "/**" 访问此路径则会再以下路径寻找静态资源,换言之,静态资源可以存放在下面几个文件里

"classpath:/META-INF/resources/,

"classpath:/resources/",

"classpath:/static/",

"classpath:/public/,

"/" 当前项目的根路径

  1. 首页: 上述静态资源文件夹下的所有index页面 都被"/**"映射
    也就是说 访问localhost:8080/ 时会自动寻找上述文件夹下的index页面
  2. 网站图标
    所有页面访问**/favicon.ico 都会被映射到静态资源路径下

@Bean

public SimpleUrlHandlerMapping faviconHandlerMapping() {

   SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();

   mapping.setOrder(-2147483647);

   mapping.setUrlMap(Collections.singletonMap("**/favicon.ico", this.faviconRequestHandler()));

   return mapping;

}

  1. 配置自定义静态资源文件夹

spring:

 resources:

   static-locations: classpath:/hello/


2.模板引擎


Thymeleaf: springboot专用


@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";


Thymeleaf使用


1.导入命名空间


xmlns:th="http://www.thymeleaf.org"


2.快速使用


 

   欢迎

 


3.基本语法


1.th:text="${}"  改变元素的文本内容


th: 修改html元素的任意属性




2.表达式


Simple expressions:

   Variable Expressions: ${...} 获取变量值 包括对象的属性 OGNL

   Selection Variable Expressions: *{...}  与${}功能一致,配合${}使用

   Message Expressions: #{...} 获取国际化内容

   Link URL Expressions: @{...} url使用

   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: 特殊操作

Page 17 of 106No-Operation: _


3.th:replace 和 th:insert th:include 的区别


1,th:inssert:保留当前主标签,保留th:fragment主标签;


2,th:replace:舍弃当前主标签,保留th:fragment主标签;


3,th:include:保留当前主标签,舍弃th:fragment主标签


4.thymeleaf与script冲突


当java script中同样出现[[]]等thymeleaf解析符号时,thymeleaf会把js中的变量解析为thymeleaf中的属性,导致页面报错




解决办法:


</div><div id="u138bfeb1"><br /></div><h2 id="c320bf74"><span>3.springmvc的自动配置原理</span></h2><div id="u4ba006df"><br /></div><div id="u46449faa"><span>1.增加视图解析映射</span></div><div id="udc7e01b0"><br /></div><div>@Configuration</div><div>public class MyConfig extends WebMvcConfigurationSupport {</div><div><br /></div><div>    @Override</div><div>    protected void addViewControllers(ViewControllerRegistry registry) {</div><div>        registry.addViewController("index.html").setViewName("index");</div><div>        registry.addViewController("index").setViewName("index");</div><div>        registry.addViewController("/").setViewName("index");</div><div>//        super.addViewControllers(registry);</div><div>    }</div><div>}</div><div id="uaaf72f53"><br /></div><h2 id="794d4fae"><span>4.修改springboot的默认配置</span></h2><div id="u50e03b94"><br /></div><div id="u77b04d77"><span>1.大多数模块直接注入一个自己的bean即可,springboot会先检测是否由用户配置,如果容器中有用户自定义的配置,就使用用户的配置</span></div><div id="uf9253cda"><br /></div><div id="u54568676"><span>2.另外一种情况是合并,spingboot会合并多个配置,如视图解析器(viewResolver) springboot会把多个视图解析器合并每个都生效</span></div><div id="u0e0051a5"><br /></div><h2 id="0379a285"><span>5.实际开发简单demo用到的功能点</span></h2><div id="ub98a2c46"><br /></div><h3 id="d562aef5"><span>1.国际化</span></h3><div id="u460a6e66"><br /></div><ol><li><span> 在类路径下建立国际化文件如下</span></li><li><span> springboot默认配置国际化信息在类路径下的message中 源码如下 </span> <br /><span>可以在配置文件中使用spring.message来修改配置路径 </span></li></ol><div>public class MessageSourceProperties {</div><div>    private String basename = "messages";</div><div>@Bean</div><div>@ConfigurationProperties(</div><div>    prefix = "spring.messages"</div><div>)</div><div>public MessageSourceProperties messageSourceProperties() {</div><div>    return new MessageSourceProperties();</div><div>}</div><div>spring:</div><div>  messages:</div><div>    basename: i18n.test</div><ol start="3"><li><span> thymeleaf中使用#{}获取国际化信息 </span></li></ol><div><div th:text="#{name}"></div></div><div><a th:href="@{/index.html(l='zh_CN')}">中文</a></div><div><a th:href="@{/index.html(l='en_US')}">英文</a></div><ol start="4"><li><span> 修改默认的国际化解析器<br /></span><span>默认的国际化解析器是由浏览器请求头传递国家和语言信息的<br /></span><strong><span>request.getHeader("Accept-Language")</span></strong></li></ol><div> public Locale resolveLocale(HttpServletRequest request) {</div><div>     Locale defaultLocale = this.getDefaultLocale();</div><div>     if (defaultLocale != null && request.getHeader("Accept-Language") == null) {</div><div>         return defaultLocale;</div><div>     } else {</div><div>         Locale requestLocale = request.getLocale();</div><div>         List<Locale> supportedLocales = this.getSupportedLocales();</div><div>         if (!supportedLocales.isEmpty() && !supportedLocales.contains(requestLocale)) {</div><div>             Locale supportedLocale = this.findSupportedLocale(request, supportedLocales);</div><div>             if (supportedLocale != null) {</div><div>                 return supportedLocale;</div><div>             } else {</div><div>                 return defaultLocale != null ? defaultLocale : requestLocale;</div><div>             }</div><div>         } else {</div><div>             return requestLocale;</div><div>         }</div><div>     }</div><div> }</div><div id="ua0a31e01"><br /></div><div id="u2c0d55e3"><span>修改默认的国际化信息解析器为如下逻辑</span></div><div id="u4b9da5b1"><br /></div><div id="u318cf710"><span>如果我们传递的参数没有带国际化信息,就使用默认的国际化解析器(从请求头中获取国际化信息并解析),如果我们传递的参数有国际化信息,就从参数中获取国际化信息</span></div><div id="u4fb3a2a6"><br /></div><div>package com.zy.hello.component;</div><div><br /></div><div>import org.springframework.util.StringUtils;</div><div>import org.springframework.web.servlet.LocaleResolver;</div><div><br /></div><div>import javax.servlet.http.HttpServletRequest;</div><div>import javax.servlet.http.HttpServletResponse;</div><div>import java.util.Locale;</div><div><br /></div><div>/**</div><div> * @author: zhangyao</div><div> * @create:2019-10-31 11:13</div><div> **/</div><div>public class MyLocaleResovler implements LocaleResolver {</div><div><br /></div><div>    @Override</div><div>    public Locale resolveLocale(HttpServletRequest httpServletRequest) {</div><div><br /></div><div>        Locale locale = Locale.getDefault();</div><div>        String l = httpServletRequest.getParameter("l");</div><div>        if(!StringUtils.isEmpty(l)){</div><div>            //参数中以下划线分割了语言和国家</div><div>            String[] localArray = l.split("_");</div><div>            locale = new Locale(localArray[0],localArray[1]);</div><div>        }</div><div><br /></div><div>        return locale;</div><div>    }</div><div><br /></div><div>    @Override</div><div>    public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {</div><div><br /></div><div>    }</div><div>}</div><div id="u908a5cd5"><br /></div><div id="u2e726109"><span>传递路径示例:</span></div><div id="u8b43f580"><br /></div><div id="u734a277e"><a href="http://localhost:8080/index.html?l=zh_CN" target="_blank"><span>http://localhost:8080/index.html?l=zh_CN</span></a></div><div id="u12dc28ab"><br /></div><div id="u2308256e"><span>把重写的国际化解析器放入容器</span></div><div id="ucd45c99d"><br /></div><div> @Bean</div><div>    public LocaleResolver localeResolver(){</div><div>        return new MyLocaleResovler();</div><div>    }</div><div id="uc066afc0"><br /></div><h3 id="2cfe70f9"><span>2.禁用thymeleaf缓存</span></h3><div id="u94f4ef67"><br /></div><div>spring:</div><div>  thymeleaf:</div><div>    cache: false</div><div id="u40a97ba5"><br /></div><div id="u10aeec9b"><span>ctrl+F9 编译idea 项目</span></div><div id="u4ae83a45"><br /></div><div id="ufbbfaa73"><span>这两个操作 使页面修改后不必重启服务 就可以生效</span></div><div id="u6c189a22"><br /></div><h3 id="9bb0e2b6"><span>3.springBoot的错误页面剖析</span></h3><div id="u2b091fab"><br /></div><h4 id="1.DefaultErrorAttributes"><span>1.DefaultErrorAttributes</span></h4><div id="ua13bc9f9"><br /></div><div>@Bean</div><div>    @ConditionalOnMissingBean(</div><div>        value = {ErrorAttributes.class},</div><div>        search = SearchStrategy.CURRENT</div><div>    )</div><div>    public DefaultErrorAttributes errorAttributes() {</div><div>        return new DefaultErrorAttributes(this.serverProperties.getError().isIncludeException());</div><div>    }</div><div id="uf495db45"><br /></div><h4 id="29b50052"><span>2.BasicErrorController // 处理/error请求的</span></h4><div id="u0d1ab37e"><br /></div><div>@Bean</div><div>@ConditionalOnMissingBean(</div><div>    value = {ErrorController.class},</div><div>    search = SearchStrategy.CURRENT</div><div>)</div><div>public BasicErrorController basicErrorController(ErrorAttributes errorAttributes, ObjectProvider<ErrorViewResolver> errorViewResolvers) {</div><div>    return new BasicErrorController(errorAttributes, this.serverProperties.getError(), (List)errorViewResolvers.orderedStream().collect(Collectors.toList()));</div><div>}</div><div id="ub7dc0326"><br /></div><div>@Controller</div><div>@RequestMapping({"${server.error.path:${error.path:/error}}"})</div><div>public class BasicErrorController extends AbstractErrorController {</div><div>    private final ErrorProperties errorProperties;</div><div>    </div><div>    </div><div>@RequestMapping(</div><div>    produces = {"text/html"}</div><div>)//请求头如果是text/html返回html页面</div><div>    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {</div><div>        HttpStatus status = this.getStatus(request);</div><div>        Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));</div><div>        response.setStatus(status.value());</div><div>        </div><div>        //返回的错误页面  如果有视图解析就返回视图解析 如果没有 就返回默认的/error</div><div>        ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);</div><div>        return modelAndView != null ? modelAndView : new ModelAndView("error", model);</div><div>    }</div><div><br /></div><div>    @RequestMapping //如果不是text/html就返回json数据</div><div>    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {</div><div>        HttpStatus status = this.getStatus(request);</div><div>        if (status == HttpStatus.NO_CONTENT) {</div><div>            return new ResponseEntity(status);</div><div>        } else {</div><div>            Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));</div><div>            return new ResponseEntity(body, status);</div><div>        }</div><div>    }</div><div id="ud6d75b03"><br /></div><div>protected ModelAndView resolveErrorView(HttpServletRequest request, HttpServletResponse response, HttpStatus status, Map<String, Object> model) {</div><div>    //拿到所有的错误页面解析器  如果没有视图解析器就返回了null</div><div>        Iterator var5 = this.errorViewResolvers.iterator();</div><div>  </div><div>        ModelAndView modelAndView;</div><div>        do {</div><div>            if (!var5.hasNext()) {</div><div>                return null;</div><div>            }</div><div><br /></div><div>            ErrorViewResolver resolver = (ErrorViewResolver)var5.next();</div><div>            modelAndView = resolver.resolveErrorView(request, status, model);</div><div>        } while(modelAndView == null);</div><div><br /></div><div>        return modelAndView;</div><div>    }</div><div id="ub828ecdd"><br /></div><h4 id="f9ed1bbb"><span>3.ErrorPageCustomizer 当发生错误时确定应该返回什么请求 默认是/error</span></h4><div id="u53d5d8ed"><br /></div><div> @Value("${error.path:/error}")</div><div>    private String path = "/error";//返回错误请求</div><div id="u84025924"><br /></div><h4 id="6d9c8f55"><span>4.DefaultErrorViewResolver   生成默认的错误页面</span></h4><div id="udb5cd4bb"><br /></div><div>public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {</div><div>    //解析</div><div>    ModelAndView modelAndView = this.resolve(String.valueOf(status.value()), model);</div><div>    if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {</div><div>        modelAndView = this.resolve((String)SERIES_VIEWS.get(status.series()), model);</div><div>    }</div><div><br /></div><div>    return modelAndView;</div><div>}</div><div><br /></div><div>//生成错误页面的抿成</div><div>private ModelAndView resolve(String viewName, Map<String, Object> model) {</div><div>    String errorViewName = "error/" + viewName;</div><div>    //模板引擎可用就使用模板引擎  error/ 404.html这种格式</div><div>    TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext);</div><div>    </div><div>    //不可用的情况下就去静态资源文件夹下找资源</div><div>    return provider != null ? new ModelAndView(errorViewName, model) : </div><div>    this.resolveResource(errorViewName, model);</div><div>}</div><div><br /></div><div><br /></div><div>//静态资源文件夹里寻找资源</div><div>private ModelAndView resolveResource(String viewName, Map<String, Object> model) {</div><div>     //所有的静态资源文件</div><div>        String[] var3 = this.resourceProperties.getStaticLocations();</div><div>        int var4 = var3.length;</div><div><br /></div><div>        for(int var5 = 0; var5 < var4; ++var5) {</div><div>            String location = var3[var5];</div><div><br /></div><div>            try {</div><div>                Resource resource = this.applicationContext.getResource(location);</div><div>                resource = resource.createRelative(viewName + ".html");</div><div>                if (resource.exists()) {</div><div>                    return new ModelAndView(new DefaultErrorViewResolver.HtmlResourceView(resource), model);</div><div>                }</div><div>            } catch (Exception var8) {</div><div>            }</div><div>        }</div><div><br /></div><div>        return null;</div><div>    }</div><div id="u3f87d805"><br /></div><h4 id="d320ad68"><span>5.错误页面生成的步骤总结</span></h4><div id="u1c2449cc"><br /></div><div id="u91cd4c84"><span>1.当发生错误时 由 </span><strong><span>ErrorPageCustomizer</span></strong><span>  确定错误请求是什么(默认是/error,可以配置)</span></div><div id="u37421fd5"><br /></div><div id="u2b9fbbc9"><span>2.由</span><strong><span>BasicErrorController</span></strong><span>  处理错误请求</span></div><div id="ua94226e4"><br /></div><div id="ucef302cb"><span>3.</span><strong><span>DefaultErrorViewResolver</span></strong><span>   生成返回的错误页面</span></div><div id="ua86accdd"><br /></div><h4 id="c8ed424b"><span>6.如果想要自定义错误页面</span></h4><div id="ufa6adfe0"><br /></div><div id="u566a0ed2"><span>1.有模板引擎直接在templates下建立error文件夹  里面存放404.html 500.html等文件即可</span></div><div id="uf8e21f1b"><br /></div><div id="uc7286855"><span> 或者直接使用4xx这样的文件名,所有以4开头的错误都会跳转到此页面</span></div><div id="u8abe0c4f"><br /></div><h2 id="e0041cf1"><span>6.自定义拦截器</span></h2><div id="u906b6cd3"><br /></div><div>package com.zy.blog.interceptor;</div><div><br /></div><div>import com.zy.blog.entity.User;</div><div>import org.springframework.web.servlet.HandlerInterceptor;</div><div>import org.springframework.web.servlet.ModelAndView;</div><div><br /></div><div>import javax.servlet.http.HttpServletRequest;</div><div>import javax.servlet.http.HttpServletResponse;</div><div><br /></div><div>/**</div><div> * @author: zhangyao</div><div> * @create:2019-11-06 09:38</div><div> **/</div><div><br /></div><div>public class LoginInterceptor implements HandlerInterceptor {</div><div>    @Override</div><div>    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {</div><div><br /></div><div>        if(request.getRequestURL().indexOf("admin")!=-1){</div><div>            User user = (User) request.getSession().getAttribute("user");</div><div>            if(user!=null){</div><div>                //已登录</div><div>                return true;</div><div>            }else{</div><div>                request.setAttribute("message","请先登录");</div><div>                request.getRequestDispatcher("/admin/login").forward(request,response);</div><div>                return false;</div><div>            }</div><div>        }</div><div>        return false;</div><div>    }</div><div><br /></div><div>    @Override</div><div>    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {</div><div><br /></div><div>    }</div><div><br /></div><div>    @Override</div><div>    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {</div><div><br /></div><div>    }</div><div>}</div><div id="ub0dfec29"><br /></div><div id="u4431a755"><span>1.实现handlerInterceptor接口 在preHandle里判断拦截器实现的需求</span></div><div id="u7bfdd657"><br /></div><div id="ua27788a6"><span>2.将自定义的拦截器配置到MVC中</span></div><div id="u766620fc"><br /></div><div>package com.zy.blog.component;</div><div><br /></div><div>import com.zy.blog.interceptor.LoginInterceptor;</div><div>import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;</div><div>import org.springframework.context.annotation.Configuration;</div><div>import org.springframework.web.servlet.config.annotation.InterceptorRegistry;</div><div>import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;</div><div><br /></div><div>/**</div><div> * @author: zhangyao</div><div> * @create:2019-11-06 11:11</div><div> **/</div><div>@Configuration</div><div>public class WebMvcConfigAdapt implements WebMvcConfigurer {</div><div>    @Override</div><div>    public void addInterceptors(InterceptorRegistry registry) {</div><div>        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/admin/**").excludePathPatterns("**/login","/login","/admin/login");</div><div>    }</div><div>}</div><div id="u75f756b8"><br /></div><div id="uea3e1110"><span>需要注意 springboot2.x 后 WebMvcConfigurationAdapt类废弃,需要使用WebMvcConfigurer代替</span></div><div id="ua5658006"><br /></div><div id="u81997f95"><strong><span>WebMvcConfigurer: 继续使用springboot提供的 webMvc配置和功能,与自定义的mvc配置合并</span></strong></div><div id="u3f455197"><br /></div><div id="u6f4dc37c"><strong><span>WebMvcConfigurationSupport: 使用后取代了springboot的默认配置,需要自己配置mvc功能</span></strong></div><div id="ub1427ee9"><br /></div><div id="u392926b5"><strong><span>@EnableWebMvc:使用此注解则springboot提供的默认配置失效</span></strong></div><div id="uc37f9371"><br /></div><h2 id="8047ee6a"><span>7.嵌入式容器详解</span></h2><div id="u0db44f67"><br /></div><div id="uc6f09b79"><br /></div><div id="ubd6640bf"><br /></div><div id="u4132e864"><strong><span>springboot默认使用tomcat作为嵌入式容器</span></strong></div><div id="ub9153626"><br /></div><h3 id="84cf0ba5"><span>修改tomcat的配置:</span></h3><div id="u3d38bb5a"><br /></div><div id="u6452ce74"><span>1.通过配置文件修改 (serverProperties)</span></div><div id="ud5ad3304"><br /></div><div>server:</div><div>  tomcat:</div><div>    accept-count: 100</div><div id="u64e52ef7"><br /></div><div>@ConfigurationProperties(</div><div>    prefix = "server",</div><div>    ignoreUnknownFields = true</div><div>)</div><div>public class ServerProperties {</div><div>    private Integer port;</div><div>    private InetAddress address;</div><div id="u50fdfa98"><br /></div><div id="ufe640026"><span>可以修改server的通用属性如 server.port属性</span></div><div id="uc692beee"><br /></div><div id="u39e8dba2"><span>也可以修改不同容器的特殊属性 如server.tomcat.accept-count tomcat的最大连接数等</span></div><div id="ua1040c90"><br /></div><div id="u36d9ed19"><span>2.通过自定义配置类修改(WebServerFactoryCustomizer)</span></div><div id="uba8cc634"><br /></div><div>@Bean</div><div>public WebServerFactoryCustomizer webServerFactoryCustomizer(){</div><div>    return new WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>() {</div><div><br /></div><div>        @Override</div><div>        public void customize(ConfigurableServletWebServerFactory factory) {</div><div>            factory.setPort(9998);</div><div>        }</div><div>    };</div><div>}</div><div id="u0e3567fb"><br /></div><div id="u12159368"><span>配置类修改容器属性实质上也是通过webServerFactoryCustomizer 这种方式修改</span></div><div id="ue8c65cdf"><br /></div><h3 id="6f1f7eec"><span>修改springboot的默认嵌入式容器</span></h3><div id="u7a873a46"><br /></div><div id="u4702399d"><span>1.排查tomcat 依赖</span></div><div id="u0c121513"><br /></div><div id="u77e62e63"><span>2.引入其他容器依赖 如jetty netty undertow</span></div><div id="u37093690"><br /></div><div> <dependency></div><div>            <groupId>org.springframework.boot</groupId></div><div>            <artifactId>spring-boot-starter-web</artifactId></div><div>            <exclusions></div><div>                <exclusion></div><div>                    <artifactId>spring-boot-starter-tomcat</artifactId></div><div>                    <groupId>org.springframework.boot</groupId></div><div>                </exclusion></div><div>            </exclusions></div><div>        </dependency></div><div>       <!-- <dependency></div><div>            <artifactId>spring-boot-starter-jetty</artifactId></div><div>            <groupId>org.springframework.boot</groupId></div><div>        </dependency>--></div><div id="u4fb5ff5c"><br /></div><div id="u40ed9477"><span>改为jetty后启动报错,原因是缺少jar包,在idea中增加依赖 tomcat下的lib包和bin下的tomcat-juli</span></div><div id="u5c9d81db"><br /></div><h1 id="c957431a"><span>七 docker 与 spring boot</span></h1><div id="u116c01b7"><br /></div><h2 id="5aba6572"><span>1.docker简介</span></h2><div id="u4a696381"><br /></div><div id="uaa044b0f"><span>docker 是一个开源的应用容器引擎,基于go语言,尊村apache2.0协议开源</span></div><div id="uf6833939"><br /></div><div id="u586d4dff"><span>docker可以把软件,应用等打包发布,便于移植到其他环境,使用时直接启动通过docker下载的容器即可,类似与window镜像系统,但是是一个轻量级的容器应用</span></div><div id="u490043cf"><br /></div><h2 id="49b6eaa2"><span>2.docker核心概念</span></h2><div id="uf2f4d104"><br /></div><div id="ua263c9d4"><span>host:主机  安装了docker的主机</span></div><div id="u9b884d56"><br /></div><div id="u14968b70"><span>client:客户端 docker的客户端,可以通过客户端访问主机</span></div><div id="u2b357687"><br /></div><div id="u2eb929ca"><span>registry:仓库 存放docker镜像,分为公共仓库(docker hub) 和私人仓库(自己搭建)</span></div><div id="u5ffc8adf"><br /></div><div id="ue7e49d2a"><span>images:镜像 类似与window镜像一样的东西</span></div><div id="udd1f5014"><br /></div><div id="u9e09055c"><span>container:容器  运行镜像的 每一个镜像可以运行在多个容器中</span></div><div id="u00952c18"><br /></div><h2 id="f7c3f935"><span>3.安装docker</span></h2><div id="u1db494ed"><br /></div><div id="u64f39532"><span>linux为例</span></div><div id="u02824ca8"><br /></div><div id="u3029c0e3"><span>centos7</span></div><div id="u94370bfa"><br /></div><div id="u8d4d5cab"><span>docker 要求linux内核大于 3.10</span></div><div id="uc1236ded"><br /></div><div id="u03867c3d"><span>查看内核版本</span></div><div id="uaa41fec0"><br /></div><div>uname -r</div><div id="u6d6e2e1c"><br /></div><div id="u3326bde5"><span>如果内核版本过低,需要升级</span></div><div id="u881aa4ad"><br /></div><div>yum update</div><div id="u02f95407"><br /></div><div id="u0ec44540"><strong><span>安装docker</span></strong></div><div id="u3c8cff96"><br /></div><div>yum install docker</div><div id="u5473f4ba"><br /></div><div id="u8c6a61c5"><strong><span>启动docker 有两种方式</span></strong></div><div id="ue450b28f"><br /></div><ol><li><br /></li></ol><div>systemctl start docker</div><ol start="2"><li><br /></li></ol><div>service docker start</div><div id="ud2e0ef64"><br /></div><div id="uc7e81ddf"><strong><span>开启启动docker</span></strong></div><div id="ue334b9be"><br /></div><div>systemctl enable docker</div><div id="u4fdff9d8"><br /></div><div id="ue3fc57e7"><strong><span>停止docker</span></strong></div><div id="u5d3fa56e"><br /></div><div>systemctl stop docker</div><div id="uca0d17aa"><br /></div><div>service docker stop</div><div id="uc2dc9b49"><br /></div><h2 id="fa7198a5"><span>4.docker常用命令</span></h2><div id="ud40328b4"><br /></div><h3 id="ac42b307"><span>镜像常用操作</span></h3><div id="uc19aab89"><br /></div><div id="u907688d1"><span>1.搜索镜像</span></div><div id="u9caadbd3"><br /></div><div>docker search mysql(镜像关键字)</div><div id="ue96898ee"><br /></div><div id="u4395303d"><span>2.拉取镜像</span></div><div id="u5d05bdeb"><br /></div><div>docker pull mysql(镜像名)</div><div id="u05f59bb9"><br /></div><div id="u2cfd2247"><span>3.查询本地镜像</span></div><div id="u94cf8611"><br /></div><div>docker images</div><div id="ucf80a2a4"><br /></div><div id="u790b902a"><span>4.删除镜像</span></div><div id="ue8ed0cba"><br /></div><div>docker rmi mysql(镜像名)</div><div id="ub2bd2cbf"><br /></div><h3 id="1a37581d"><span>容器常用操作</span></h3><div id="u4c2578b9"><br /></div><div id="u95993b91"><strong><span>1.根据镜像启动容器</span></strong></div><div id="u7cb35dae"><br /></div><div>docker run -d --name mysql01 mysql01 -p 3306:3306</div><div id="uf4ebc4c8"><br /></div><div id="u2cd4d8cd"><span>-d:后台运行</span></div><div id="u25756267"><br /></div><div id="ub8a2c915"><span>--name:容器名</span></div><div id="u898aecc9"><br /></div><div id="ucd1fe63c"><span>-p:端口映射 第一个端口号是主机端口 第二个端口是docker端口</span></div><div id="u06fdab42"><br /></div><div id="u86e84c29"><strong><span>2.查看所有的运行中容器</span></strong></div><div id="ua15dfce1"><br /></div><div>docker ps -a</div><div id="u98144a65"><br /></div><div id="u99194a9e"><span>-a 所有的容器</span></div><div id="ufe6fe724"><br /></div><div id="u5ac6689c"><span>不加-a只查询运行中的容器</span></div><div id="u98449c56"><br /></div><div id="u853e95c1"><strong><span>3.停止容器</span></strong></div><div id="ue12548d9"><br /></div><div>docker stop mysql</div><div id="uafe35992"><br /></div><div id="u061b0da3"><strong><span>4.删除容器</span></strong></div><div id="ue6af95f6"><br /></div><div>docker rm mysql(容器名)</div><div id="uc0eb064a"><br /></div><div id="u298ba557"><span>5.查看防火墙</span></div><div id="uaf7b6d21"><br /></div><div>service firewalld status</div><div>service firewalld stop 关闭防火墙</div><div id="u8dcd9fe7"><br /></div><div id="u949a97e8"><span>6.查看容器日志</span></div><div id="ue79b4372"><br /></div><div>docker logs mysql(容器名)</div><div id="uc0a523fb"><br /></div><h1 id="410b114d"><span>八 springboot中的数据交互(mybatis jpa spring data)</span></h1><div id="u5c3f4ee6"><br /></div><div id="uc85d2f54"><span>缺</span></div><div id="u78fc7ec3"><br /></div><h1 id="a836c621"><span>九 cache</span></h1>

目录
相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
71 2
|
19天前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
38 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
7天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
52 13
|
14天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
1月前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
1月前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
63 9
|
1月前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
1月前
|
监控 前端开发 Java
Java SpringBoot –性能分析与调优
Java SpringBoot –性能分析与调优
|
1月前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
28天前
|
Java Kotlin 索引
学习Spring框架特性及jiar包下载
Spring 5作为最新版本,更新了JDK基线至8,修订了核心框架,增强了反射和接口功能,支持响应式编程及Kotlin语言,引入了函数式Web框架,并提升了测试功能。Spring框架可在其官网下载,包括文档、jar包和XML Schema文档,适用于Java SE和Java EE项目。
31 0
下一篇
DataWorks