柒索

一个头脑聪明,五肢发达的男人。

0%

Lombok - 工具简介:

Lombok是一个编译时注释预处理器,有助于在编译时注入一些代码。Lombok提供了一组在开发时处理的注释,以将代码注入到Java应用程序中,注入的代码在开发环境中立即可用。在详细介绍之前,可以去其官网看一下作者提供的视频,视频中阐述了Lombok 的简单用法。https://projectlombok.org/

Lombok - 安装过程:

基于 Maven:

示例代码:

1
2
3
4
5
6
7
8
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
</dependencies>

添加好 Maven 依赖之后,就可以在代码中使用 Lombok 的注解来简化代码了。

基于IntelliJ IDEA:

安装 Lombok IntelliJ plugin:

Jetbrains IntelliJ IDEA Editor完全兼容 Lombok,要在 IDEA 中使用 Lombok,那就需要在IntelliJ IDEA 中安装 Lombok IntelliJ plugin 插件,以下为安装步骤:

  • Go to File > Settings > Plugins

  • Click on Browse repositories...

  • Search for Lombok Plugin

  • Click on Install plugin

  • Restart IntelliJ IDEA

具体安装过程可参考官网或者插件 Github 主页。

在IntelliJ IDEA使用Lombok:

  • Go to Refactor > Lombok
  • 在打开的 JavaBean 文件中按照需求添加相应的注解即可。

Lombok - 常用注解:

