Mac下vim安装taglist

1 安装taglist

taglist的安装非常简单。从vim官网的这个链接http://www.vim.org/scripts/script.php?script_id=273,就可以下载到taglist的最新版。将下载得到的taglist_xx.zip文件解压,可以得到两个文件夹:

doc/
plugin/

把这两个文件夹拷贝到 ~/.vim/ 目录下(如果~/.vim/ 目录下已有这两个文件夹,那把文件夹里面的内容拷过来就可以)。然后编辑~/.vimrc,添加如下几行:

filetype on
let Tlist_Ctags_Cmd = '/usr/bin/ctags'

2 开始使用

完成上述的安装步骤之后,进入vim,执行命令生成帮助标签:

:helptags ~/.vim/doc 

然后你可以通过这个命令来查看帮助了:

:help taglist.txt

现在我们随便用vim打开一个代码文件,然后执行

:TlistOpen

你会看到这样的报错:

%e5%b1%8f%e5%b9%95%e5%bf%ab%e7%85%a7-2016-09-22-%e4%b8%8b%e5%8d%8810-39-55

如果根据提示按ENTER,就会出现一个显示tags的侧边栏,但并没有预期的内容显示

%e5%b1%8f%e5%b9%95%e5%bf%ab%e7%85%a7-2016-09-22-%e4%b8%8b%e5%8d%8810-40-53

3 解决Mac的问题

出现上面的问题是因为Mac虽然自带了ctags程序,但是和taglist插件需要的ctags并不相同。我们需要下载一份ctags,然后自己编译(这里需要XCode的comman-line tool)。

首先去ctags官网http://ctags.sourceforge.net/下载一份ctags源码,解压后用以下命令编译:

./configure
make -j4

make命令执行完后,会在当前文件夹生成名为ctags的可执行文件,为了与系统自带的ctags区分开,我们把它重命名为my_ctags,并放到/usr/local/bin/

mv ctags my_ctags
cp my_ctags /usr/local/bin/

然后来修改~/.vimrc,将taglist所需要用到的ctags改成我们刚刚编译好的那个:

let Tlist_Ctags_Cmd = '/usr/local/bin/my_ctags'

现在,重新用vim打开一个源码文件,并执行:TlistOpen,如图,现在就能完整的看到taglist了:

%e5%b1%8f%e5%b9%95%e5%bf%ab%e7%85%a7-2016-09-22-%e4%b8%8b%e5%8d%8810-50-16

[译] Spring 入门 – 通过 JPA 访问数据

原网页:https://spring.io/guides/gs/accessing-data-jpa/

你将构建

你将构建一个应用,它会保存Customer这个POJO(简单Java对象)到内存数据库中

你将需要

如何完成这个指南

如同大多数的Spring入门指南,你可以从头开始并完成每一个步骤,或者可以跳过这个你已经熟悉的基本配置过程。无论哪种方式,您最终会获得可运行的代码。

从头开始,请看“使用Gradle构建”部分。

跳过最基本的部分,按下面的步骤操作:

  • 下载然后解压本项目的代码,或者使用Git克隆一个代码仓库:
    git clone https://github.com/spring-guides/gs-accessing-data-jpa.git
  • cd 到 gs-accessing-data-jpa/initial 目录
  • 直接跳到“定义一个简单实体

当你完成这些后,你可以把你的结果与gs-accessing-data-jpa/complete目录中的代码进行对比。

使用Gradle构建

首先,你要创建一个基本的构建脚本。你可以使用任何你喜欢的构建系统来构建Spring应用程序,但是你所需要的Gralde和Maven构建代码已经包含在这里了。如果你对两者都不熟悉,可以参考“使用Gradle构建Java项目”或“使用Maven构建Java项目”。

创建目录结构

你需要在你选的一个用作项目目录的文件夹中,创建下面的子目录结构;例如你可以在*nix系统中使用mkdir -p src/main/java/hello这样的命令来完成。

└── src
    └── main
        └── java
            └── hello

创建Gradle的build文件

下面是initial目录下的Gradle的build文件(译注:实际这个initial指的是项目的根目录,它包含了上面所创建的src目录,以及gradle.build文件,这样执行gradle build命令时,gradle才能正确地找到要构建的代码)。

文件名:build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.5.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'

jar {
    baseName = 'gs-accessing-data-jpa'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
    maven { url "https://repository.jboss.org/nexus/content/repositories/releases" }
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile("com.h2database:h2")
    testCompile("junit:junit")
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.3'
}

Spring Boot Gradle 插件提供了许多有用的功能:

  • 它收集classpath下的所有的jar包,构建为一个单独的“超级jar包”,使你的服务在传输和运行上变得更方便。
  • 它自动搜索包含public static void main()的类,并标记为运行的入口。
  • 它提供了一个嵌入式以来解决方案,预设了一些符合“Spring Boot 依赖关系”的版本号。你也可以用自己的版本号来覆盖它们,如果没有覆盖,那么最终会用Boot默认选择的版本。

使用Maven构建

使用IDE构建

定义一个简单实体

在这个例子中,你需要保存一个被标记为JPA实体的Customer对象。

文件名:src/main/java/hello/Customer.java

package hello;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
    private String firstName;
    private String lastName;

    protected Customer() {}

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return String.format(
                "Customer[id=%d, firstName='%s', lastName='%s']",
                id, firstName, lastName);
    }

}

这样你就有了一个带有idfirstNamelastName三个属性的Customer类。另外还有两个构造器。默认的(第一个)构造函数只为了提供给JPA使用,你不会直接用到它,所以他被声明为protected。另一个构造器就是你用来创建Customer实例并存入数据库的。

注:在本指南中,getter和setter都因篇幅限制而省略

Customer类被标注了@Entity注解来声明这是个JPA实体。因为缺少一个显式的@Table注解,根据约定这个实体会被映射到名为Customer的表中。

