当前位置: 首页 > news >正文

百度搜索结果优化seo全称

百度搜索结果优化,seo全称,做网站老板嫌弃太丑谁的锅,怎么评判一个网站做的好与坏文章目录 45、web实验-抽取公共页面46、web实验-遍历数据与页面bug修改47、视图解析-【源码分析】-视图解析器与视图[暂时没看]48、拦截器-登录检查与静态资源放行49、拦截器-【源码分析】-拦截器的执行时机和原理50、文件上传-单文件与多文件上传的使用51、文件上传-【源码流程…

文章目录

    • 45、web实验-抽取公共页面
    • 46、web实验-遍历数据与页面bug修改
    • 47、视图解析-【源码分析】-视图解析器与视图[暂时没看]
    • 48、拦截器-登录检查与静态资源放行
    • 49、拦截器-【源码分析】-拦截器的执行时机和原理
    • 50、文件上传-单文件与多文件上传的使用
    • 51、文件上传-【源码流程】文件上传参数解析器
    • 52、错误处理-SpringBoot默认错误处理机制
    • 53、错误处理-【源码分析】底层组件功能分析【看了但是自己没有理解】
    • 54、错误处理-【源码流程】异常处理流程【没看,打算看文档的时候再一起看,现在看不懂】
    • 55、错误处理-【源码流程】几种异常处理原理【没看,打算看文档的时候再一起看,现在看不懂】
    • 56、原生组件注入-原生注解与Spring方式注入
      • 使用原生的注解
      • Spring方式注入
    • 57、原生组件注入-【源码分析】DispatcherServlet注入原理
    • 58、嵌入式Servlet容器-【源码分析】切换web服务器与定制化【没看】
      • 定制Servlet容器
    • 59、定制化原理-SpringBoot定制化组件的几种方式(小结)
      • 定制化的常见方式
      • 原理分析套路
    • 60、数据访问-数据库场景的自动配置分析与整合测试
      • 导入JDBC场景
      • 相关数据源配置类
      • 修改配置项
      • 单元测试数据源
    • 61、数据访问-自定义方式整合druid数据源
      • Druid是什么?
      • 自定义方式
    • 62、数据访问-druid数据源starter整合方式
    • 63、数据访问-整合MyBatis-配置版
      • 小结
    • 64、数据访问-整合MyBatis-注解配置混合版
    • 65、数据访问-整合MyBatisPlus操作数据库
      • MyBatisPlus是什么
    • 66、数据访问-CRUD实验-数据列表展示
    • 67、数据访问-CRUD实验-分页数据展示
    • 68、数据访问-CRUD实验-删除用户完成
    • 69、数据访问-准备阿里云Redis环境
    • 70、数据访问-Redis操作与统计小实验
    • 71、单元测试-JUnit5简介
    • 72、单元测试-常用测试注解
    • 73、单元测试-断言机制
      • 简单断言
      • 数组断言
      • 组合断言
      • 异常断言
      • 超时断言
      • 快速失败
    • 74、单元测试-前置条件
    • 75、单元测试-嵌套测试
    • 76、单元测试-参数化测试
      • 迁移指南
    • 77、指标监控-SpringBoot Actuator与Endpoint
      • 如何使用
    • 78、指标监控-常使用的端点及开启与禁用
      • 常使用的端点
      • Health Endpoint
      • Metrics Endpoint
      • 开启与禁用Endpoints
      • 暴露Endpoints
    • 79、指标监控-定制Endpoint
      • 定制 Health 信息
      • 定制info信息
      • 定制Metrics信息
      • 定制Endpoint
    • 80、指标监控-Boot Admin Server
    • 81、高级特性-Profile环境切换
      • @Profile条件装配功能
    • 82、高级特性-配置加载优先级
      • 外部化配置
    • 83、高级特性-自定义starter细节
      • starter启动原理
      • 自定义starter
    • 84、原理解析-SpringApplication创建初始化流程
      • SpringBoot启动过程
    • 85、原理解析-SpringBoot完整启动过程
    • 86、原理解析-自定义事件监听组件
    • 87、后会有期

45、web实验-抽取公共页面

官方文档 - Template Layout
中文文档
复习Template 语法,把链接放上来

  • 公共页面/templates/common.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><!--注意要添加xmlns:th才能添加thymeleaf的标签-->