你如果是使用IDEA的话,在当前文件上按command+F12,或者长按command在左侧找到Structure,就能够看到 lombok 为当前类生成的方法。

  • @Data :注解在类上;提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法

    示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    import lombok.Data;

    @Data
    public class Person {
    private String firstName;
    private String lastName;
    private String job;
    }
  • @Setter/@Getter:注解在属性或类上;为属性提供 Setter/Getter 方法

    示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import lombok.Getter;
    import lombok.Setter;

    // 只为 firstName 生成Getter、Setter 方法
    public class Person {
    @Getter
    @Setter
    private String firstName;
    private String lastName;
    private String job;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import lombok.Getter;
    import lombok.Setter;

    @Getter
    @Setter
    public class Person {
    // 为所有字段生成Getter、Setter 方法

    private String firstName;
    private String lastName;
    private String job;
    }

  • @Log4j :注解在类上;为类提供一个 属性名为log 的 log4j 日志对象

  • @Value:此注解集@equals()、@hashCode()、@toString()、@Getter()于一身。

    示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import lombok.Value;
    import lombok.experimental.NonFinal;

    @Value
    public class Person {
    /** 类本身以及类中所有的字段都是private final类型的,不会生成Setter方法。
    * 可以通过显式指定某个注解覆盖掉默认的属性。
    * 通过@NonFinal注解修饰的字段,不是final类型的。
    */
    String firstName;

    String lastName;
    @NonFinal
    String job;
    }

  • @NoArgsConstructor/@AllArgsConstructor: 自动生成无参数构造函数/全参构造函数。

    示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import lombok.AllArgsConstructor;
    import lombok.NoArgsConstructor;

    @NoArgsConstructor
    @AllArgsConstructor
    public class Person {
    private String firstName;

    private String lastName;

    private String job;
    }

  • @NonNull :修饰方法、构造函数的参数或者类字段,Lombok自动生成一个非空检测语句。

    示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    import lombok.NonNull;

    public class Person{
    public String Example(@NonNull String sum){

    return null;
    }
    }

  • @Synchronized 将方法变成同步方法

  • @SneakyThrows:将受检异常转换为非受检异常,避免抛出或尝试语句。

lombok 项目官网上还有一些其他注解的用法,此处就不列举了,附链接:https://projectlombok.org/features/all

参考资料:

前言:

本文讲解了在 JAVA8的环境中使用 Servlet3.1的标准容器中使用 Http 上下文的方式来深入了解 Servlet,通过一个简单的Maven Web项目,可以通过您喜爱的浏览器或Postman来访问。

环境准备:

  • Java Version : 1.8.0_121
  • Maven Version:Apache Maven 3.3.9
  • IDE:IntelliJ IDEA (2017.2.3)
  • System:macOS Sierra

Servlet - 简介:

Servlet是基于Java技术的web组件,容器托管的,用于生成动态内容。它是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。像其他基于Java的组件技术一样,Servlet也是基于平台无关的Java类格式,被编译为平台无关的字节码,可以被基于Java技术的web server动态加载并运行。容器,有时候也叫做servlet引擎,是web server为支持servlet功能扩展的部分。客户端通过Servlet容器实现的请求/应答模型与Servlet交互。

使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于 CGI,Servlet 有以下几点优势:

  • 性能明显更好。
  • Servlet 在 Web 服务器的地址空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。
  • Servlet 是独立于平台的,因为它们是用 Java 编写的。
  • 服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet 是可信的。
  • Java 类库的全部功能对 Servlet 来说都是可用的。它可以通过 sockets 和 RMI 机制与 applets、数据库或其他软件进行交互。

Servlet - 容器:

Servlet容器是web server或application server的一部分,提供基于请求/响应发送模型的网络服务,解码基于MIME的请求,并且格式化基于MIME的响应。Servlet 容器也包含了管理Servlet生命周期。

Servlet容器可以嵌入到宿主的web server中,或者通过Web Server的本地扩展API单独作为附加组件安装。Servelt容器也可能内嵌或安装到包含web功能的application server中。

所有Servlet容器必须支持基于HTTP协议的请求/响应模型,比如像基于HTTPS(HTTP over SSL)协议的请求/应答模型可以选择性的支持。容器必须实现的HTTP协议版本包含HTTP/1.0 和 HTTP/1.1。因为容器或许支持RFC2616 (HTTP/1.1)描述的缓存机制,缓存机制可能在将客户端请求交给Servlet处理之前修改它们,也可能在将Servlet生成的响应发送给客户端之前修改它们,或者可能根据RFC2616规范直接对请求作出响应而不交给Servlet进行处理。

Servlet容器应该使Servlet执行在一个安全限制的环境中。在Java平台标准版(J2SE, v.1.3 或更高) 或者 Java平台企业版(Java EE, v.1.3 或更高) 的环境下,这些限制应该被放置在Java平台定义的安全许可架构中。比如,高端的application server为了保证容器的其他组件不受到负面影响可能会限制Thread对象的创建。

Java SE 6是构建Servlet容器最低的Java平台版本。

事件序列:

以下是一个典型的事件序列:

1、客户端(如 web浏览器)发送一个HTTP请求到web服务器;

2、Web服务器接收到请求并且交给servlet容器处理,servlet容器可以运行在与宿主web服务器同一个进程中,也可以是同一主机的不同进程,或者位于不同的主机的web服务器中,对请求进行处理。

3、servlet容器根据servlet配置选择相应的servlet,并使用代表请求和响应对象的参数进行调用。

4、servlet通过请求对象得到远程用户,HTTP POST参数和其他有关数据可能作为请求的一部分随请求一起发送过来。Servlet执行我们编写的任意的逻辑,然后动态产生响应内容发送回客户端。发送数据到客户端是通过响应对象完成的。

5、一旦servlet完成请求的处理,servlet容器必须确保响应正确的刷出,并且将控制权还给宿主Web服务器。

Servlet - 规范:

许多供应商已经实施了servlet规范(例如:Tomcat,Jetty),尽管规范的确发展,供应商最终还是为我们部署我们的Web应用程序提供了实现。

通过JSR 340的提案,servlet 3.1规范在大版本3.0(JSR 315)上进行了迭代,允许我们的Web应用程序利用非阻塞IO和HTTP协议升级机制等功能。

在Servlet 3.0规范发布后的一大特点是不再需要一个web.xml 作为描述为我们所有的Servlet、过滤器、Listeners、init-PARAMS在 xml 文件中进行配置,大多数元数据、配置现在可以通过注释来完成。

此次使用web.xml 仅仅是为了在尝试访问安全路由时配置容器的登录过程。

web.xml:

1
2
3
4
5
6
7
8
9
10
11
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">

<!-- 将以任何安全路由的基本身份验证来挑战用户 -->
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>servletbasics</realm-name>
</login-config>
</web-app>

Servlet - 生命周期:

Servlet是按照一个严格定义的生命周期被管理,该生命周期规定了Servlet如何被加载、实例化、初始化、处理客户端请求,以及何时结束服务。该声明周期可以通过javax.servlet.Servlet接口中的init、service和destroy这些API来表示,所有Servlet必须直接或间接的实现GenericServlet或HttpServlet抽象类。

以下是典型servlet的生命周期。

  1. init 实例化:

    用户访问这个Servlet,由容器实例化,它的init()方法被调用一次。通常,Servlet被实例化一次,并且在使用中产生大量并发,尽管容器可以汇集实现SingleThreadModel的多个servlet来处理重负载。

  2. 调用Service服务:
    Servi为每个请求调用Servlets的service()方法,如果您的servlet实现了HttpServlet接口,那么该请求将被委派给与您给定的请求动词匹配的任何便利方法。

  3. 销毁 Servlet:
    destroy()方法被调用,允许我们钩入生命周期,并终止servlet使用的任何资源。

  4. 垃圾收集:
    垃圾收集器收集servlet。

Servlet - 过滤器:

Servlet的过滤器旨在拦截对servlet,jsp或甚至静态HTML文件的请求。他们还将响应拦截回客户端,因此可用于修改请求/响应,有时甚至根据特定条件阻止或重定向它们。

其中包括:

  • 身份验证:拦截请求以防止未经身份验证的用户
  • 压缩:将响应压缩回客户端
  • 更改请求/响应体的交换格式
  • 跟踪请求/响应

Servlet - 监听器:

servlet规范允许我们定义WebListener,它可以对Web应用程序中发生的某些事件做出反应。事件可以在会话,请求,应用程序级别,不同类型的WebListener被设计为对不同的事件做出反应。

对于不同的场景,存在以下WebListeners:

Scope WebListener 接口 Event
Web context ServletContextListener
ServletContextAttributeListener
ServletContextEvent
ServletContextAttributeEvent
Session HttpSessionListener
HttpSessionActivationListener
HttpSessionAttributeListener
HttpSessionEvent
HttpSessionEvent
HttpSessionBindingEvent
Request ServletRequestListener
ServletRequestAttributeListener
ServletRequestEvent
ServletRequestAttributeEvent

Servlet - Context:

Servlet - 注解:

在web应用中,使用注解的类仅当它们位于WEB-INF/classes目录中,或它们被打包到位于应用的WEB-INF/lib中的jar文件中时它们的注解才将被处理。

Web应用部署描述符的web-app元素包含一个新的“metadata-complete”属性。“metadata-complete”属性定义了web描述符是否是完整的,或是否应该在部署时检查jar包中的类文件和web fragments。如果“metadata-complete”设置为“true”,部署工具必须必须忽略存在于应用的类文件中的所有指定部署信息的servlet注解和web fragments。如果metadata-complete属性没有指定或设置为“false”,部署工具必须检查应用的类文件的注解,并扫描web fragments。

以下注解必须被Servlet 3.0兼容的容器支持。

@WebServlet:

该注解用于在Web应用中定义Servlet组件。该注解在一个类上指定并包含声明Servlet的元数据。必须指定注解的urlPatterns或value属性。所有其他属性是可选的默认设置。@WebServlet注解的类必须继承javax.servlet.http.HttpServlet类。

使用示例:

1
2
3
4
@WebServlet(”/foo”)
public class CalculatorServlet extends HttpServlet{
//...
}

@WebFilter:

该注解用于在Web应用中定义Filter。该注解在一个类上指定且包含声明过滤器的元数据。如果没有指定Filter名字则默认是全限定类名。注解的urlPatterns属性, servletNames 属性 或 value 属性必须被指定。所有其他属性是可选的默认设置。@WebFilter注解的类必须实现javax.servlet.Filter。

使用示例:

1
2
3
4
5
6
@WebFilter(“/foo”)
public class MyFilter implements Filter {
public void doFilter(HttpServletRequest req, HttpServletResponse res) {
...
}
}

@WebInitPara:

该注解用于指定必须传递到Servlet或Filter的任何初始化参数。它是WebServlet和WebFilter注解的一个属性。

@WebListener:

WebListener注解用于注解用来获得特定web应用上下文中的各种操作事件的监听器。@WebListener注解的类必须实现以下接口:

  • javax.servlet.ServletContextListener
  • javax.servlet.ServletContextAttributeListener
  • javax.servlet.ServletRequestListener
  • javax.servlet.ServletRequestAttributeListener
  • javax.servlet.http.HttpSessionListener
  • javax.servlet.http.HttpSessionAttributeListener
  • javax.servlet.http.HttpSessionIdListener

使用示例:

1
2
3
4
5
6
7
8
@WebListener
public class MyListener implements ServletContextListener{
public void contextInitialized(ServletContextEvent sce) {
ServletContext sc = sce.getServletContext();
sc.addServlet("myServlet", "Sample servlet", "foo.bar.MyServlet", null, -1);
sc.addServletMapping("myServlet", new String[] { "/urlpattern/*" });
}
}

@MultipartConfig:

该注解,当指定在Servlet上时,表示请求期望是mime/multipart类型。相应servlet的HttpServletRequest对象必须使用getParts和getPart方法遍历各个mime附件以获取mime附件。javax.servlet.annotation.MultipartConfig的location属性和元素被解析为一个绝对路径且默认为javax.servlet.context.tempdir。如果指定了相对地址,它将是相对于tempdir位置。绝对路径与相对地址的测试必须使用java.io.File.isAbsolute。

Servlet - 异步操作:

异步处理在重负载或在客户端和服务器之间以不同速度读取和写入大量数据的情况下特别有用,意味着两个实体之一可能会等待来自另一个的输入。

在servlet 3.0规范中,引入了servlet内部的异步处理,允许长时间运行的任务在一个单独的线程中完成,以允许请求线程返回到从它处理其他请求的池中。

通过servlet 3.1规范,我们得到了能够以异步方式在客户端和服务器之间读写数据的功能,从而允许以非阻塞方式异步处理客户端和服务器之间的长时间读写操作,特别适用于大型读取和写入时可能阻止的数据流以不同的速度完成。这些功能通过ReadListenerWriteListener接口来实现。

作为servlet 3.1规范的一部分,我们为servlet和过滤器提供异步处理支持。

参考资料:

JCP(Java Servlet 3.1规范):https://jcp.org/en/jsr/detail?id=340

NPM是什么?

npm(全称 Node Package Manager,即node包管理器)是Node.js默认的、以JavaScript编写的软件包管理系统。

NPM的使用场景:

  • 允许用户从NPM服务器下载别人编写的第三方包到本地使用。
  • 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
  • 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用

NPM-工作原理:

npm依赖解析的主要思想:尽可能地减少间接依赖安装目录的深度,最理想的情况是与直接依赖安装在同一目录下,通过这种方式来减少依赖目录的嵌套,缓解整个依赖目录层次过深的问题。(因为 Windows 中文件路径的长度不能大于 260 个字符。)

参考资料:NPM基本用法和使用技巧

NPM-基础操作:

NPM是随同Node.js一起安装的包管理工具,所以我们只需要安装nodejs就可以同时安装成功NPM

安装Node.js并更新npm

Win系统:

进入Node.js 官方网站,找到 Downloads 栏目,选择适合自己系统的安装包进行安装。

MacOS系统:

在MacOS系统上建议先安装Homebrew,然后使用homebrew来安装NPM。

1
2
brew search nodejs #搜索
brew install nodejs #安装

CentOS系统:

在CentOS系统上,我们可以使用yum命令来安装Node.js,前提是需要配置好yum源。

1
yum -y install nodejs

Ubuntu系统:

在 Ubuntu系统上,我们可以使用apt-get方式来安装Node.js。

1
apt-get install nodejs  

安装完成并且配置好相关环境之后,我们可以再Terminal中输入node -v
npm -v分别来测试nodejsnpm是否安装成功。

npm常用参数:

  • -g, –global:安装全局依赖,如果没有指定依赖包名,则将当前目录中的包安装至全局

  • -S, –save:安装依赖的同时将该依赖写入 dependencies

  • -D, –save-dev:安装依赖的同时将该依赖写入 devDependencies

  • -O, –save-optional:安装依赖的同时将该依赖写入 optionalDependencies

  • -E, –save-exact:写入 package.json 时带有确切版本号

  • –no-optional:不安装 optional dependencies,可继承

  • –only={dev[elopment]|prod[uction]}:无视 NODE_ENV,只安装 devDependencies 或仅安装除了 devDependencies 之外的依赖项

  • –dry-run:走一遍安装的过程并报告结果,但实际上没有安装任何依赖

在本地安装npm软件包

有两种方法来安装NPM包:本地或全局,你选择哪一种安装使用基于你想如何使用包。

如果你想使用类似的Node.js依赖于包从自己的模块 require,然后要在本地安装,这是npm install的默认行为。在另一方面,如果你想使用它作为一个命令行工具,像繁重的CLI的东西,那么你要在全局安装它。

npm install命令的使用可在下文npm-cli部分查看。

init初始化项目:

1
2
npm init #在项目根目录下使用它会创建一个package.json文件,需要填写一些内容,详见下文
npm init -y # 在package.json文件中全部使用默认选项

使用 package.json

管理本地安装的npm软件包的最佳方法是创建一个package.json文件。

一个package.json文件为你提供了很多方便:

- 它作为您的项目所依赖的包的文档。
- 它允许您使用语义版本控制规则来指定项目可以使用的包的版本。
- 使您的构建可重复,这意味着它的方式更容易与其他开发人员共享。

package.json语法:

  • “name”
  • 全部小写
  • 一个字,没有空格
  • 破折号和下划线允许
  • “version”

demo:

1
2
3
4
{
"name": "my-awesome-package",
"version": "1.0.0"
}

其他字段释义:

字段名称 说明
name 当前项目名称
version 项目版本信息,默认为1.0.0
description 来自readme的信息,否则为空字符串 “”
main 默认为index.js
scripts 默认情况下会创建一个空test脚本
keywords 关键词信息,默认空
author 作者信息,默认空
license 软件许可证 ISC
bugs 来自当前项目的信息(如果存在)
homepage 来自当前项目的信息(如果存在)
dependencies 您的应用程序在生产中需要这些软件包
devDependencies 这些软件包仅用于开发和测试

安装npm软件包

安装本地(local)软件包:

1
npm install <packageName> # 需要在当前项目项目根目录下,与package.json 文件在同一目录下

安装全局(global)软件包:

1
npm install -g  <packageName> 

在全局安装时出现Permission denied错误时,请在npm指令前加上 sudo(类UNIX系统下)

查看npm软件包

查看本地(local)软件包:

1
npm list # 与package.json 在同一目录下运行

查看全局(global)软件包:

1
npm list -g # Terminal中运行

更新npm软件包

1
npm list -g # 查看系统中全局安装过的软件包

应该经常更新您依赖的软件包,以便您可以获得对上游代码进行的任何更改。

更新本地(local)软件包:

1
npm update <packageName> #对单个包升级

更新全局(global)软件包:

npm -g是管理本地全局包的命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
➜  ~ npm -g outdated # 使用此命令可以查看那些包有更新:
Package Current Wanted Latest Location
cordova 6.5.0 7.0.1 7.0.1
create-react-app 1.3.0 1.3.3 1.3.3
elf-cli 1.4.0 1.7.0 1.7.0
express 4.15.2 4.15.3 4.15.3
ionic 2.2.2 3.5.0 3.5.0
node-gyp 3.6.0 3.6.2 3.6.2
node-inspector 1.0.0 1.1.1 1.1.1
npm 4.4.1 5.3.0 5.3.0
wechat-api 1.32.0 1.33.0 1.33.0


npm update -g <packageName> # 更新全局的软件包


参考:npm升级所有可更新包

卸载npm软件包

卸载本地(local)软件包

1
npm uninstall <packageName>

删除本地模块时你应该思考的问题:是否将在package.json上的相应依赖信息也消除?

  • npm uninstall 模块: 删除模块,但不删除模块留在package.json中的对应信息
  • npm uninstall --save 模块: 删除模块,同时删除模块留在package.json中dependencies下的对应信息
  • npm uninstall --save-dev 模块: 删除模块,同时删除模块留在package.json中devDependencies下的对应信息

卸载全局(global)软件包

1
npm uninstall -g <packageName>  

发布npm包

你可以推送任何包含 package.json 文件的文件夹,比如一个 node module

####注册账号

要发布软件包,你必要有一个 npm 账号,如果没有可以使用 npm adduser 创建一个。然后使用 npm login 登录。

参考:

npm的语义版本控制

语义版本控制是许多项目用于传达此版本中的哪些更改的标准。
沟通发布中的哪些更改很重要,因为有时这些更改将会破坏依赖于该包的代码。

semver:语义化版本标准Link

作为发布者:

如果一个项目将与其他人共享,那么应该从1.0.0项目开始,尽管有些项目在npm不符合这个规则。
之后,变更应处理如下:

  • 错误修正和其他微小变化:修补程序释放,增加最后一个数字,例如1.0.1
  • 不破坏现有功能的新功能:轻微释放,增加中间数字,例如1.1.0
  • 破坏向后兼容性的更改:主要版本,增加第一个数字,例如2.0.0

作为使用者:

作为开发者,可以指定应用程序在package.json文件中可以接受哪些类型的更新。

如果您从1.0.4开始,那么您将如何指定范围:

  • 补丁版本:1.0或1.0.x或~1.0.4
  • 次要版本:1或1.x或^1.0.4
  • 主要版本:*或x

NPM-私有模块:

你可以使用 NPM 命令行工具来管理你在 NPM 仓库的私有模块代码,这使得在项目中使用公共模块变的更加方便。

准备工作

你需要一个 2.7.0 以上版本的 npm ,并且需要有一个可以登陆 npm 仓库的账号。

1
2
npm install -g npm
npm login

软件包配置

所有的私有模块都是 scoped package 的。

scope 是 npm 的新特性。如果一个模块的名字以 “@” 开始,那么他就是一个scoped package。scope 就是”@”与”/“之间的部分。

1
@scope/project-name

当你注册私有模块到一个用户下时,你的 scope 就是当前用户的用户名。

1
@username/project-name

如果要使用npm init 初始化一个软件包,你可以通过自定义 --scope 选项设置你的 scope

1
npm init --scope=<your_scope>

如果你在大多数时候使用的 scope 都是相同的,可以设置一个默认的 scope ,这样在我们初始化的时候会自动使用该 scope

1
npm config set scope <your_scope>

发布模块

1
npm publish

默认情况下,scoped package 会发布为私有模块,发布为私有模块是需要付费的,费用是每个月 $7

一旦完成发布,你将会在npm库站点上看到你的 scoped package,有 private 标志,说明是非公共的模块,他人无法使用。

私有仓库

授权访问

如果你要授权给其他人使用你的模块,你可以在 package 的权限设置页面设置哪些用户可以拥有 只读或读写、权限。也可以通过命令行进行相关设置

1
npm owner add <user> <package name>

安装私有模块

如果要安装私有模块,你必须要有权限访问到要安装的私有模块。安装的时候可以使用 scope package name

1
npm install @scope/project-name

当你在项目中使用这些代码模块时可以如下使用

1
var project = require('@scope/project-name')

参考资料:

NPM-CLI命令:

命令 释义
npm install 安装模块
npm uninstall 卸载模块
npm update 更新模块
npm outdated 检查模块是否已经过时
npm ls 查看安装的模块
npm init 在项目中引导创建一个package.json文件
npm help 查看某条命令的详细帮助
npm root 查看包的安装路径
npm config 管理npm的配置路径
npm cache 管理模块的缓存
npm start 启动模块
npm stop 停止模块
npm restart 重新启动模块
npm test 测试模块
npm version 查看模块版本
npm view 查看模块的注册信息
npm adduser 用户登录
npm publish 发布模块
npm access 在发布的包上设置访问级别
npm package.json 的语法

参考资料:
NPM官网 CLI Commands

NPM-常用配置:

常用配置项:

  • cache:npm 本地缓存目录,默认 ~/.npm
  • cache-max:保持缓存项目且不向 registry 检查的最长时间,单位秒,默认 Infinity,缓存中的数据不会自动删除除非执行 npm cache clean 命令
  • cache-min:保持缓存项目且不向 registry 检查的最短时间,单位秒,默认 10,可以置为 999999 等以尽量延长缓存生效时间
  • depthnpm ls 等命令中的默认深度,默认 Infinity
  • editor:npm 默认使用的编辑器
  • engine-strict:如果置为 true,npm 将会拒绝安装不符合当前 Node.js 版本的模块
  • force:强力执行一些命令
    • 生命周期脚本执行失败不再阻塞安装过程
    • 发布会覆盖已经发布的版本
    • 访问 registry 时会跳过缓存
  • global:全局模式
  • globalconfig:全局配置文件的路径
  • global-style:以安装全局依赖的方式安装局部依赖,只有直接依赖会被放在顶层依赖目录中
  • https-proxy:代理
  • if-present:如果置为 truenpm run-script 就不会在脚本找不到时报错
  • ignore-scripts:如果置为 true,npm 就不会运行 package.json 定义的脚本
  • init-module:指定 npm init 命令运行的模块
  • init-author-namenpm init 使用的默认作者名
  • init-author-emailnpm init 使用的默认作者邮箱
  • init-author-urlnpm init 使用的默认作者 URL
  • init-licensenpm init 使用的默认许可证
  • init-versionnpm init 使用的默认版本号
  • jsonnpm ls 等命令输出 JSON 格式的数据
  • link:如果置为 true,如果全局依赖中有合适的包,安装局部依赖时将会直接链接到这个全局依赖的包;如果全局依赖中没有该包的任何版本,则全局安装这个包,并链接到局部依赖中;其他情况则在局部依赖中安装该包
  • longnpm lsnpm search 显示额外信息
  • messagenpm version 写在 git 提交中的信息,%s 将被替换为版本号
  • npat:安装时运行测试
  • onload-script:指定一个在 npm 加载时 require() 的包,编程使用 npm 时可能会有用
  • only:与命令中的 --only 效果类似
  • optional:如果置为 false,则不安装 optionalDependencies 中的依赖
  • prefix:指定安装全局依赖的路径
  • production:如果置为 true,则开启生产模式,npm install 将不安装开发依赖,声明周期脚本运行时自动设置 NODE_ENV="production"
  • registry:指定 npm registry 的 URL
  • rollback:移除安装失败的模块
  • save:与命令中的 --save 效果类似
  • scope:与命令中的 --scope 效果类似
  • shrinkwrap:如果置为 false,安装时忽略 npm-shrinkwrap.json
  • progress:如果置为 false,不显示进度条
  • loglevel:设置输出日志的 level,置为 silly 可以显示全部日志

npmrc:

配置文件有:

  • 项目配置文件(/path/to/my/project/.npmrc)
  • 用户配置文件(~/.npmrc)
  • 全局配置文件(/path/to/node/etc/npmrc)
  • 内置配置文件(/path/to/npm/npmrc)

scripts:

npm 支持的生命周期脚本有:

  • prepublish: 发布模块之前执行,也在不带任何参数的局部 npm install 之前执行
  • publishpostpublish: 发布模块之后执行
  • preinstall: 安装该模块之前执行
  • installpostinstall: 安装该模块之后执行
  • preuninstalluninstall: 移除该模块之前执行
  • postuninstall: 移除该模块之后执行
  • preversionversion: 修改模块版本号之前执行
  • postversion: 修改模块版本号之后执行
  • pretesttestposttest: 在 test 命令的前后执行
  • prestopstoppoststop: 在 stop 命令的前后执行
  • prestartstartpoststart: 在 start 命令的前后执行.
  • prerestartrestartpostrestart: 在 restart 命令的前后执行,如果 restart 脚本没有提供,restart 命令将会执行 stop 脚本再执行 start 脚本

对于自定义名称的脚本,可以通过 npm run-script <pkg> <stage> 来执行,匹配名称的 prepost 命令同样也会执行。

NPM-参考资料:

Gulp- 简介

Automate and enhance your workflow | 用自动化构建工具增强你的工作流程

Gulp 是什么?

gulp是前端开发过程中一种基于流的代码构建工具,是自动化项目的构建利器;它不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成;
使用它,不仅可以很愉快的编写代码,而且大大提高我们的工作效率。

gulp是基于Nodejs的自动任务运行器,它能自动化地完成 javascript、coffee、sass、less、html/image、css 等文件的测试、检查、合并、压缩、格式化、浏览器自动刷新、部署文件生成,并监听文件在改动后重复指定的这些步骤。在实现上,她借鉴了Unix操作系统的管道(pipe)思想,前一级的输出,直接变成后一级的输入,使得在操作上非常简单。通过本文,我们将学习如何使用Gulp来改变开发流程,从而使开发更加快速高效。

gulp 和 grunt 非常类似,但相比于 grunt 的频繁 IO 操作,gulp 的流操作,能更快地更便捷地完成构建工作。

Gulp的核心概念?

流,简单来说就是建立在面向对象基础上的一种抽象的处理数据的工具。在流中,定义了一些处理数据的基本操作,如读取数据,写入数据等,程序员是对流进行所有操作的,而不用关心流的另一头数据的真正流向。流不但可以处理文件,还可以处理动态内存、网络数据等多种数据形式。

而gulp正是通过流和代码优于配置的策略来尽量简化任务编写的工作。这看起来有点“像jQuery”的方法,把动作串起来创建构建任务。早在Unix的初期,流就已经存在了。流在Node.js生态系统中也扮演了重要的角色,类似于*nix将几乎所有设备抽象为文件一样,Node将几乎所有IO操作都抽象成了stream的操作。因此用gulp编写任务也可看作是用Node.js编写任务。当使用流时,gulp去除了中间文件,只将最后的输出写入磁盘,整个过程因此变得更快。

Gulp的特点?

  • 易于使用:
    通过代码优于配置的策略,gulp 让简单的任务简单,复杂的任务可管理。
  • 构建快速:
       利用 Node.js 流的威力,你可以快速构建项目并减少频繁的 IO 操作。
    
  • 易于学习:
       通过最少的 API,掌握 gulp 毫不费力,构建工作尽在掌握:如同一系列流管道。
    
  • 插件高质:
       gulp 严格的插件指南确保插件如你期望的那样简洁高质得工作。
    

Gulp- 环境搭建

gulp 是基于 node 实现的,那么我们就需要先安装 node

Node是一个基于Google V8 JavaScript引擎建立的一个平台,可以利用它实现Web服务,做类似PHP的事。

1
2
3
4
5
npm install -g gulp  # 全局安装gulp 
gulp -v # 查看gulp是否安装成功

➜ ~ gulp -v
[20:17:32] CLI version 3.9.1

Gulp- 构建项目

使用Gulp来构建项目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mkdir Gulp && cd Gulp && npm init -y && npm install gulp --save-dev
#使用npm初始化项目并且安装Gulp模块,能够看到如下的package.json文件中已经包含了Gulp的相关信息。
{
"name": "Gulp",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"gulp": "^3.9.1"
}
}