Customer类的id属性被标注了@Id注解,这样JPA会知道这是对象的ID。id属性同样被标注了@GenetaredValue注解来向JPA声明这个对象的ID应该被自动生成。

另外两个属性firstNamelastName没被标注。根据约定这两个属性将被映射为Customer表的列。

最后,toString()方法提供了一个很方便的方式将Customer的属性打印出来。

创建一个简单的查询

Spring Data JPA聚焦在使用JPA保存数据到关系数据库。它最引人瞩目的特点是具有在运行时通过repository api自动创建repository的实现的能力。

为了看到它们如何工作,我们来创建一个与Customer类一起工作的repository。

文件名:src/main/java/hello/CustomerRepository.java

package hello;

import java.util.List;

import org.springframework.data.repository.CrudRepository;

public interface CustomerRepository extends CrudRepository<Customer, Long> {

    List<Customer> findByLastName(String lastName);
}

CustomerRepository扩展了CrudRepositoryCustomerLong作为实体和id的传递给了CrudRepository。通过扩展CrudRepositoryCustomerRepository继承了多个方法来完成Customer的持久化工作,其中包括保存、删除和寻找Customer实体。

Spring Data JPA 还可以通过简单地声明他们的方法签名定义其他的查询方法。就像在这个CustomerRepository中的findByLastName()方法一样。

在一个典型Java应用程序中,你会需要写一个CustomerRepository类的实现。但这也是Spring Data JPA 的强大之处:现在你不需要再根据这个repository接口写一个CustomerRepository类的实现了。Spring Data JPA在会运行程序时为你做这些事。

让我们把他们连接起来看看怎么样。

创建Application类

现在你要创建一个Application类,带上其他所有的组件。

文件名:src/main/java/hello/Application.java

package hello;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

    private static final Logger log = LoggerFactory.getLogger(Application.class);

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }

    @Bean
    public CommandLineRunner demo(CustomerRepository repository) {
        return (args) -> {
            // save a couple of customers
            repository.save(new Customer("Jack", "Bauer"));
            repository.save(new Customer("Chloe", "O'Brian"));
            repository.save(new Customer("Kim", "Bauer"));
            repository.save(new Customer("David", "Palmer"));
            repository.save(new Customer("Michelle", "Dessler"));

            // fetch all customers
            log.info("Customers found with findAll():");
            log.info("-------------------------------");
            for (Customer customer : repository.findAll()) {
                log.info(customer.toString());
            }
            log.info("");

            // fetch an individual customer by ID
            Customer customer = repository.findOne(1L);
            log.info("Customer found with findOne(1L):");
            log.info("--------------------------------");
            log.info(customer.toString());
            log.info("");

            // fetch customers by last name
            log.info("Customer found with findByLastName('Bauer'):");
            log.info("--------------------------------------------");
            for (Customer bauer : repository.findByLastName("Bauer")) {
                log.info(bauer.toString());
            }
            log.info("");
        };
    }

}

@SpringBootApplication是个方便的注解,自动添加了所有以下内容:

  • @Configuration标记这个类作为bean以定义应用程序上下文的来源。
  • @EnableAutoConfiguration告诉SpringBoot开始添加基于classpath设置,其他Beans,以及各种属性设置的Beans。
  • 通常情况下你会给Spring MVC应用加上@EnableWebMvc注解,但当Spring Boot看到classpath中有spring-webmvc时,会自动添加这个注解。这标记该应用程序是一个Web应用程序,并激活一些关键行为,比如创建一个DispatcherServlet
  • @ComponentScan告诉Spring去hello包中寻找其他组件,配置,服务。

Application类包括了一个main()函数,并加入了一些测试数据到CustomerRepository中。首先它从应用上下文中获取到CustomerRepository,然后它通过展示save()方法,创建了一些测试数据,来保存了几个Customer对象。然后调用findAll()来从数据库中获得所有的Customer对象。接着调用findOne()来通过ID获取一个单独的Customer对象。最后,它调用findByLastName()方法找到了所有lastName 为 “Bauer”的Customer对象。

注意:默认情况下,Spring Boot会启用JPA repository支持,并扫描package(和他的下级package)来确认@SpringBootApplication的位置。如果你在一些不可见的package中配置有JPA repository 接口的定义,你可以用@EnableJpaRepositories注解,和他的类型安全的参数:basePackageClasses=MyRepository.class 来指出这个package。

构建一个可执行的JAR包

如果你正在使用gradle,你可以使用./gradlew bootRun命令来运行应用程序。

你可以构建一个包含所有必要的依赖,类和资源的一个可执行的JAR文件。这样使传输,版本管理和部署服务在整个开发生命周期在不同的环境,等等,变得更容易

./gradlew build

然后你可以这样运行JAR包:

java -jar build/libs/gs-accessing-data-jpa-0.1.0.jar

如果你正在使用Maven,你可以通过mvn spring-boot:run来运行应用,或者你也可以通过mvn clean package来构建JAR包,然后输入下面的命令来运行:

java -jar target/gs-accessing-data-jpa-0.1.0.jar

注意:上述过程将创建一个可运行的JAR。你也可以选择构建一个经典的WAR包来代替。

你将会看到这样的输出:

== Customers found with findAll():
Customer[id=1, firstName='Jack', lastName='Bauer']
Customer[id=2, firstName='Chloe', lastName='O'Brian']
Customer[id=3, firstName='Kim', lastName='Bauer']
Customer[id=4, firstName='David', lastName='Palmer']
Customer[id=5, firstName='Michelle', lastName='Dessler']

== Customer found with findOne(1L):
Customer[id=1, firstName='Jack', lastName='Bauer']

== Customer found with findByLastName('Bauer'):
Customer[id=1, firstName='Jack', lastName='Bauer']
Customer[id=3, firstName='Kim', lastName='Bauer']

小结

恭喜,你已经写出了一个简单的使用Spring Data JPA来保存、取出对象的应用——关于repository的实现,一点代码也没有。

注意:如果你对暴露JPA在超媒体的RESTful前段下感兴趣,你可能会想阅读《用REST访问JPA数据

spring如何让thymeleaf不使用XML来解析页面

thymeleaf 实际使用中的问题

在基于spring的web开发中,如果需要使用模板引擎,一般都会选择thymeleaf。thymeleaf在实际使用中有一个问题,前端开发人员一般使用html标准来开发前段页面,html标准容错性高,不要求所有标签都必须闭合,但是thymeleaf在解析页面时使用的是xml标准,它要求所有标签都闭合,因此如果写出了这样的标签,thymeleaf就会报错:

<meta charset="UTF-8">

错误代码如下:

016-09-15 01:13:49,708 ERROR ErrorHandler:57 - [THYMELEAF][qtp1944815218-15] Fatal error during parsing
org.xml.sax.SAXParseException; lineNumber: 6; columnNumber: 3; 元素类型 "meta" 必须由匹配的结束标记 "</meta>" 终止。
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)

必须将meta标签闭合,也就是改成这样:

<meta charset="UTF-8"></meta>

另外,如果你在页面中内嵌了JavaScript,也可能会遇到js代码被thymeleaf解析而失效的情况。

解决方案

看起来,thymeleaf好像是一个及其难用的模板引擎?实际上,这并不是thymeleaf的一个问题,而是“设计成这样”——thymeleaf会将输入的内容解析成标准的XML(参考这里的讨论)。

实际上要解决这个问题也很简单,只需要添加一个nekohtml的依赖就可以了。

首先在Gradle中添加这一条依赖:(用Maven的同学请自行改写):

dependencies {
    compile("net.sourceforge.nekohtml:nekohtml:1.9.21")
}

然后在application.yml中添加如下配置:

spring:
    thymeleaf:
            mode: LEGACYHTML5
                cache: false

然后你就可以大胆的写不闭合的标签了。至于内嵌的JavaScript解析问题,我建议所有的js代码都从外部引用,这是个好习惯。

thymeleaf 3

我们刚刚说的其实是thymeleaf 2,因为"org.springframework.boot:spring-boot-starter-thymeleaf"这个包中包含的thymeleaf版本是2.1.4。

在thymeleaf 3中,HTML作为新的模板类型开始被支持,因此也不会检查标签是否闭合。你可以参考这篇迁移指南来了解怎样从thymeleaf 2升级到thymeleaf 3。

[译] Spring Session 与 Spring Security

原文:http://docs.spring.io/spring-session/docs/current-SNAPSHOT/reference/html5/guides/security.html

本指南介绍如何将Spring Session与Spring Security一起使用。它假定您已经应用Spring Security到您的应用程序。

完整的指导可以在这里找到。

更新依赖

你用Spring Session之前,你必须确保更新你的依赖。如果你正在使用Maven,确保添加以下依存关系:

文件名:pom.xml

<dependencies>
        <!-- ... -->

        <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
        <version>1.3.0.BUILD-SNAPSHOT</version>
        <type>pom</type>
        </dependency>
        <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.2.5.RELEASE</version>
        </dependency>
</dependencies>

由于我们使用的是快照版本,我们需要确保添加Spring快照Maven仓库。确保你的pom.xml包含如下内容:

文件名:pom.xml

<repositories>

        <!-- ... -->

        <repository>
        <id>spring-snapshot</id>
        <url>https://repo.spring.io/libs-snapshot</url>
        </repository>
</repositories>

Spring 配置

添加必需的依赖关系之后,我们就可以开始创建Spring配置。Spring配置负责创建一个Spring Session实现的Servlet过滤器来取代HttpSession实现的过滤器。增加如下Spring配置:

@Configuration
@EnableRedisHttpSession 
public class Config {

        @Bean
        public JedisConnectionFactory connectionFactory() {
                return new JedisConnectionFactory(); 
        }
}
  1. EnableRedisHttpSession创建了一个名为springSessionRepositoryFilter的Spring Bean来实现过滤器。这个由Spring Session实现的过滤器是负责替换HttpSession的实现。在这种情况下,Spring Session由redis支持。

  2. 然后创建了一个RedisConnectionFactory来连接Spring Session到地址是localhost,端口为6379的redis服务器。更多关于配置Spring Data Redis的信息可以参考这个文档

Servlet Container 初始化

上面的Spring 配置创建了一个名为springSessionRepositoryFilter的Spring Bean,为了让我们这个过滤器生效,Spring需要加载这个Config类。

由于我们的应用已经使用SecurityInitializer来加载Spring的配置,我们可以简单地把Config类加进去:

文件名:SecurityInitializer.java

public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {

        public SecurityInitializer() {
                super(SecurityConfig.class, Config.class);
        }
}

最后我们需要确保Servlet Container(如Tomcat)为每一个请求用上我们的springSessionRepositoryFilter。确保Spring Session的springSessionRepositoryFilterspringSecurityFilterChain之前调用非常重要,幸运的是,Spring Session提供了一个叫做AbstractHttpSessionApplicationInitializer的工具类让这件事变得超级容易。你可以按下面这么写:

文件名:Initializer.java

public class Initializer extends AbstractHttpSessionApplicationInitializer {

}

类的名字(Initializer)并不重要,重要的是我们继承了AbstractHttpSessionApplicationInitializer

通过继承AbstractHttpSessionApplicationInitializer类,我们确保了springSessionRepositoryFilterspringSecurityFilterChain之前调用。

Security 示例程序

运行 Security 示例程序

你可以获取源码,输入下面的命令,来运行 Security 示例程序。

为了让示例程序正常工作,你必须安装Redis 2.8+在本地(localhost),并运行在6379端口。或者,你也可以修改JedisConnectionFactory来指定一个Redis服务器

$ ./gradlew :samples:security:tomcatRun

现在你应该可以访问http://localhost:8080/

访问 Security 示例程序

试着开始用这个Web应用,输入下面的用户名密码来登录:

  • 用户名user
  • 密码password