<head th:fragment="commonheader"><!--common-->...
</head>
<body>
<!-- left side start-->
<div id="leftmenu" class="left-side sticky-left-side">...<div class="left-side-inner">...<!--sidebar nav start--><ul class="nav nav-pills nav-stacked custom-nav"><li><a th:href="@{/main.html}"><i class="fa fa-home"></i> <span>Dashboard</span></a></li>...<li class="menu-list nav-active"><a href="#"><i class="fa fa-th-list"></i> <span>Data Tables</span></a><ul class="sub-menu-list"><li><a th:href="@{/basic_table}"> Basic Table</a></li><li><a th:href="@{/dynamic_table}"> Advanced Table</a></li><li><a th:href="@{/responsive_table}"> Responsive Table</a></li><li><a th:href="@{/editable_table}"> Edit Table</a></li></ul></li>...</ul><!--sidebar nav end--></div>
</div>
<!-- left side end--><!-- header section start-->
<div th:fragment="headermenu" class="header-section"><!--toggle button start--><a class="toggle-btn"><i class="fa fa-bars"></i></a><!--toggle button end-->...</div>
<!-- header section end--><div id="commonscript"><!-- Placed js at the end of the document so the pages load faster --><script th:src="@{/js/jquery-1.10.2.min.js}"></script><script th:src="@{/js/jquery-ui-1.9.2.custom.min.js}"></script><script th:src="@{/js/jquery-migrate-1.2.1.min.js}"></script><script th:src="@{/js/bootstrap.min.js}"></script><script th:src="@{/js/modernizr.min.js}"></script><script th:src="@{/js/jquery.nicescroll.js}"></script><!--common scripts for all pages--><script th:src="@{/js/scripts.js}"></script>
</div>
</body>
</html>
  • /templates/table/basic_table.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"><meta name="description" content=""><meta name="author" content="ThemeBucket"><link rel="shortcut icon" href="#" type="image/png"><title>Basic Table</title><div th:include="common :: commonheader"> </div><!--将common.html的代码段 插进来-->
</head><body class="sticky-header"><section>
<div th:replace="common :: #leftmenu"></div><!-- main content start--><div class="main-content" ><div th:replace="common :: headermenu"></div>...</div><!-- main content end-->
</section><!-- Placed js at the end of the document so the pages load faster -->
<div th:replace="common :: #commonscript"></div></body>
</html>

Difference between th:insert and th:replace (and th:include)

46、web实验-遍历数据与页面bug修改

控制层代码:

@GetMapping("/dynamic_table")
public String dynamic_table(Model model){//表格内容的遍历List<User> users = Arrays.asList(new User("zhangsan", "123456"),new User("lisi", "123444"),new User("haha", "aaaaa"),new User("hehe ", "aaddd"));model.addAttribute("users",users);return "table/dynamic_table";
}

页面代码:

<table class="display table table-bordered" id="hidden-table-info"><thead><tr><th>#</th><th>用户名</th><th>密码</th></tr></thead><tbody><tr class="gradeX" th:each="user,stats:${users}"><td th:text="${stats.count}">Trident</td><td th:text="${user.userName}">Internet</td><td >[[${user.password}]]</td></tr></tbody>
</table>

47、视图解析-【源码分析】-视图解析器与视图[暂时没看]

ctrl+b进入代码

视图解析原理流程

  1. 目标方法处理的过程中(阅读DispatcherServlet源码),所有数据都会被放在 ModelAndViewContainer 里面,其中包括数据和视图地址。
  2. 方法的参数是一个自定义类型对象(从请求参数中确定的),把他重新放在 ModelAndViewContainer
  3. 任何目标方法执行完成以后都会返回ModelAndView(数据和视图地址)。
  4. processDispatchResult()处理派发结果(页面改如何响应)
    • render(mv, request, response); 进行页面渲染逻辑
      • 根据方法的String返回值得到 View 对象【定义了页面的渲染逻辑】
      1. 所有的视图解析器尝试是否能根据当前返回值得到View对象
      2. 得到了 redirect:/main.html --> Thymeleaf new RedirectView()
      3. ContentNegotiationViewResolver 里面包含了下面所有的视图解析器,内部还是利用下面所有视图解析器得到视图对象。
      4. view.render(mv.getModelInternal(), request, response); 视图对象调用自定义的render进行页面渲染工作。
      • RedirectView 如何渲染【重定向到一个页面】
      • 获取目标url地址
      • response.sendRedirect(encodedURL);