gulpfile.js文件的使用:

gulp也需要一个文件作为它的主文件,在gulp中这个文件叫做gulpfile.js。

创建gulpfile.js文件,与package.json文件一样放在项目根目录中,之后需要做的就是在gulpfile.js文件中定义任务了。

在gulpfile.js文件中写入以下内容:

1
2
3
4
var gulp = require('gulp');
gulp.task('default', function() {
console.log("Gulp OK!");
});

完成之后在Terminal中运行**gulp**命令,然后会看到刚才在task任务中要输出的内容.

1
2
3
4
5
6
➜  gulp
[00:35:29] Using gulpfile ~/WebStrom-Work/Gulp/gulpfile.js
[00:35:29] Starting 'default'...
Gulp OK!
[00:35:29] Finished 'default' after 141 μs

Gulp- API

gulp.src()

语法:

1
gulp.src(globs[, options])

输出(Emits)符合所提供的匹配模式(glob)或者匹配模式的数组(array of globs)的文件。 将返回一个 Vinyl files 的 stream 它可以被 piped 到别的插件中。

名称 类型 含义
globs String 或 Array 所要读取的 glob 或者包含 globs 的数组。
options Object 通过 glob-stream 所传递给 node-glob 的参数。

gulp.dest()

语法:

1
gulp.dest(path[, options])