接着点击“login”按钮,你应该能够看到一个提示你已经用user登录的消息。用户的登录信息此时保存在Redis中而不是Tomcat所实现的HttpSession中。

它是如何工作的

我们实际上是在持久化登录信息到Redis中,而不是Tomcat所实现的HttpSession。Spring Session代替了HttpSession,并使用Redis来存储数据:当Spring Security的SecurityContextPersistenceFilter保存SecurityContextHttpSession对象中时,他就会被持久化到Redis里。

对于Spring Security来说,当一个新的HttpSession被创建,Spring Session生成了一个名为SESSION的cookie发送到你的浏览器,它包含了这个Session的id。你可以到浏览器中看到这个Cookie(这里有ChromeFirefox关于Cookie的帮助)。

如果你愿意,你可以很容易用redis-cli从Redis中删掉刚才生成的Session。比如,在一个类Linux系统中你可以这么操作:

$ redis-cli keys '*' | xargs redis-cli del

Redis的文档中有说明如何安装redis-cli

或者,你也可以指定去删除某个key。例如输入下面的命令:

$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e

现在访问http://localhost:8080/,你会发现刚才的登录认证已经取消了。

[译] Spring入门 – Web应用程序安全

原网页 https://spring.io/guides/gs/securing-web/

本指南将引导您完成创建一个资源由Spring Security的保护的一个简单的Web应用程序的过程。

你将构建

你将构建一个通过固定的用户列表作为后端的登录表单来保护页面安全的Spring MVC应用程序

你将需要

  • 大约15分钟
  • 一个喜欢的文本编辑器或IDE
  • JDK 1.8 或更高版本
  • Gradle 2.3+ 或 Maven 3.0+
  • 你同样可以将本指南的代码直接导入Spring Tool Suite (STS)并从这里开始你的工作

如何完成这个指南

如同大多数的Spring入门指南,你可以从头开始并完成每一个步骤,或者可以跳过这个你已经熟悉的基本配置过程。无论哪种方式,您最终会获得可运行的代码。

要从头开始,请看“使用gradle构建”部分。

要跳过最基本的部分,按下面的步骤操作:

  • 下载然后解压本项目的代码,或者使用Git克隆一个代码仓库:
    git clone https://github.com/spring-guides/gs-securing-web.git
  • cd 到 gs-securing-web/initial 目录
  • 直接跳到“部署Spring Security

使用gradle构建

首先,你要创建一个基本的构建脚本。你可以使用任何你喜欢的构建系统来构建Spring应用程序,但是你所需要的Gralde和Maven构建代码已经包含在这里了。如果你对两者都不熟悉,可以参考“使用Gradle构建Java项目”或“使用Maven构建Java项目”。

创建目录结构

你需要在你选的一个用作项目目录的文件夹中,创建下面的子目录结构;例如你可以在*nix系统中使用mkdir -p src/main/java/hello这样的命令来完成。

└── src
    └── main
        └── java
            └── hello

创建Gradle的build文件

下面是initial目录下的Gradle的build文件(译注:实际这个initial指的是项目的根目录,它包含了上面所创建的src目录,以及gradle.build文件,这样执行gradle build命令时,gradle才能正确地找到要构建的代码)。

文件名:build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.5.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'

jar {
    baseName = 'gs-securing-web'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile("org.springframework.boot:spring-boot-starter-thymeleaf")
    testCompile("junit:junit")
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.3'
}

使用maven构建

略,请参考原文

使用IDE构建

略,请参考原文

创建一个不安全的Web应用

在你可以尝试将安全性应用于Web应用之前,你需要一个用于“保护”的Web应用程序。本节中的步骤指导您完成创建一个非常简单的Web应用程序。然后你将在下一节使用Spring Security将其保护起来。

这个web应用程序包括两个简单的视图,一个是“主页”,一个是“Hello World”页。“主页”的视图由下面这个themeleaf模板来定义:

文件名:src/main/resources/templates/home.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example</title>
    </head>
    <body>
        <h1>Welcome!</h1>

        <p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
    </body>
</html>

如你所见,这个简单的视图包括一个指向“/hello”页面的链接,它由下面这个themeleaf模板来定义:

src/main/resources/templates/hello.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Hello World!</title>
    </head>
    <body>
        <h1>Hello world!</h1>
    </body>
</html>

这个Web应用基于Spring MVC,因此你需要配置Spring MVC,然后设置view controller来暴露这些模板。下面就是一个配置好Spring MVC的Class。

文件名:src/main/java/hello/MvcConfig.java

package hello;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/home").setViewName("home");
        registry.addViewController("/").setViewName("home");
        registry.addViewController("/hello").setViewName("hello");
        registry.addViewController("/login").setViewName("login");
    }

}

addViewControllers()方法(覆盖了WebMvcConfigurerAdapter的同名方法)添加了四个view controller。其中两个view controller指向了“home”视图(在home.html中定义),另一个指向了“hello”视图(在hello.html中定义)。第四个view controller指向另一个视图“login”,你将会在下个章节创建这个视图。

此刻,你可以直接跳到“让Web应用可执行”的部分,在不需要任何登陆工作的情况下运行Web应用。

一旦最基本的Web应用创建好了,你可以给他加上安全防护。

部署Spring Security

假设现在你希望防止未授权的用户在输入“/hello”这个网址后看到欢迎页的内容。当前状态下,如果用户点击“home”页上的链接,他们可以没有任何阻碍地看到欢迎页。现在你需要在用户看到这个页面前添加一个强制用户登录的阻碍。

你可以通过配置Spring Security来完成上面所说的事。如果Spring Security在classpath中,SpringBoot会自动使用“基本”HTTP认证来保护所有HTTP端点,你也可以进一步的定制安全设置。首先要做的事情就是把Spring Security加入到classpath中。

如果使用Gradle,它将会是dependencies部分中的一行:

文件名:build.gradle

dependencies {
    ...
    compile("org.springframework.boot:spring-boot-starter-security")
    ...
}

