mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-25 12:46:41 +08:00
733 lines
21 KiB
HTML
733 lines
21 KiB
HTML
<!DOCTYPE html>
|
||
|
||
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
|
||
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
|
||
<head>
|
||
|
||
<head>
|
||
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
|
||
|
||
<link rel="icon" href="/static/favicon.png">
|
||
|
||
<title>结束语 以终为始:Spring Boot 总结和展望.md.html</title>
|
||
|
||
<!-- Spectre.css framework -->
|
||
|
||
<link rel="stylesheet" href="/static/index.css">
|
||
|
||
<!-- theme css & js -->
|
||
|
||
<meta name="generator" content="Hexo 4.2.0">
|
||
|
||
</head>
|
||
|
||
|
||
|
||
<body>
|
||
|
||
|
||
|
||
<div class="book-container">
|
||
|
||
<div class="book-sidebar">
|
||
|
||
<div class="book-brand">
|
||
|
||
<a href="/">
|
||
|
||
<img src="/static/favicon.png">
|
||
|
||
<span>技术文章摘抄</span>
|
||
|
||
</a>
|
||
|
||
</div>
|
||
|
||
<div class="book-menu uncollapsible">
|
||
|
||
<ul class="uncollapsible">
|
||
|
||
<li><a href="/" class="current-tab">首页</a></li>
|
||
|
||
</ul>
|
||
|
||
|
||
|
||
<ul class="uncollapsible">
|
||
|
||
<li><a href="../">上一级</a></li>
|
||
|
||
</ul>
|
||
|
||
|
||
|
||
<ul class="uncollapsible">
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/00 开篇词 从零开始:为什么要学习 Spring Boot?.md.html">00 开篇词 从零开始:为什么要学习 Spring Boot?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/01 家族生态:如何正确理解 Spring 家族的技术体系?.md.html">01 家族生态:如何正确理解 Spring 家族的技术体系?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/02 案例驱动:如何剖析一个 Spring Web 应用程序?.md.html">02 案例驱动:如何剖析一个 Spring Web 应用程序?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/03 多维配置:如何使用 Spring Boot 中的配置体系?.md.html">03 多维配置:如何使用 Spring Boot 中的配置体系?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/04 定制配置:如何创建和管理自定义的配置信息?.md.html">04 定制配置:如何创建和管理自定义的配置信息?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/05 自动配置:如何正确理解 Spring Boot 自动配置实现原理?.md.html">05 自动配置:如何正确理解 Spring Boot 自动配置实现原理?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/06 基础规范:如何理解 JDBC 关系型数据库访问规范?.md.html">06 基础规范:如何理解 JDBC 关系型数据库访问规范?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/07 数据访问:如何使用 JdbcTemplate 访问关系型数据库?.md.html">07 数据访问:如何使用 JdbcTemplate 访问关系型数据库?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/08 数据访问:如何剖析 JdbcTemplate 数据访问实现原理?.md.html">08 数据访问:如何剖析 JdbcTemplate 数据访问实现原理?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/09 数据抽象:Spring Data 如何对数据访问过程进行统一抽象?.md.html">09 数据抽象:Spring Data 如何对数据访问过程进行统一抽象?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/10 ORM 集成:如何使用 Spring Data JPA 访问关系型数据库?.md.html">10 ORM 集成:如何使用 Spring Data JPA 访问关系型数据库?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/11 服务发布:如何构建一个 RESTful 风格的 Web 服务?.md.html">11 服务发布:如何构建一个 RESTful 风格的 Web 服务?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/12 服务调用:如何使用 RestTemplate 消费 RESTful 服务?.md.html">12 服务调用:如何使用 RestTemplate 消费 RESTful 服务?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/13 服务调用:如何正确理解 RestTemplate 远程调用实现原理?.md.html">13 服务调用:如何正确理解 RestTemplate 远程调用实现原理?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/14 消息驱动:如何使用 KafkaTemplate 集成 Kafka?.md.html">14 消息驱动:如何使用 KafkaTemplate 集成 Kafka?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/15 消息驱动:如何使用 JmsTemplate 集成 ActiveMQ?.md.html">15 消息驱动:如何使用 JmsTemplate 集成 ActiveMQ?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/16 消息驱动:如何使用 RabbitTemplate 集成 RabbitMQ?.md.html">16 消息驱动:如何使用 RabbitTemplate 集成 RabbitMQ?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/17 安全架构:如何理解 Spring 安全体系的整体架构?.md.html">17 安全架构:如何理解 Spring 安全体系的整体架构?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/18 用户认证:如何基于 Spring Security 构建用户认证体系?.md.html">18 用户认证:如何基于 Spring Security 构建用户认证体系?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/19 服务授权:如何基于 Spring Security 确保请求安全访问?.md.html">19 服务授权:如何基于 Spring Security 确保请求安全访问?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/20 服务监控:如何使用 Actuator 组件实现系统监控?.md.html">20 服务监控:如何使用 Actuator 组件实现系统监控?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/21 指标定制:如何实现自定义度量指标和 Actuator 端点?.md.html">21 指标定制:如何实现自定义度量指标和 Actuator 端点?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/22 运行管理:如何使用 Admin Server 管理 Spring 应用程序?.md.html">22 运行管理:如何使用 Admin Server 管理 Spring 应用程序?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/23 数据测试:如何使用 Spring 测试数据访问层组件?.md.html">23 数据测试:如何使用 Spring 测试数据访问层组件?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/24 服务测试:如何使用 Spring 测试 Web 服务层组件?.md.html">24 服务测试:如何使用 Spring 测试 Web 服务层组件?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
<a class="current-tab" href="/专栏/Spring Boot 实战开发/结束语 以终为始:Spring Boot 总结和展望.md.html">结束语 以终为始:Spring Boot 总结和展望.md.html</a>
|
||
|
||
|
||
|
||
|
||
|
||
</li>
|
||
|
||
</ul>
|
||
|
||
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||
|
||
<div class="sidebar-toggle-inner"></div>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<script>
|
||
|
||
function add_inner() {
|
||
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
|
||
inner.classList.add('show')
|
||
|
||
}
|
||
|
||
|
||
|
||
function remove_inner() {
|
||
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
|
||
inner.classList.remove('show')
|
||
|
||
}
|
||
|
||
|
||
|
||
function sidebar_toggle() {
|
||
|
||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let content = document.querySelector('.off-canvas-content')
|
||
|
||
if (sidebar_toggle.classList.contains('extend')) { // show
|
||
|
||
sidebar_toggle.classList.remove('extend')
|
||
|
||
sidebar.classList.remove('hide')
|
||
|
||
content.classList.remove('extend')
|
||
|
||
} else { // hide
|
||
|
||
sidebar_toggle.classList.add('extend')
|
||
|
||
sidebar.classList.add('hide')
|
||
|
||
content.classList.add('extend')
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
function open_sidebar() {
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
|
||
sidebar.classList.add('show')
|
||
|
||
overlay.classList.add('show')
|
||
|
||
}
|
||
|
||
function hide_canvas() {
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
|
||
sidebar.classList.remove('show')
|
||
|
||
overlay.classList.remove('show')
|
||
|
||
}
|
||
|
||
|
||
|
||
</script>
|
||
|
||
|
||
|
||
<div class="off-canvas-content">
|
||
|
||
<div class="columns">
|
||
|
||
<div class="column col-12 col-lg-12">
|
||
|
||
<div class="book-navbar">
|
||
|
||
<!-- For Responsive Layout -->
|
||
|
||
<header class="navbar">
|
||
|
||
<section class="navbar-section">
|
||
|
||
<a onclick="open_sidebar()">
|
||
|
||
<i class="icon icon-menu"></i>
|
||
|
||
</a>
|
||
|
||
</section>
|
||
|
||
</header>
|
||
|
||
</div>
|
||
|
||
<div class="book-content" style="max-width: 960px; margin: 0 auto;
|
||
|
||
overflow-x: auto;
|
||
|
||
overflow-y: hidden;">
|
||
|
||
<div class="book-post">
|
||
|
||
<p id="tip" align="center"></p>
|
||
|
||
<div><h1>结束语 以终为始:Spring Boot 总结和展望</h1>
|
||
|
||
<p>终于到了课程的最后一讲啦,这一讲我们将对整个 Spring Boot 课程进行总结。</p>
|
||
|
||
<p>Spring Boot 不仅是 Spring 家族的重要组成成员,也是一款业界领先的应用程序开发框架。通过 Spring Boot 提供的多项核心功能,我们能够快速构建一个完整的 Web 服务开发解决方案。</p>
|
||
|
||
<p>作为一门针对 Spring Boot 的系统化课程,在课程最后,我们先总结一下整个课程中介绍的 Spring Boot 核心功能,然后梳理一下写作过程中的一些思考和心得,最后对 Spring Boot 的未来发展进行展望。</p>
|
||
|
||
<h3>Spring Boot 的创新性</h3>
|
||
|
||
<p>Spring Boot 是 Spring 家族中由 Pivotal 团队提供的核心开发框架,它基于 Spring4.0 设计,目的是简化新 Spring 应用程序的初始搭建过程和开发过程。</p>
|
||
|
||
<p>自这个框架诞生以来,它就是快速应用开发领域(Rapid Application Development,RAD)界的领导者。通过使用 Spring Boot 内置的自动配置机制,使得开发人员再也不需要像传统的 Spring 框架那样,使用复杂和重复的配置构建和运行整个 Web 应用程序了,大大简化了开发工作流程。从这点上讲,Spring Boot 无疑是一款具有创新性的开发框架。</p>
|
||
|
||
<p>Spring Boot 不仅继承了 Spring 框架原有的优秀特性,同时它还添加了很多新的功能,包含但不限于以下五点:</p>
|
||
|
||
<ul>
|
||
|
||
<li>可以创建独立的 Spring 应用程序,这些应用程序可以以 JAR 包的形式直接运行;</li>
|
||
|
||
<li>内嵌 Tomcat、Jetty 等 Servlet 容器;</li>
|
||
|
||
<li>提供自动配置的“starter”项目以简化外部组件依赖管理;</li>
|
||
|
||
<li>尽可能把配置 Spring 容器的工作自动化;</li>
|
||
|
||
<li>提供开箱即用的特性,如指标、健康检查和外部化配置。</li>
|
||
|
||
</ul>
|
||
|
||
<p>除此之外,Spring Boot 还是 “约定优于配置(Convention over configuration)”设计理念的倡导者和实践者。</p>
|
||
|
||
<p>约定优于配置是一种软件设计范式,旨在帮助软件开发人员获得已经默认的内置功能组件,从而减少做决定的次数。在日常开发过程中,开发人员只需要指定自己所开发的应用程序中与约定存在差异的那部分内容即可,剩余的全部交给框架处理。</p>
|
||
|
||
<p>当然,Spring Boot 框架的强大之处还体现在集成性上。</p>
|
||
|
||
<p>在使用传统的 Spring 框架时,我们经常会遇到因为各个依赖的组件之间版本不一致导致应用程序无法启动的情况。而 Spring Boot 通过集成大量的外部框架,使得依赖包的版本冲突、引用的不稳定性等问题得到了很好的解决。在这点上,同样也体现了 Spring Boot 的创新性。</p>
|
||
|
||
<h3>Spring Boot 课程总结</h3>
|
||
|
||
<p>总结完 Spring Boot 的各项核心功能及所具备的创新性,我们再来总结一下整个课程的讲解特色和与其他课程之间的差异。</p>
|
||
|
||
<p>这里,我整理了本课程的三大亮点。</p>
|
||
|
||
<p><strong>第一大亮点:完整介绍了 Spring Boot 开发技术体系</strong>。通过学习本课程,你可以全面梳理基于 Spring Boot 的 Web 应用程序开发技术组件,其中包括配置体系、数据访问、Web 服务、消息通信、系统安全、系统监控、系统测试等专项主题。这些技术组件涵盖了 Java EE 应用程序开发涉及的方方面面,具有广泛的应用场景。</p>
|
||
|
||
<p><strong>第二大亮点:提供了实用的应用程序开发案例</strong>。这个案例系统足够简单,可以让你从零开始理解和掌握其中的各项知识点。同时,这个案例系统又足够完整,涉及的各个核心功能都为我们提供了相关的配置项和示例代码,在日常开发过程中可以进行参考。</p>
|
||
|
||
<p><strong>第三大亮点:提供了深入的功能组件原理分析过程</strong>。这些分析过程能帮助你在掌握 Spring Boot 框架应用的基础上,深入理解自动配置、数据访问、远程调用等核心技术组件的实现原理,做到知其然而知其所以然。</p>
|
||
|
||
<p>整个课程从平时的积累到酝酿,再到启动,最后到上线经历了小半年的时间,伴随着这个过程,我把 Spring Boot 的部分源代码系统梳理了一遍,也对内部的设计思想和实现原理做了一些提炼和总结。</p>
|
||
|
||
<p>总体而言,Spring Boot 是一款代码质量非常高的开源框架,其中关于 Spring Boot 和 Spring 框架的集成、内置的自动配置机制,以及数据访问、远程调用等诸多功能都给我留下了深刻的印象,使我受益良多,相信坚持学习到今天的你也是如此。</p>
|
||
|
||
<h3>Spring Boot 的发展和演进</h3>
|
||
|
||
<p>最后,我们来对 Spring Boot 的发展做一些展望。</p>
|
||
|
||
<p>首先,我们来看一下 Spring Boot 与 Spring 框架的演进过程。</p>
|
||
|
||
<p>目前 Spring 已经演进到 5.X 版本,随着 Spring 5 的正式发布,我们迎来了响应式编程(Reactive Programming)的全新发展时期。</p>
|
||
|
||
<p>Spring 5 中内嵌了与数据管理相关的响应式数据访问、与系统集成相关的响应式消息通信,以及与 Web 服务相关的响应式 Web 框架等多种响应式组件,从而极大简化了响应式应用程序的开发过程和难度。</p>
|
||
|
||
<p>以支持响应式 Web 的 Spring WebFlux 为例,这里我们给出它的架构图,如下图所示:</p>
|
||
|
||
<p><img src="assets/Cgp9HWAdAZCAB17fAACQeZA8Cyk925.png" alt="Drawing 0.png" /></p>
|
||
|
||
<p>Spring WebFlux 架构图(来自 Spring 官网)</p>
|
||
|
||
<p>在图中我们可以看到,上图左侧为基于 Spring Webflux 的技术栈,右侧为基于 Spring MVC 的技术栈。我们知道传统的 Spring MVC 是在 Java EE 的 Servlet 标准之上进行构建的,该标准本身就是阻塞式和同步式。而 Spring WebFlux 基于响应式流进行构建,因此我们可以使用它来构建异步非阻塞的服务。</p>
|
||
|
||
<p>随着 WebFlux 等响应式编程技术的兴起,它为构建具有即时响应性和回弹性的应用程序提供了一个很好的技术基础。</p>
|
||
|
||
<p>我们知道一个分布式系统中,可能存在数十乃至数百个独立的 Web 应用程序,它们之间互相通信以完成复杂的业务流程,而这个过程势必涉及大量的 I/O 操作。</p>
|
||
|
||
<p>一旦涉及 I/O 操作,尤其是阻塞式 I/O 操作将会整体增加系统的延迟并降低吞吐量。如果我们能够在复杂的流程中集成非阻塞、异步通信机制,就可以高效处理跨服务之间的网络请求。针对这种场景,WebFlux 也是一种非常有效的解决方案。</p>
|
||
|
||
<p>下面我们再来看一下 Spring Boot 2 的另一张官网架构图,如下图所示:</p>
|
||
|
||
<p><img src="assets/CioPOWAdAZ2AMVhnAACWjgTTFkY662.png" alt="Drawing 1.png" /></p>
|
||
|
||
<p>Spring Boot 2 架构图(来自 Spring 官网)</p>
|
||
|
||
<p>从图中我们可以看到,上图底部将 Spring Data 明确划分为两大类型:一类是支持 JDBC、JPA 和部分 NoSQL 的传统 Spring Data Repository,另一类则是支持 Mongo、Cassandra、Redis、Couchbase 等的响应式 Spring Data Reactive Repository。</p>
|
||
|
||
<p>这张图背后的意义在于,Spring Boot 可以帮助我们构建从 Web 服务层到数据访问层的全栈式响应式编程技术,从而确保系统的各个环节都具备即时响应性。</p>
|
||
|
||
<p>未来,让我们一起期待响应式编程技术与 Spring Boot 框架之间更加紧密的整合吧。</p>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div>
|
||
|
||
<div style="float: left">
|
||
|
||
<a href="/专栏/Spring Boot 实战开发/24 服务测试:如何使用 Spring 测试 Web 服务层组件?.md.html">上一页</a>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
</div>
|
||
|
||
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||
|
||
</div>
|
||
|
||
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"709975308f363d60","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
|
||
|
||
</body>
|
||
|
||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
|
||
|
||
<script>
|
||
|
||
window.dataLayer = window.dataLayer || [];
|
||
|
||
|
||
|
||
function gtag() {
|
||
|
||
dataLayer.push(arguments);
|
||
|
||
}
|
||
|
||
|
||
|
||
gtag('js', new Date());
|
||
|
||
gtag('config', 'G-NPSEEVD756');
|
||
|
||
var path = window.location.pathname
|
||
|
||
var cookie = getCookie("lastPath");
|
||
|
||
console.log(path)
|
||
|
||
if (path.replace("/", "") === "") {
|
||
|
||
if (cookie.replace("/", "") !== "") {
|
||
|
||
console.log(cookie)
|
||
|
||
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
setCookie("lastPath", path)
|
||
|
||
}
|
||
|
||
|
||
|
||
function setCookie(cname, cvalue) {
|
||
|
||
var d = new Date();
|
||
|
||
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
|
||
|
||
var expires = "expires=" + d.toGMTString();
|
||
|
||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||
|
||
}
|
||
|
||
|
||
|
||
function getCookie(cname) {
|
||
|
||
var name = cname + "=";
|
||
|
||
var ca = document.cookie.split(';');
|
||
|
||
for (var i = 0; i < ca.length; i++) {
|
||
|
||
var c = ca[i].trim();
|
||
|
||
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
|
||
|
||
}
|
||
|
||
return "";
|
||
|
||
}
|
||
|
||
|
||
|
||
</script>
|
||
|
||
|
||
|
||
</html>
|
||
|