能被 pipe 进来,并且将会写文件。并且重新输出(emits)所有数据,因此你可以将它 pipe 到多个文件夹。如果某文件夹不存在,将会自动创建它。

  • path 类型: String or Function ,文件将被写入的路径(输出目录)。也可以传入一个函数,在函数中返回相应路径,这个函数也可以由 vinyl 文件实例 来提供。

  • options
    类型: Object , 为一个可选的参数对象,通常我们不需要用到

gulp.task()

语法:

1
gulp.task(name[, deps], fn)
  • name
    类型: String,任务的名字,如果你需要在命令行中运行你的某些任务,那么,请不要在名字中使用空格。

  • deps
    类型: Array,一个包含任务列表的数组,这些任务会在你当前任务运行之前完成。

    demo
    1
    2
    3
    gulp.task('mytask', ['array', 'of', 'task', 'names'], function() {
    // 做一些事
    });

    注意: 你的任务是否在这些前置依赖的任务完成之前运行了?请一定要确保你所依赖的任务列表中的任务都使用了正确的异步执行方式:使用一个 callback,或者返回一个 promise 或 stream。

  • fn
    该函数定义任务所要执行的一些操作。通常来说,它会是这种形式:gulp.src().pipe(someplugin())。

gulp.watch()

语法:

1
gulp.watch(glob[, opts], tasks)

gulp.watch()用来监视文件的变化,当文件发生变化后,我们可以利用它来执行相应的任务。

  • glob类型: String or Array ,一个 glob 字符串,或者一个包含多个 glob 字符串的数组,用来指定具体监控哪些文件的变动。

  • opts 类型: Object

传给 gaze 的参数。

  • cb(event)
    类型: Function ,每次变动需要执行的 callback。

参考:Gulp-API

Gulp- 常用插件

压缩JS -> gulp-uglify:

安装 gulp-uglify:

1
npm install gulp-uglify --save-dev 

示例代码:

1
2
3
4
5
6
7
8
9
var gulp = require('gulp');
var uglify = require('gulp-uglify');

gulp.task('javascript',function () { // javascript: 任务名称
gulp.src('./src/js/*.js') // src: 定位到需要压缩的js文件目录下
.pipe(uglify()) // 执行压缩文件
.pipe(gulp.dest('./dist/js')); // 输出到指定目录
});

API参考:gulp-uglify

压缩CSS -> gulp-minify-css:

安装 gulp-minify-css

1
npm install gulp-minify-css --save-dev

示例代码:

1
2
3
4
5
6
7
8
var gulp = require('gulp');
var minify = require('gulp-minify-css')