如果使用Maven,他将会是<dependencies>标签中的一个子标签:

文件名:pom.xml

<dependencies>
    ...
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    ...
</dependencies>

下面是确保只有认证过的用户才能看到“秘密的”欢迎页的安全配置:

文件名:src/main/java/hello/WebSecurityConfig.java

package hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
}

这个WebSecurityConfig类被@EnableWebMvcSecurity标注,来启用Spring Security的web安全支持、以及提供与Spring MVC的融合。这个类还继承了WebSecurityConfigurerAdapter并重写了一些方法来指定一些特定的Web安全设置。

configure(HttpSecurity)方法规定了哪个URL应该被保护,哪个不应该。具体而言,“/”和“/home”的路径被配置为不需要任何认证。所有其他URL必须进行身份验证。

当用户成功登录后,他们将被重定向到先前请求的需要身份验证的页面。还有一个自定义(由loginPage()指定)的“/login”页面,每个用户都可以查看。

对于configureGlobal(AuthenticationManagerBuilder)方法,它设置了一个单一用户在内存中的用户数据库。该用户被赋予“user”的用户名,“password”的密码,以及“USER”作为角色。

现在,我们需要创建登录页面。目前已经为“login”视图赋予了视图控制器,所以你只需要创建login视图本身:

文件名:src/main/resources/templates/login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example </title>
    </head>
    <body>
        <div th:if="${param.error}">
            Invalid username and password.
        </div>
        <div th:if="${param.logout}">
            You have been logged out.
        </div>
        <form th:action="@{/login}" method="post">
            <div><label> User Name : <input type="text" name="username"/> </label></div>
            <div><label> Password: <input type="password" name="password"/> </label></div>
            <div><input type="submit" value="Sign In"/></div>
        </form>
    </body>
</html>

正如你所看到的,这个Thymeleaf模板只是给出了一个采集用户名和密码,并将它们作为请求post到“/login”的表单。正如刚刚配置的,Spring Security提供一个过滤器,截取该请求,并验证用户身份。如果用户身份验证失败,页面被重定向到“/login?error”,我们的页面将显示相应的错误信息。一旦成功登出了,我们的应用程序重定向到到“/login?logout”并显示相应的登陆成功的消息。

最后,我们需要给用户提供一种方式来显示当前用户名和“Sign Out”按钮。更新hello.html来问好当前用户,并包含一个“Sign Out”的按钮,如下所示:

文件名:src/main/resources/templates/hello.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Hello World!</title>
    </head>
    <body>
        <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
        <form th:action="@{/logout}" method="post">
            <input type="submit" value="Sign Out"/>
        </form>
    </body>
</html>

我们通过使用Spring Security所集成的HttpServletRequest#getRemoteUser()来显示用户名。该“Sign Out”按钮提交一个POST请求给“/logout”。一旦成功退出,将用户重定向到“/login?logout”。

让Web应用可执行

虽然可以打包这项服务作为一个传统的web应用程序归档或WAR文件部署到外部应用服务器,下面展示了更简单的方法来创建一个独立的应用程序。你将打包一切到一个单一的,可执行的JAR文件中,用一个良好旧式Javamain()方法来调用。在此过程中,你会用到Spring所支持的嵌入式Tomcat servlet容器作为HTTP运行实例,而不是部署一个外部实例。

文件名:src/main/java/hello/Application.java

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) throws Throwable {
        SpringApplication.run(Application.class, args);
    }

}

@SpringBootApplication是个方便的注解,自动添加了所有以下内容:

  • @Configuration标记这个类作为bean以定义应用程序上下文的来源。
  • @EnableAutoConfiguration告诉SpringBoot开始添加基于classpath设置,其他Beans,以及各种属性设置的Beans。
  • 通常情况下你会给Spring MVC应用加上@EnableWebMvc注解,但当Spring Boot看到classpath中有spring-webmvc时,会自动添加这个注解。这标记该应用程序是一个Web应用程序,并激活一些关键行为,比如创建一个DispatcherServlet
  • @ComponentScan告诉Spring去hello包中寻找其他组件,配置,服务。

main()方法使用Spring Boot的SpringApplication.run()方法来启动应用程序。你有没有注意到,这里没有一行XML,同样也没有web.xml文件。这个Web应用程序是100%纯Java写的,你不必处理配置任何管道或基础设施(译注:plumbing or infrastructure,我这里直译了)。

构建一个可执行的JAR包

如果你正在使用gradle,你可以使用./gradlew bootRun命令来运行应用程序。

你可以构建一个包含所有必要的依赖,类和资源的一个可执行的JAR文件。这样使传输,版本管理和部署服务在整个开发生命周期在不同的环境,等等,变得更容易

./gradlew build

然后你可以这样运行JAR包:

java -jar build/libs/gs-securing-web-0.1.0.jar

如果你正在使用Maven,你可以通过mvn spring-boot:run来运行应用,或者你也可以通过mvn clean package来构建JAR包,然后输入下面的命令来运行:

java -jar target/gs-securing-web-0.1.0.jar

注意:上述过程将创建一个可运行的JAR。你也可以选择构建一个经典的WAR包来代替。

一旦应用程序启动,用浏览器访问http://localhost:8080。你应该看到主页:

home

当你点击这个链接,它会尝试把你带到/hello所指向的欢迎页,但因为这个页面是受保护的,而且目前为止你没有登录,它会带你到登陆页

login

注意:如果你是直接从“不安全”的版本跳到这的,那么你将不会看到登陆页,请放松地回到上面写完其余的基于安全的代码

在登录页面,分别输入“user”和“password”作为用户名和密码,即可作为测试用户登录。一旦你提交登录表单,你会被进行身份验证,然后带你到欢迎页:

welcome

如果你点击“Sign Out”按钮,你的身份验证被撤销,你将会返回到登录页并显示一个消息提示你已经登出。

小结

恭喜你,你已经开发了一个简单的、使用Spring Security来保护的Web应用。

