需求 员工列表 |普通CRUD|restfulCRUD
架构 |请求URL|请求方式
修改|updateEmp?|emp/{id}…PUT
1 2 3 4 5 6 7 <footer  th:fragment ="copy" > hello </footer > <div  th:insert ="footer :: copy" > </div > <div  th:replace ="footer :: copy" > </div > <div  th:include ="footer :: copy" > </div > 
insert 是将整个元素插入到引用中
1 <div  th:fragment ="topbar" >  这里测试 include replace 和insert</div > 
1 2 3 <div  id ="include"  th:include ="~{templates_hello::topbar}" > hi</div > <div  id ="replace"  th:replace ="templates_hello::topbar" > hi</div > <div  id ="insert"  th:insert ="templates_hello::topbar" > hai</div > 
1 2 3 <div  id ="include" >  这里测试 include replace 和insert</div > <div >  这里测试 include replace 和insert</div > <div  id ="insert" > <div >  这里测试 include replace 和insert</div > </div > 
挺前端的
错误响应 如何定制错误页面?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @Bean @ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT) public  DefaultErrorAttributes errorAttributes ()  {    return  new  DefaultErrorAttributes (this .serverProperties.getError().isIncludeException()); } @Bean @ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT) public  BasicErrorController basicErrorController (ErrorAttributes errorAttributes,         ObjectProvider<ErrorViewResolver> errorViewResolvers)  {    return  new  BasicErrorController (errorAttributes, this .serverProperties.getError(),             errorViewResolvers.orderedStream().collect(Collectors.toList())); } @Bean public  ErrorPageCustomizer errorPageCustomizer (DispatcherServletPath dispatcherServletPath)  {    return  new  ErrorPageCustomizer (this .serverProperties, dispatcherServletPath); }   @Bean      @ConditionalOnBean(DispatcherServlet.class)      @ConditionalOnMissingBean(ErrorViewResolver.class)      DefaultErrorViewResolver conventionErrorViewResolver ()  {         return  new  DefaultErrorViewResolver (this .applicationContext, this .resourceProperties);     } 
系统出现错误以后去/error处理请求
这老师是源码杀手,我要炸了,我现在开始怕源码了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @RequestMapping(produces = MediaType.TEXT_HTML_VALUE) public  ModelAndView errorHtml (HttpServletRequest request, HttpServletResponse response)  {    HttpStatus  status  =  getStatus(request);     Map<String, Object> model = Collections             .unmodifiableMap(getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));     response.setStatus(status.value());     ModelAndView  modelAndView  =  resolveErrorView(request, response, status, model);     return  (modelAndView != null ) ? modelAndView : new  ModelAndView ("error" , model); } @RequestMapping 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, isIncludeStackTrace(request, MediaType.ALL));     return  new  ResponseEntity <>(body, status); } 
所以到底如何定制? 有模版引擎的话,就在error下写一个404.html就可以了,你甚至可以用4xx.html来批评所有的4开头的错误
1 <h1 > status:[[${status}]]</h1 > 
没有模版引擎就在静态资源文件夹找
嵌入式servlet容器 默认是tomcat
如何定制修改servlet容器 
方法11 2 @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) public  class  ServerProperties  {
 
方法21 2 3 4 5 6 7 8 9 10 @Bean public  WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryWebServerFactoryCustomizer () {    return  new  WebServerFactoryCustomizer <ConfigurableWebServerFactory>(){         @Override          public  void  customize (ConfigurableWebServerFactory factory)  {             factory.setPort(8083 );         }     }; } 
 
注册Servlet、Filter、Listener 
切换Servlet容器 
 
排除tomcat依赖 
引入其他依赖 
 
嵌入式的tomcat如何实现 源码警告 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication @EnableConfigurationProperties(ServerProperties.class) public  class  EmbeddedWebServerFactoryCustomizerAutoConfiguration  {         @Configuration(proxyBeanMethods = false)      @ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })      public  static  class  TomcatWebServerFactoryCustomizerConfiguration  {         @Bean          public  TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer (Environment environment,                  ServerProperties serverProperties)  {            return  new  TomcatWebServerFactoryCustomizer (environment, serverProperties);         }     } 
源码变了。。。
以前是放一个嵌入式的容器工厂,然后配置tomcat,最后传给TomcatEmbeddedServletContainer,并且启动tomcat容器
配置修改是如何生效的 配置文件+定制器, 他们本质上都是定制器
SpringBoot根据导入的依赖情况,给容器添加相应的容器工厂, 容器中某个组件要创建对象就会惊动后置处理器, 只要是嵌入式的servlet容器工厂,后置处理器就会工作, 后置处理器会从容器中获取所有的定制器,调用定制器的方法。 
嵌入式servlet什么时候创建 springboot启动, 运行run, 创建IOC容器, 并初始化, 创建容器中的每个bean, 如果是web应用就创建web容器,否则创建AnnotationConfigApplicationContext, 在web的IOC容器中, 重写了onRefresh, 在这里创建了嵌入式的Servlet, 获取容器工厂, tomcatembeddedservletcontainerfactory创建对象以后,后置处理器就开始配置,然后获得新的servlet容器,最后启动
优点 简单便携
缺点 不支持jsp