gulp.task('css',function () {
gulp.src('./src/css/*.css')
.pipe(minify())
.pipe(gulp.dest('./dist/css'));
});

API参考:gulp-minify-css

压缩图片 -> gulp-imagemin:

安装 gulp-imagemin

1
npm install gulp-imagemin --save-dev

示例代码:

1
2
3
4
5
6
7
8
var gulp = require('gulp');
var image = require('gulp-imagemin');

gulp.task('image',function () {
gulp.src('./src/images/*.*')
.pipe(imagemin())
.pipe(gulp.dest('./dist/images'));
});

API参考:gulp-imagemin

编译Less-> gulp-less:

安装 gulp-less

1
npm install gulp-less --save-dev

示例代码:

1
2
3
4
5
6
7
8
var gulp = require('gulp');
var less = require('gulp-less');

gulp.task('less',function () {
gulp.src('./src/less/*.*')
.pipe(less())
.pipe(gulp.dest('./dist/less'));
});

API参考:gulp-less

自动刷新-> gulp-livereload:

安装gulp-livereload

1
npm install gulp-livereload --save-dev

示例代码:

1
在每个gulp.task()方法中的gulp.src()方法后追加   .pipe(livereload());    即可。

需要配合谷歌浏览器插件 LiveReload插件来使用,实现自动刷新。