想写一个新的指南,或向已有的指南贡献自己的能力?请看我们的贡献指南

基础算法的lua实现

二分查找

function BSearch(elements, x, low, high)
	local mid
	if(low>high) then
		return -1
	end

	mid = math.ceil((low+high)/2)
	if(x==elements[mid]) then
		return mid
	end

	if(x<elements[mid]) then
		return BSearch(elements, x, low, mid-1)
	end

	if(x>elements[mid]) then
		return BSearch(elements, x, mid+1, high)
	end
end

快速排序

function qsort(array, left, right)
	local i = left
	local j = right

	if(left >= right) then
		return array
	end

	local pivot = array[left]

	while(i < j) do
		while(i < j and array[j] > pivot)do
			j = j-1
		end
		if(i < j)then
			array[i] = array[j]
			i = i + 1
		end

		while(i < j and array[i] < pivot)do
			i = i + 1
		end
		if(i < j)then
			array[j] = array[i]
			j = j - 1
		end

		array[i] = pivot
	end
	qsort(array, left, i-1)
	qsort(array, i+1, right)

	return array
end

 

 

Awsome iOS Tools

ios7-weather-app-design

iOS开发工具集合
持续更新,欢迎推荐

Thrid-party libraries & SDKs

1、分享到社交网络:ShareKit
三行代码,搞定分享功能。当然,关于分享我推荐一种更“高大上”(或者更Apple-Styled)的做法:《iOS关于应用内分享

2、Lua解释器:LuaJIT-iOS-Framework
如果你想在App里内嵌一个胶水语言,我推荐你用Lua。基本的介绍可以看这里:《iOS下使用Lua进行编程》。另外,iOS7 SDK新加入了JavaScript解释器JavaScriptCore.framework,有兴趣你可以试一试——从此再也不用拿webView来解析JS啦。

Project Tools

1、图片资源压缩:ImageOptim
很多人可能用过PNGCrush、JPEGOptim等命令行工具来压缩App中的图片资源并保留透明度,现在ImageOptim对这些工具做了整合,所以你再也不用编写脚本去遍历你的工程目录、找出图片然后匹配对应的压缩工具了——用拖拽的方式把图片放进ImageOptim就可以。

注意,如果你的资源图片使用ImageOptim压缩过,那么请在将工程选项中的“Build Settings” -> “Compress PNG Files” 置为NO。

2、清理项目中不用的资源:xcodeutils
这是个命令行工具,作用就是找出那些你不调用的资源文件(代码、图片等),然后提示你把它从项目中清理出去。容易造成误删,谨慎使用。

Teamwork Tools

1、发布和测试工具:Testflight
最好用的On-The-Air发布和测试工具,那些说能做得比Testflight更好的都是骗人的。

2、代码托管、Bug跟踪:Gitlab
Github的一个第三方实现。免费、私有、开放API。我的实践是:通过git branches管理features、共同维护代码,通过gitlab进行pull和push。因为历史原因,我们用了redmine来做bug追踪,而实际上gitlab的”issues“就非常好用。

如果你安装了却不能用,请升级你的内存。

3、任务看板:Trello
用于团队成员之间同步工作进度。可以配合一种项目管理模式来使用,当然——前提是你的team人数多到需要用这个工具。可以参考这篇文章:《使用Trello实现敏捷项目管理

Lua对象的继承和反射

对象的继承
在《Progranming in Lua》中提到了一种继承Lua对象的方法

Object = {}

function Object:new (o)
	o = o or {}
	setmetatable(o, self)
	self.__index = self
	return o
end

function Object:hello()
	print("hello")
end

ExtendedObject = Object:new()
function ExtendedObject:hello()
	print("new hello")
end

obj1 = Object:new()
obj2 = ExtendedObject:new()
obj1.hello()
obj2.hello()

上面的代码完成了简单的面向对象和继承机制。此时如果在Object中定义一个函数hello,在ExtendedObject可以对其重载,改变hello函数的行为。比如上面obj2的hello()调用,打印出来的结果是”new hello”。

对象的反射
现在,在上面那段代码后面加上这些:

print("obj1 list members :")
for k,v in pairs(getmetatable(obj1)) do
    print(" ", k)
end

print("-------------------")

print("obj2 list members :")
for k,v in pairs(getmetatable(obj2)) do
    print(" ", k)
end

运行结果是这样的:

obj1 list members :
 	hello
 	__index
 	new
-------------------
obj2 list members :
 	hello
 	__index

getmetatable()的作用是返回一个table的元表(metatable)。这可以用来实现对象的反射机制:告诉调用者,我都有哪些方法和属性。但是这里的输出好像不对,obj2的Class虽然继承了obj1,但metatable打印出来的结果却不一样。这是因为 —— 他们的metatable确实不一样,但lua的运行机制在这里恰好实现了重载(override)的作用:如果ExtendedObject自己实现了方法hello,那么它的metatable中就能找到这个方法,也就可以直接调用。如果它未实现这个方法,就去查找__index所指向Class的metatable,也就是Object的metatable。

所以,如果你这样写:

for k,v in pairs(getmetatable(obj2.__index)) do
    print(" ", k)
end

得到的就是:__index, new, hello 三个属性。

近期技术汇总

1、KVO KVC 原理,isa swizzling
KVC/KVO原理以及isa swizzling http://hotfm.iteye.com/blog/1218402

2、ARC中的strong、weak
《iOS5 ARC学习笔记:strong、weak等详解》 http://mobile.51cto.com/iphone-386301.htm
llvm 关于 ARC的文档 http://clang.llvm.org/docs/AutomaticReferenceCounting.html

3、block and callback
http://beyondvincent.com/blog/2013/07/12/102/

示例代码gist:
https://gist.github.com/ziggear/9206330

4、autoreleasepool实现
关键字:
release count
对象栈
NSRunLoop
http://blog.sina.com.cn/s/blog_80b6100b01015vcm.html

5、GCD的实现
GCD 原理:队列与分发