视图解析
- 返回值以 forward: 开始: new InternalResourceView(forwardUrl); --> 转发request.getRequestDispatcher(path).forward(request, response);
- 返回值以 redirect: 开始: new RedirectView() --> render就是重定向
- 返回值是普通字符串:new ThymeleafView()—>


阅读源码:最好自己在IDE,打断点,且Debug模式运行实例,这样比较没那么沉闷。

48、拦截器-登录检查与静态资源放行

需要复习一些request,response,session等知识点,把复习链接放在这里

  1. 编写一个拦截器实现HandlerInterceptor接口

  2. 拦截器注册到容器中(实现WebMvcConfigureraddInterceptors()

  3. 指定拦截规则(注意,如果是拦截所有,静态资源也会被拦截】

编写一个实现HandlerInterceptor接口的拦截器:

package edu.gdpu.config;import edu.gdpu.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class AdminWebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()) //拦截器注册到容器中.addPathPatterns("/**") //所有请求都被拦截包括静态资源.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**");
//        ?静态资源这里还可以这样子写的,在/static/**全部发现,需要在application.yml配置
//        # 静态资源访问前缀//#spring://#  mvc://#    static-path-pattern: /res/**   麻烦的是css,js等静态资源都要加上/static才会被访问到}
}

拦截器注册到容器中 && 指定拦截规则:

@Configuration
public class AdminWebConfig implements WebMvcConfigurer{@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor())//拦截器注册到容器中.addPathPatterns("/**")  //所有请求都被拦截包括静态资源.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); //放行的请求
}

49、拦截器-【源码分析】-拦截器的执行时机和原理

看了老师那么多源码解析,我都是懵懵懂懂的,就是没听,这次认真学习IDEA的debug调试,附上链接

  1. 根据当前请求,找到HandlerExecutionChain(可以处理请求的handler以及handler的所有 拦截器)
  2. 先来顺序执行 所有拦截器的 preHandle()方法。
    • 如果当前拦截器preHandle()返回为true。则执行下一个拦截器的preHandle()
    • 如果当前拦截器返回为false。直接倒序执行所有已经执行了的拦截器的 afterCompletion();
  3. 如果任何一个拦截器返回false,直接跳出不执行目标方法。
  4. 所有拦截器都返回true,才执行目标方法。
  5. 倒序执行所有拦截器的postHandle()方法。
  6. 前面的步骤有任何异常都会直接倒序触发 afterCompletion()
  7. 页面成功渲染完成以后,也会倒序触发 afterCompletion()
    在这里插入图片描述

DispatcherServlet中涉及到HandlerInterceptor的地方:

public class DispatcherServlet extends FrameworkServlet {...protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;boolean multipartRequestParsed = false;WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);try {ModelAndView mv = null;Exception dispatchException = null;...//该方法内调用HandlerInterceptor的preHandle()if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// Actually invoke the handler.mv = ha.handle(processedRequest, response, mappedHandler.getHandler());...//该方法内调用HandlerInterceptor的postHandle()mappedHandler.applyPostHandle(processedRequest, response, mv);}			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}catch (Exception ex) {//该方法内调用HandlerInterceptor接口的afterCompletion方法triggerAfterCompletion(processedRequest, response, mappedHandler, ex);}catch (Throwable err) {//该方法内调用HandlerInterceptor接口的afterCompletion方法triggerAfterCompletion(processedRequest, response, mappedHandler,new NestedServletException("Handler processing failed", err));}finally {...}}private void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response,@Nullable HandlerExecutionChain mappedHandler, Exception ex) throws Exception {if (mappedHandler != null) {//该方法内调用HandlerInterceptor接口的afterCompletion方法mappedHandler.triggerAfterCompletion(request, response, ex);}throw ex;}private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,@Nullable Exception exception) throws Exception {...if (mappedHandler != null) {//该方法内调用HandlerInterceptor接口的afterCompletion方法// Exception (if any) is already handled..mappedHandler.triggerAfterCompletion(request, response, null);}}}
public class HandlerExecutionChain {...boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {for (int i = 0; i < this.interceptorList.size(); i++) {HandlerInterceptor interceptor = this.interceptorList.get(i);//HandlerInterceptor的preHandle方法if (!interceptor.preHandle(request, response, this.handler)) {triggerAfterCompletion(request, response, null);return false;}this.interceptorIndex = i;}return true;}void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)throws Exception {for (int i = this.interceptorList.size() - 1; i >= 0; i--) {HandlerInterceptor interceptor = this.interceptorList.get(i);//HandlerInterceptor接口的postHandle方法interceptor.postHandle(request, response, this.handler, mv);}}void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {for (int i = this.interceptorIndex; i >= 0; i--) {HandlerInterceptor interceptor = this.interceptorList.get(i);try {//HandlerInterceptor接口的afterCompletion方法interceptor.afterCompletion(request, response, this.handler, ex);}catch (Throwable ex2) {logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);}}}} 

50、文件上传-单文件与多文件上传的使用