API参考:gulp-livereload

Google Chrome Plugin:LiveReload

完整gulpfile.js文件:

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
27
28
29
30
31
32
33
34
35
36
37
var gulp = require('gulp'); // Gulp
var uglify = require('gulp-uglify'); // JavaScript
var minify = require('gulp-minify-css'); // CSS
var imagemin = require('gulp-imagemin'); // Images
var less = require('gulp-less'); // Less
var livereload = require('gulp-livereload') // LiveReload

// 执行所有任务
gulp.task('default', ['javascript','css','less','image']);

gulp.task('javascript',function () { // jsscript: 任务名称
gulp.src('./src/js/*.js') // src: 定位到需要压缩的js文件目录下
.pipe(uglify()) // 执行压缩文件
.pipe(gulp.dest('./dist/js')); // 输出到指定目录
});



gulp.task('css',function () {
gulp.src('./src/css/*.css')
.pipe(minify())
.pipe(gulp.dest('./dist/css'));
});

gulp.task('less',function () {
gulp.src('./src/less/*.*')
.pipe(less())
.pipe(gulp.dest('./dist/css'));
});


gulp.task('image',function () {
gulp.src('./src/images/*.*')
.pipe(imagemin())
.pipe(gulp.dest('./dist/images'));
});

Gulp- 参考资料

常见web项目目录:

在当前项目的根目录下执行tree命令,即可看到项目的整个目录结构,如果没有tree命令,在Mac系统下可以使用brew进行安装:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
➜  Glup tree ../Glup
../Glup

├── build # 项目构建脚本
├── src # 源码目录
│   ├── css # CSS文件
│   ├── fonts # 字体文件
│   ├── images # 图片文件
│   ├── js # js脚本文件
│   ├── less # less文件
│   └── sass # sass文件
├── dist # 编译出来的发布版本目录
│   ├── css
│   ├── fonts
│   ├── images
│   └── js
├── docs # 文档
├── test # 测试脚本
├── gulpfile.js # Gulp工具构建项目的主文件
├── node_modules # npm包存放目录
├── package-lock.json #npm5.0以上项目依赖文件
├── package.json # npm包管理配置文件
├── LICENSE # 授权协议
└── README.md # 项目说明文件

DQL

WITH…AS…

With查询语句不是以select开始的,而是以“WITH”关键字开头创建临时表查询

可认为在真正进行查询之前预先构造了一个临时表,之后便可多次使用它做进一步的分析和处理

UNION&UNION ALL

PS:UNION比UNION ALL 效率低,如果明确确认集合中不包括重复记录则使用UNION ALL ,如果表数据很大可能会导致用磁盘进行排序耗费时间

为了合并多个SELECT语句的结果,可以使用集合操作符,实现集合的并、交、差。

集合操作符包括UNION、UNION ALL、INTERSECT和MINUS。

多条作集合操作的SELECT语句的列的个数和数据类型必须匹配。

MINUS

MINUS函数获取两个结果集的差集。只有在第一个结果集中存在,在第二个结果集中不存在的数据,才能够被显示出来。也就是结果集一减去结果集二的结果。

DML

SELECT INTO

语句形式为:SELECT vale1, value2 into Table2 from Table1

要求目标表Table2不存在,因为在插入时会自动创建表Table2,并将Table1中指定字段数据复制到Table2中。示例如下:

INSERT INTO SELECT

(1)要求目标表Table2必须存在,并且字段field,field2…也必须存在

(2)注意Table2的主键约束,如果Table2有主键而且不为空,则 field1, field2…中必须包括主键

(3)注意语法,不要加values,和插入一条数据的sql混了,不要写成:

MERGE

INSERT FIRST

有氧训练的适应

有氧训练的基础适应

在有氧训练中,身体通过改变生理系统的过程来产生适应,以下表格是未经训练的人通过有氧训练产生的反应:

指标 反应
最大摄氧量 升高
安静心率 下降
运动心率(次最大) 下降
最大心率 不变或少量下降
动静脉氧差 升高
脉搏输出量 升高
心输出量 升高
收缩血压 不变或少量上升
肌肉的氧化能力 升高

重复的有氧运动的全部适应就是使身体更加有效,使得在每种水平的活动中,所有与器官所做的努力减少。

心血管系统的变化

心血管系统由两个部分组成: 心脏和血管。

急性适应和慢性适应

急性适应

在运动中,心脏的兴奋性增加,为所需的身体部分提供血液。尽管这不是血流增加的唯一原因,但是有一种简单的解释,就是通过交感神经系统和副交感神经系统分别释放神经递质(肾上腺素、去甲肾上腺素和乙酰胆碱)来改变心脏的兴奋性。

慢性适应

心血管在有氧耐力训练中出现,变化是慢性的,心脏变得肥大,与抗阻训练中肌纤维的肥大类似。需要注意的是,训练引起的心脏大小的变化与年龄和性别都没有关系。