-将一段(Block)代码作为特定任务,放到指定的队列(queue:Serial(串行,同时只能执行一个任务)/globel(并行,同时可执行多个任务,但执行顺序是随机的)/main(全局的Serial,在主线程里面执行任务) dispatch queue)里,进行同步/异步(dispatch_sync/dispatch_async)处理。根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。dispatch_sync/dispatch_async的意思就是将任务进行同步/异步并行处理,不一定需要一个任务处理完后才能处理下一个
-一个任务可以是一个函数(function)或者是一个block。 GCD的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节。
http://www.devdiv.com/gcd_-blog-316270-50758.html

6、#include #import @import
6.1 import与include的区别
这个语法要追溯到Objective-C的根:vanilla C。#import语句是预处理器指令和#include有类似的方式工作。唯一的区别是#import不会导入已经导入的头文件;它是一次性处理。

6.2 @import 的来源:
新的解决方案:模块 (Modules)
Modules第一次在Objective-C中公共露面是在2012 LLVM开发者大会上Apple’s Doug Gregor的一次谈话。这是一次迷人的谈话,强烈推荐给对编译感兴趣的人。

你可以在线看这些视频 http://llvm.org/devmtg/2012-11/#talk6

一个Modules不仅告诉编译器哪些头文件组成了Modules,而且还告诉编译器什么需要链接。这个就解救了你不用你去手动的链接框架。这虽然是一件小事,但是能让开发更加简单就是一件好事。

use like this:
@import UIKit;
@import MapKit;
@import iAd;

http://blog.csdn.net/joywii/article/details/12103327

7、iOS的几种非阻塞操作:
POSIX thread
NSThread(继承POSIX thread实现)
GCD
NSRunLoop (在主线程中且不阻塞UI)
(可以看看梦维的几篇讲iOS多线程的文档)

Programming Is Hard, Let’s Go Scripting… Part.2

编程太难,滚去写脚本 (第二部分)
原文:http://www.perl.com/pub/2007/12/06/soto-11.html
第一部分:http://blog.csdn.net/zh405123507/article/details/8968001

按:之前立志翻译多少多少文章,到最后果然还是一个project都没完成啊,在github上新建了好多repository也是一样initial commit之后就没有动过了…… 这个习惯不好,所以还是开始慢慢填之前挖下的坑吧。


Tcl
Perl之后是Tcl,某种意义上比Perl更纯粹的“脚本语言”。Perl只是为了图方便而把一切对象当做string来处理,而Tcl却真的把string用来作为调度的容器[译注 1],用string作为容器导致的一个糟糕后果就是性能低下 —— 当然这不是Tcl被大家抛弃的原因(译注:其实就是吧魂淡!),我认为Tcl被冷落主要有下面两个原因:
首先,Tcl还停留在Unix的使用心态下[译注 2] —— 控制工具而不是创造工具。所以语言不会做太多优化,毕竟那些最快的部分都是C写的。
然后,Tcl真没有一个像样的扩展机制,所以可以想象最终用户会因为不断地会有新的Tcl executable而放弃使用这种语言,例如他们开始用Incr-Tcl等机制之后。[译注 3]
但不得不说,我总是很佩服Tcl在语义中使用的代理机制,但是它和Lisp一样陷入了一个误区:它认为每个人都在使用“One True Syntax”[译注 4]。关于这个One True Syntax:

Python
Tcl之后我们来谈谈Python。与Guido的想法由ABC进行积极的激励不同,Python社区的人,他们的启发是因为对Perl的消极感受。然而我不是非常有资格来谈论Python,因为我只是窃取了它的对象机制用在了Perl 5里面(译注:呵呵……)—— 这是我一直后悔没加的东西。

Ruby
所以我更有资格谈论Ruby —— 那是因为很大一部分Ruby的代码是从Perl“借”过去的,并基于smalltalk的语义实现。我总是将Ruby视为Perl在生态链中的一个更为接近的对手,不只是因为他借走了Perl的一些想法,更重要的原因是,Perl和Ruby对函数式编程的支持相比Python之类的更为严谨。但是从另一方面考虑,Ruby因此毁了他的其余部分(函数式编程的支持之外的)声明语法。

*sh
与此同时,Bourne shell发展出Korn shell和bash两个衍生版。我没有在这两个东西上做什么工作 —— 谢天谢地我没有做什么。我只能这样说,shell的不断衍生是在告诉你这样不断地添加临时的语言特性最终会成为一个乱七八糟的语言。

PHP
我们也见证过PHP的崛起——它通过“Worse-is-better”的尝试[译注 5],达到了一个令人眼花缭乱(译注:似乎带有贬义)的高度。大体上,PHP正面临着与Perl相同的问题,只是进展的更慢一些。有一件事PHP能做得更好,那就是packaging——嗯你知道我不是在讨论namespace。

Python and PHP
译注:为什么这里有这张图呢?因为上面既有Python(蟒蛇),又有PHP(大象)哈哈哈哈……

Javascript
然后我们来讲Javascript,超级nice的设计。虽然目前来看还有些需要解决的问题,但没关系,Javascript最后肯定会被证明是一个用来运行Perl6的绝好的平台!Pugs[译注 6]已经有能将Perl编译成Javscript代码的后端(译注:我勒个去…… 这个技术太厉害了!),即使这项技术在去年发生了一些bitrot[译注 7]……

Monad/PowerShell
我特意关注了一下大硬公司的莫纳德[译注 8],我很高兴地想强调莫纳德想Perl 6一样拥有基于对象的管道机制(object pipe)[译注 9],我只希望他们不要为这玩意儿申请专利……

Lua/AppleScript
这些脚本语言被使用在更广泛的领域,哦很抱歉,我必须承认我就是没用过这些语言,因为我不为游戏写代码,也没有Mac[译注 10]。

其实嘛,我认为这两个语言在各自领域都有(比我所了解到的)更深的作为,并且在当前这个环境下都能体现出来。