  • 页面代码/static/form/form_layouts.html
<form role="form" th:action="@{/upload}" method="post" enctype="multipart/form-data"><div class="form-group"><label for="exampleInputEmail1">邮箱</label><input type="email" name="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email"></div><div class="form-group"><label for="exampleInputPassword1">名字</label><input type="text" name="username" class="form-control" id="exampleInputPassword1" placeholder="Password"></div><div class="form-group"><label for="exampleInputFile">头像</label><input type="file" name="headerImg" id="exampleInputFile"></div><div class="form-group"><label for="exampleInputFile">生活照</label><input type="file" name="photos" multiple></div><div class="checkbox"><label><input type="checkbox"> Check me out</label></div><button type="submit" class="btn btn-primary">提交</button>
</form>

Html中label标签
input标签的multiple,多文件上传
复习request、response
POST提交表单时EnType设置问题

  • 控制层代码
@Slf4j
@Controller
public class FormTestController {@GetMapping("/form_layouts")public String form_layouts(){return "form/form_layouts";}@PostMapping("/upload")public String upload(@RequestParam("email") String email,@RequestParam("username") String username,@RequestPart("headerImg") MultipartFile headerImg,@RequestPart("photos") MultipartFile[] photos) throws IOException {log.info("上传的信息:email={},username={},headerImg={},photos={}",email,username,headerImg.getSize(),photos.length);if(!headerImg.isEmpty()){//保存到文件服务器,OSS服务器String originalFilename = headerImg.getOriginalFilename();headerImg.transferTo(new File("H:\\cache\\"+originalFilename));}if(photos.length > 0){for (MultipartFile photo : photos) {if(!photo.isEmpty()){String originalFilename = photo.getOriginalFilename();photo.transferTo(new File("H:\\cache\\"+originalFilename));}}}return "main";}
}

在这里插入图片描述

文件上传相关的配置类:

  • org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration
  • org.springframework.boot.autoconfigure.web.servlet.MultipartProperties

文件大小相关配置项:

spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=100MB

51、文件上传-【源码流程】文件上传参数解析器

文件上传相关的自动配置类MultipartAutoConfiguration有创建文件上传参数解析器StandardServletMultipartResolver

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class })
@ConditionalOnProperty(prefix = "spring.servlet.multipart", name = "enabled", matchIfMissing = true)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(MultipartProperties.class)
public class MultipartAutoConfiguration {private final MultipartProperties multipartProperties;public MultipartAutoConfiguration(MultipartProperties multipartProperties) {this.multipartProperties = multipartProperties;}@Bean@ConditionalOnMissingBean({ MultipartConfigElement.class, CommonsMultipartResolver.class })public MultipartConfigElement multipartConfigElement() {return this.multipartProperties.createMultipartConfig();}@Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)@ConditionalOnMissingBean(MultipartResolver.class)public StandardServletMultipartResolver multipartResolver() {//配置好文件上传解析器StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily());return multipartResolver;}}
//文件上传解析器
public class StandardServletMultipartResolver implements MultipartResolver {private boolean resolveLazily = false;public void setResolveLazily(boolean resolveLazily) {this.resolveLazily = resolveLazily;}@Overridepublic boolean isMultipart(HttpServletRequest request) {return StringUtils.startsWithIgnoreCase(request.getContentType(), "multipart/");}@Overridepublic MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException {return new StandardMultipartHttpServletRequest(request, this.resolveLazily);}@Overridepublic void cleanupMultipart(MultipartHttpServletRequest request) {if (!(request instanceof AbstractMultipartHttpServletRequest) ||((AbstractMultipartHttpServletRequest) request).isResolved()) {// To be on the safe side: explicitly delete the parts,// but only actual file parts (for Resin compatibility)try {for (Part part : request.getParts()) {if (request.getFile(part.getName()) != null) {part.delete();}}}catch (Throwable ex) {LogFactory.getLog(getClass()).warn("Failed to perform cleanup of multipart items", ex);}}}}
public class DispatcherServlet extends FrameworkServlet {@Nullableprivate MultipartResolver multipartResolver;private void initMultipartResolver(ApplicationContext context) {...//这个就是配置类配置的StandardServletMultipartResolver文件上传解析器this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);...}protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;boolean multipartRequestParsed = false;//最后finally的回收flag...try {ModelAndView mv = null;Exception dispatchException = null;try {//做预处理,如果有上传文件 就new StandardMultipartHttpServletRequest包装类processedRequest = checkMultipart(request);multipartRequestParsed = (processedRequest != request);// Determine handler for the current request.mappedHandler = getHandler(processedRequest);...// Determine handler adapter for the current request.HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());...// Actually invoke the handler.mv = ha.handle(processedRequest, response, mappedHandler.getHandler());}....finally {...if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {...return this.multipartResolver.resolveMultipart(request);...}}protected void cleanupMultipart(HttpServletRequest request) {if (this.multipartResolver != null) {MultipartHttpServletRequest multipartRequest =WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);if (multipartRequest != null) {this.multipartResolver.cleanupMultipart(multipartRequest);}}}
}

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());跳到以下的类

public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapterimplements BeanFactoryAware, InitializingBean {@Overrideprotected ModelAndView handleInternal(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {ModelAndView mav;...mav = invokeHandlerMethod(request, response, handlerMethod);...return mav;}@Nullableprotected ModelAndView invokeHandlerMethod(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {ServletWebRequest webRequest = new ServletWebRequest(request, response);try {WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);if (this.argumentResolvers != null) {//关注点invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);}...invocableMethod.invokeAndHandle(webRequest, mavContainer);...return getModelAndView(mavContainer, modelFactory, webRequest);}finally {webRequest.requestCompleted();}}}

this.argumentResolvers其中主角类RequestPartMethodArgumentResolver用来生成

public class ServletInvocableHandlerMethod e
http://www.dinnco.com/news/24555.html

相关文章:

  • 网站 头尾调用seo优化方法网站快速排名推广渠道
  • 熟人做网站怎么收钱东莞网站建设工作
  • 西安做百度推广网站 怎样备案网站优化公司大家好
  • 有没有国外的做美食的视频网站短视频seo是什么
  • 网站设计需要哪些技能网站优化有哪些类型
  • 网站开发人员定罪案例百度热搜关键词排名优化
  • 网站建设业务员的工作总结及计划上海百度seo牛巨微
  • 成都市建设委员会门户网站社群营销怎么做
  • 网站域名哪些后缀更好中国军事新闻最新消息
  • 用html5做的网站淘宝店铺怎么推广和引流
  • 优秀网站评析网络营销运营推广
  • 怎么看网站是否被收录凡科建站下载
  • wordpress免费教育机构主题上海seo优化培训机构
  • 做鞋子批发网站济南网站优化排名
  • 东莞市常平东部中心医院长沙靠谱关键词优化服务
  • 百度seo效果seo是指
  • 出名的网站建设软件视频号视频怎么看下载链接
  • vps网站管理助手教程百度今日数据
  • php网站开发第三章东莞seo建站优化工具
  • 绍兴模板建站代理360外链
  • 风铃做的网站能否推广我赢网客服系统
  • 用什么软件可以做网站动态怎么做宣传推广
  • 绍兴优秀做网站的企业培训公司有哪些
  • 好听的公司名字免费网站排名优化在线
  • 湖北高速公路建设网站网络稿件投稿平台
  • 怎么自己在电脑上做网站推广公司简介
  • wordpress 优化 插件seo营销论文
  • 如何查询网站的建设商企业域名查询
  • html网站搭建中国行业数据分析网
  • 日本十大顶尖包装百度推广优化方案