与长期有氧运动有关的最显著的改变就是安静状态下的平均心率值(静息心率)和运动时的最大心率值,训练大约两周后心率值就会降低。

身体代谢的变化

神经系统与骨骼的变化

有氧运动引起的神经系统的变化主要是适应类型发生改变,而不是神经元、运动单位等等的数量增加,所观察到的变化是长时间产生的适应。与抗阻训练一样,神经生理学的变化与有氧运动直接相关。

有氧运动引起骨骼发生的变化不多,其中最通常涉及到的就是骨矿密度的增加和关节软骨的变化。其中骨矿密度的变化则更为重要,尤其是鉴于骨矿含量随着衰老而减少的事实,随着年龄的增长,骨矿密度减少,随之而来的就是骨损伤(骨折)出现的概率增加。

影响有氧运动适应性的因素

遗传因素

每个人从出生开始就规定了理论上的运动能力上限,这个上限不是绝对的,而是一个范围的某一点,这个点的高低取决于训练刺激和积极性大小。但是,似乎都有一个不能超越的绝对值,是有遗传因素决定的。

性别

年龄

停训

抗阻训练的适应

肌肉系统

骨骼肌简介

肌肉的宏观结构和组织

肌肉的微观结构和排列

细肌丝和粗肌丝的排列

肌丝滑动理论: 肌肉如何进行收缩

肌肉收过的启动

肌肉活动的终止

肌纤维的类型

各种人群中肌纤维的分布

##神经组织

神经纤维

神经冲动、去极化和动作单位

神经肌肉接点

本体感受器

骨骼系统

骨骼系统是由200多块骨通过关节来连接组成的,为肌肉和器官提供支持和基础。中轴骨包含颅骨,椎骨,脊柱,胸骨和肋骨。四肢骨包括肩带、胳膊、腿和臀。骨的形状与它们的功能和承受的负荷有关。

骨组织的类型

骨组织是活跃的、有生命的组织,由两种类型组成:

  • 密质骨:密质骨的特点是矿物质和细胞排列在哈佛氏系统中,哈佛氏系统占骨量的80%,并且位置朝向最外面一层。
  • 松质骨:松质骨是多孔的,有很多枝杈叫做骨小梁行程格子状的排列。这种多空的骨组织可以容纳骨髓和脂肪,还为骨的力量提供了微观结构。不同骨中骨密质和骨松质的百分含量不同。

骨组织的主要功能

骨组织的功能可以分结构功能和生理功能:

  • 结构功能:从结构上看,骨骼系统是身体运动和保护内脏器官的基础。
  • 生理功能:从生理上看,骨组织行程红细胞和白细胞,具有造血的作用。

另外,骨是存储钙和磷的地方,这些看,矿物质是神经传导,肌肉活动,心脏收缩,血液凝固和行程能量的基础。由于松质骨和密质骨不同的组成成分,所以密质骨最适合用于结构支撑,而松质骨则最适合用于骨的生理功能。

骨的生长和重建

骨的健康

  1. 骨矿密度大量减小导致骨功能减弱,具有骨折的危险性。
  2. 骨折最容易发生的部位是臀部、脊柱和腕部。
  3. 骨矿密度与长期的体育活动密切相关。
  4. 运动可以通过增加力量有助于预防骨折。

结缔组织

人体含有无数个组织。结缔组织对私人教练具有很大的意义,不管健身教练是否带训练班,不管在那里进行力量和伸展练习,都需要了解结缔组织相关的内容。

肌腱

肌肉与骨通过更有力的组织(肌腱)相连,肌腱将肌肉产生的张力传递给骨,从而引起运动。

肌腱的主要组成部分是胶原蛋白,以波浪式的方式成束排列,它是一种没有弹性的组织。是人体内所含的最多的蛋白质,是所有生命组织的一个结构成分。

肌腱的另一个组成成分是底物,底物是非纤维物质,由几种不同的分子组成,可以结合起来形成更加稳固而坚硬的结构。

韧带

韧带将骨和骨相连,为关节提供支撑。因此与肌腱不同的是,韧带附着在骨的末端。韧带的组成与肌腱相似,胶原束平行排列。

韧带具有一定的伸展性,一旦拉力消失就能回到原始的长度,这个特点为关节的支撑和顺应力提供了一种平衡。

弹性蛋白是一种非常复杂的生化物质,使韧带具有一定的伸展性,具有恢复原始长度的能力。

筋膜

从解剖学来看,筋膜是一个广义的名词,用来形容所有不具有特殊名称的结缔组织。筋膜的形状和厚度根据功能需要有很大的变化范围。

共有三种类型的筋膜:

  • 浅筋膜:或称(外层筋膜),位于皮肤下,这种双层组织所含的脂肪数据量不定,皮肤的可移动性是由浅筋膜提供,下面是深筋膜。
  • 深筋膜:深筋膜比浅筋膜更紧凑更坚硬,深筋膜与肌肉和骨骼相连,它可以将内脏器官和肌肉进行分离。
  • 浆膜:浆膜是最深层次的筋膜,它是一种浆液状的,含有液体的膜,直接覆盖在内脏器官的表面。[心包膜宝绕心脏,也是一种浆膜]

肌肉中的所有结缔组织(包括肌纤维膜、肌内膜、肌束膜、肌外膜)都是筋膜的类型,根据存在部位具有特殊的名称。

筋膜具有的三种类型的功能:

  • 首先:它形成了肌肉内的框架,连接肌肉并且保护它的稳定性。
  • 第二:使肌肉产生的力能够安全有效的得到传递。
  • 最后:他在各种器官和组织之间提供了必要的绝缘性,发挥它们独特的功能,同事不受相连结构的干扰。

生成Model层代码

1
2
3
bee generate scaffold City \ 
-fields="Id:int64,Name:string,CountryCode:string,District:string,Population:string" \
-conn="root:root@tcp(127.0.0.1:3306)/world"