所谓当前环境
我所观察到的当前环境,我们看到的这些脚本语言和他们的社区就像丛林里面的各个部落,而根据各个部落的衍生关系,他们之间有时进行着“交易”,有时进行着“战争”,但大体上他们之间互相都保持着距离。
(译注:Linux发展至今,许许多多的衍生版之间也是这样的关系,读者可以意会一下 :) )

我更倾向于用这种人类学的理论来看待这些事。你们许多人都应该是Perl程序员,但也有一些来自别的语言的“部落”,而根据你们的部族历史,C程序员会将一个string类型看做占1byte的指针,函数型编程的程序员会把它看做一个列表,而java程序员会把它当做对象(Java程序员自语:说指针的自重,老子的世界没有指针)。我,会把string看做Text,一个大写的“T”。

所谓Text
我会从后现代视角看待Text这个词。当然 —— “后现”代这个术语本身是上下文敏感的。一些家伙认为后现代主义是对庸俗授予权力,另一些家伙认为:这他妈就是Perl的哲学。

但是我用后现代主义来看Text,无论是口语上还是书面上,它是一种要求两端都具有智力的端对端的传达工具,有时他甚至需要传输介质也有智力才行。我才不想和一个SB的编程语言对话,我希望我的编程语言能理解我所输入的(所有的)string(译注:也就是前面提到的Text)。

话说回来,Perl就是个后现代语言。但许多保守的人认为后现代是个相当自由的概念。所以相当讽刺的是,我对后现代主义的观点主要来自于传教士所教的语言学和翻译 —— 具体而言,就是威克理夫圣经的翻译。他们所灌输的一件事是:真的没有一种叫做“人类的原语言”的东西 —— 意思就是人类的所有语言都是图灵完备的。[译注 11]

所以当你出发去寻找所谓的“原始部落”然后分析他们的语言(译注:这里应该指的是scripting language的原始部落),你会发现他们在结构上就像人类语言一样复杂。基本上,如果你研究的足够长时间,你可以用任何一种人类的语言表达任何事情。人类的语言是图灵完备的,因为他本来就是完备的(译注:所以为们也把Human language成为“自然语言”)。

因此,人类语言的不同之处不(那么)在于你可以说些什么,而在于你必须说成什么形式。在英语中,你必须区分单复数形式;在日语中,你不必区分单复数,但你必须从语言上体现你对谈话者的尊重程度,以及你对所提及人和事的尊重程度。

所以语言之间的区别在于那些你必须去表达的部分。显然,如果你的语言必须让你表达,你就不能在一定程度上精简地使用它 —— 让我们回到脚本语言:

  • 在不同的脚本语言中,都有哪些方法是可以进行精简的?
  • (换句话说)在俄罗斯的菜谱中,罗宋汤有多少种做法?
  • 语言的设计者在许多维度上都有操纵这些的自由,让我来谈谈其中的几个维度……

( ** 译注:终于到本文的关键部分了……让我再挖个坑吧,敬请期待《编程太难,滚去写脚本 (第三部分)》,O(∩_∩)O谢谢 ** )


译注:
1、这段翻译的不明确,原文:“Perl just pretends that everything is a string when it’s convenient, but Tcl really believes that as a controlling metaphor. ”

2、Mindset —— 心态 —— 被翻译为“使用心态”,是指语言使用某些工具的态度,参见下文,而不是用户的操作心态

3、Incr Tcl是Tcl编程语言的面向对象编程的扩展包,Wiki:http://zh.wikipedia.org/zh-cn/Incr_Tcl

4、One True Syntax 是什么?我也不知道,这篇文章里的专用名词很多都难以考证了

5、Worse-is-better ,是相对UNIX的使用哲学“Do the right thing”提出的另一种观点。详情可参考:http://www.jwz.org/doc/worse-is-better.html (中文:http://www.aqee.net/the-rise-of-worse-is-better/

6、Pugs是Perl 6的一个编译器和解释器,目的是通过bootstrap技术实现使用Perl设计Perl的编译器,使之能够将Perl语言编写的代码生成Haskell、Javascript等代码(Wiki: http://en.wikipedia.org/wiki/Pugs

在编译器领域中,bootstrap技术(并不是Twitter的那套bootstrap -__-# )指的是使用待编译语言来设计编译器。例如用C语言设计一个C语言的编译器,这就是bootstrap。目前实现这种技术的语言有 BASIC, ALGOL, C, Pascal, PL/I, Factor, Haskell, Modula-2, Oberon, OCaml, Common Lisp, Scheme, Java, Python, Scala, Nimrod, Eiffel, 等等……

7、bitrot = bit rot , Bit rot, also bit decay, data rot, or data decay, is a colloquial computing phrase for the gradual decay of storage media or a (sometimes jocular) explanation for the degradation of a software program over time, even if “nothing has changed”.(抱歉这段太TM深奥了,Wiki:http://en.wikipedia.org/wiki/Bit_rot

8、Microsoft Monad,是Windows PowerShell项目的代号。目的是提供比CMD更强大的命令行和自动化工具,据称Monad被称为是“The Future of Windows Scripting”。呵呵。

9、基于对象的管道机制:传统管道在UNIX SHELL中起到不少作用,它能够将上一命令生成的字符串作为下一命令的参数进行传递。例如:

> ls | grep "abc"

作用是列出当前目录的文件名(ls),并通过grep找出含有abc的文件名。中间的”|”符号就是管道操作符。而在PowerShell中,管道可以这样用:

> 1,2,3 | ForEach-Object{$_ *2} 

也就是将传入的1,2,3看做单独的对象来处理,通过”$_”遍历并乘2,得到一个2,4,6组成的数组。

10、Lua被广泛应用在游戏脚本和手机客户端里,而AppleScript是Mac OS X操作系统中一个提供自动化操作的脚本语言,简单来说AppleScript执行起来就像按键精灵。

11、简单判定图灵完备的方法就是看该语言能否模拟出图灵机,也就是可以模拟一切的可计算问题。