# 大染志
Go, JavaScript, Ruby on Rails, Java,Docker, CI, CD, Photography

0%

## Java CORS实现Ajax跨域请求

Posted on 2012-08-23 Edited on 2014-07-22 In HTML5 , java , javascript

跨域问题在我们开发web应用的时候经常遇到，但一直没有很好的解决方案。目前可能大家认为相对比较好使的就是——JSONP技术。不过这样前台通常需要告诉后台需要返回的函数名称，而后台需要向前台前台返回的则是一个可以执行的代码段。这样在后台处理的时候就相对麻烦一些。

其实在新的W3C标准中，我们只需要在服务器后端添加一句话即可以比较好的解决跨域问题。如java servlet中：

    response.setHeader("Access-Control-Allow-Origin","http://toozhao.com");

这段代码的意思就是，允许来自toozhao.com的跨域HTTP请求，当然我们也可以使用通配符 “*”,这样任意的请求都可以访问这个地址了，而不会出现跨域的问题。

不过据其他文档中介绍，这样做是不安全的。因为这样服务器不能访问document.cookie 对象。不知道请求者的相关信息，而微软的介绍文档中说到：

> 安全警报 为了保护用户数据，跨域请求是匿名的，这意味着服务器无法轻松找出正在请求数据的用户。 因此，只应请求和响应不属于敏感信息或个人身份识别信息的跨域数据。

因此为了安全，我们只应该向我们能保证其安全的站点提供Access-Control-Allow-Origin，即（CORS）。或者对可以公开的数据采用该种方式。

我个人认为在下面的情景中，比较适合采用这种跨域处理技术：

此外，CORS还有一些其他属性可以设置：

    Access-Control-Allow-Origin: http://www.toozhao.com   //设置允许跨域的地址
    Access-Control-Allow-Methods: POST, GET   //设置跨域允许的方法
    Access-Control-Allow-Headers: NCZ      //设置跨域允许的头部信息
    Access-Control-Max-Age: 1728000   //设置跨域允许的最大时间

好了有了上面的这些参数，只要我们在java 中可以获取到HttpServletResponse 对象，即可以设置属性。被允许的前台就可以使用一般的ajax调用了。如jquery：

    $.ajax({

    url: 'http://toozhao.com/test/xxx',

    method: 'GET'，

    success: function(msg){

    console.log(msg);

    }

    });

参考文档：
http://huaidan.org/archives/2729.html
http://msdn.microsoft.com/zh-cn/library/dd573303(v=vs.85).aspx

注：已修正图片中B系统URL错误。

## java web.xml定义配置错误页面及使用

Posted on 2012-08-16 Edited on 2014-07-22 In java , 未分类

我们在开发java web 的程序时候，经常会需要给用户提示信息，或者页面。最常见的，比如用户输入了一个不存在的网址，默认情况下Tomcat会给用户返回一个默认的页面。如下所示：

这个页面千篇一律。我们完全可以给用户展示一个自定义的页面。

其实java web程序中web.xml 本身就支持自定义错误页面，我们只需要在web.xml添加如下信息：

    <error-page>
     <error-code>404</error-code>
     <location>/errorpage/404.html</location>
     </error-page>
     <error-page>
     <error-code>401</error-code>
     <location>/errorpage/401.html</location>
     </error-page>
     <error-page>
     <error-code>500</error-code>
     <location>/errorpage/500.html</location>
     </error-page>

当然“error-code”，可以自己选择在程序中出现得最多的错误码。我个人认为通常我们拦截：

401：未授权

404：没有找到页面

500：服务器内部错误

这三个即可。在“location”中配置你自己的html,当然页面样式，内容这些这些都可以自己定义。这个就看你自己啦。

如果我们不做其他操作，当系统出现这些错误情况时，服务器就会自动调用我们配置的网页。当然我们可以自行在恰当的时候使用它。

在servlet或者其他可能访问到HttpServletResponse对象的地方，使用：

    response.sendError(404); //404为你需要的错误代码

    //也可以向前台网页传输错误语句，不过前台网页需要相应支持。这里没有实现

    response.sendError(404,"这里写想要输出到前台的提示信息");

在java中还可以使用：

    response.setStatus(404);  //设置状态码

设置状态码来实现，不过这并不能调用配置的自定义页面。只是在前台显示错误，并无输出。

## java 服务器端实现HTTP无enctype=”multipart/form-data”文件上传

Posted on 2012-08-14 Edited on 2014-07-22 In java

在java web中我们一般都是使用commons-fileupload 和cos 进行服务器端上传文件的处理，而这种情况通常是我们通过在网页中的form标签中设置enctype=”multipart/form-data”这样的信息，才可以。否则commons-fileupload和cos都不能获取到文件。HTML网页设置格式如下图所示：

    <html>
    <body>
    <h2>Hello upload-file</h2>
    <form method="POST" action="upload" enctype="multipart/form-data">
    file upload:<br>
    <input type="file" name="file" />
    <input type="submit" value="submit">
    </form>
    </body>
    </html>

这只是一个简单例子，但如果我们遇到这样的情况：我们有一个java本地的客户端，使用HTTP协议来上传文件，不过这里没有表单。commons-fileupload的服务器端就会报错

其实解决的办法也很简单，面对没有设置”multipart/form-data”属性的客户端，我们可以通过request.getInputStream() 获取输入流，从中读取文件内容。

下面是我写的一断简单代码，把输入流信息，写入到C盘的一个文件：

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

     InputStream input= request.getInputStream(); //获取流
     OutputStream out = new FileOutputStream(new File("c://test.txt"));
     byte[] buffer = new byte[1024];
     int count;
     while ((count = input.read(buffer)) != -1) {
     out.write(buffer, 0, count);  //写文件
     }
     out.flush();
     out.close();
     input.close();
     }

不过这种方式是不能直接解析上面那种form表单的文件上传方式，他会在文件的前后各加上一段信息,下面是一个form表单上传，输入流中的信息：

    ------WebKitFormBoundaryOPczhvGNCBlneBER
    Content-Disposition: form-data; name="file"; filename="??????.txt"
    Content-Type: text/plain
    #下面是我写入的文件内容
    df03c9cf37c5fbc5a7894e04297127d7
    3a9bb0371ea5789666ab438b3b7e05c2
    #到此为止
    ------WebKitFormBoundaryOPczhvGNCBlneBER--

如果form中没有加上enctype=”multipart/form-data”属性信息，输入流中得到的只有在<input value=””>中设置的value值，因此，通过流来获取上传的文件，应该只适合于从客户端直接向服务器写文件。

## 分享多个公网上著名的maven组件仓库

Posted on 2012-08-09 Edited on 2014-07-22 In java , MAVEN

我们都知道maven是项目构建的神器，不过用maven从国外下载东西的时候这速度可真就不怎么神器了。而且如果你在公司里面使用maven,而公司里面没有自己建一个maven代理仓库的话，大家一起使用maven下载组件的时候，就费力了。

因此一个公司是完全有必须要搭建一个maven代理仓库的。既可以节省宽带资源、也可以节省其他人编译相同代码说下载组件的时间，而且代理仓库服务器上的组件还可以随时复制、迁移到其他服务器，造福其他程序员。通常情况下，我们使用nexus搭建自己的maven仓库和做公网上那些用得很多的仓库的代理仓库，今天就在这里分享一些我搜集的公网上常用的代理仓库。这些已经能够保证我工作中的maven项目95%以上正常编译了。

> 中央仓库：http://repo1.maven.org/maven2/

这个就是全世界最核心的maven仓库，相信大家都知道，nexus默认就已经提供。

> apache snapshots: http://repository.apache.org/snapshots/

apache 的快照组件仓库

> apache webservices :http://ws.zones.apache.org/repository2/

apache 的web services仓库，通常用得不多。

> codehaus snapshots: http://nexus.codehaus.org/snapshots/

> and ：http://snapshots.repository.codehaus.org/

另外一个比较著名的开源组织codehaus的快照仓库，貌似其中一个已经有一年多没有更新了。

> jenkins :http://repo.jenkins-ci.org/public/

开源项目jenkins 的仓库

> ops4j:http://repository.ops4j.org/maven2/

开源项目ops4j的maven仓库

> nexus ：https://repository.sonatype.org/content/groups/forge/

这是nexus自己的仓库，本身就包含了很过仓库仓库的代理，不过速度貌似不够快。

> spring external:http://repository.springsource.com/maven/bundles/external/

> spring osgi:http://s3.amazonaws.com/maven.springframework.org/osgi/

> spring release bundle:http://repository.springsource.com/maven/bundles/release/

> spring release libs:http://repo.springsource.org/libs-release/

> spring snapshots libs:http://repo.springsource.org/libs-snapshot/

spring 这个开源组织提供的仓库的确很多，而在我平时的编译中也经常用到，有一点spring 做得特别牛，那就是它吧很多一般的jar包转成了或者重新制作成了bundle。(bundle是osgi技术中需要的jar包，bundle可以当成普通jar包使用，而普通jar包不能当成bundle使用，举个简单的例子，如果你想把jar包放到你的osgi 应用服务器virgo 或者 jboss as 7中使用，你就必须得用bundle才可以。)所以当你找不到某个包的bundle版本的时候，试试去spring的maven仓库，他的所有包都是bundle.

> wso2：http://maven.wso2.org/nexus/content/groups/wso2-public/

> wso2-2:http://dist.wso2.org/maven2/

wso2是一个企业级web services中间件，提供了很多，比较强大的组件。如AS， IS,ESB等。大家有兴趣可以看看。

把这样仓库全部做成你的nexus的代理，就相当于你拥有它们所有仓库的能力了。是不是瞬间战斗力提升了很多。

如果你想尽快使用你添加的这些代理仓库，请在nexus中更新这些仓库的 index(索引)，你就可以马上使用这些仓库了。

## Spring Data MongoDB 简单使用

Posted on 2012-08-06 Edited on 2014-07-22 In java , mongodb

这篇文章，主要是作为一个记录，记录我一个小时之前搞定这个东西的兴奋心情。spring mongodb主要是mongodb-java-driver 进行了一些封装，然后可以配合强大的spring使用。我觉得可以简单把它看成一个mongo的”ORM”框架。通过我从星期五到星期天的捣腾，我发现熟悉spring 框架本身其实是最重要的。好下面直接上吧：

首先我在eclipse里面建了一个maven项目，你需要添加如下依赖信息(这里用到的spring框架是3.0.6.RELEASE版本)：

    <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <spring.version>3.0.6.RELEASE</spring.version>
     <slf4j.version>1.6.1</slf4j.version>
     </properties>

    <dependencies>
     <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>4.8.1</version>
     <scope>test</scope>
     </dependency>
     <dependency>
     <groupId>org.springframework.data</groupId>
     <artifactId>spring-data-mongodb</artifactId>
     <version>1.0.2.RELEASE</version>
     </dependency>
     <dependency>
     <groupId>log4j</groupId>
     <artifactId>log4j</artifactId>
     <version>1.2.16</version>
     </dependency>
     <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-api</artifactId>
     <version>${slf4j.version}</version>
     </dependency>
     <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>jcl-over-slf4j</artifactId>
     <version>${slf4j.version}</version>
     </dependency>
     <dependency>
     <groupId>org.slf4j</groupId>
     <artifactId>slf4j-log4j12</artifactId>
     <version>${slf4j.version}</version>
     </dependency>
     <!-- Spring dependencies -->
     <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-core</artifactId>
     <version>${spring.version}</version>
     <exclusions>
     <exclusion>
     <groupId>commons-logging</groupId>
     <artifactId>commons-logging</artifactId>
     </exclusion>
     </exclusions>
     </dependency>
     <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-test</artifactId>
     <version>${spring.version}</version>
     <scope>test</scope>
     <exclusions>
     <exclusion>
     <groupId>commons-logging</groupId>
     <artifactId>commons-logging</artifactId>
     </exclusion>
     </exclusions>
     </dependency>
     <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context</artifactId>
     <version>${spring.version}</version>
     </dependency>
     <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-aop</artifactId>
     <version>${spring.version}</version>
     </dependency>
     <dependency>
     <groupId>cglib</groupId>
     <artifactId>cglib</artifactId>
     <version>2.2</version>
     </dependency>
     <dependency>
     <groupId>org.mongodb</groupId>
     <artifactId>mongo-java-driver</artifactId>
     <version>2.8.0</version>
     </dependency>
     <dependency>
     <groupId>org.springframework.data</groupId>
     <artifactId>spring-data-commons-core</artifactId>
     <version>1.2.1.RELEASE</version>
     </dependency>
     </dependencies>

由于这里面的某些依赖可能maven中央仓库没有，所以请在pom里添加下面两个spring的仓库:

    <repository>
     <id>spring-maven-release</id>
     <name>Spring Maven Release Repository</name>
     <url>http://maven.springframework.org/release</url>
     </repository>
     <repository>
     <id>spring-maven-milestone</id>
     <name>Spring Maven Milestone Repository</name>
     <url>http://maven.springframework.org/milestone</url>
     </repository>

下面进行我们的代码编写,首先我们需要一个简单的java POJO类:person.java用于存储人的信息，其有三个属性：id(和mongodb中的ObjectId对应)，name-姓名，age-年龄。

    package com.toozhao.mongo.bean;

    import org.springframework.data.annotation.Id;
    import org.springframework.data.mongodb.core.mapping.Document;

    /**
     *
     * @author Junv
     *
     */
    @Document
    public class Person {

    @Id
     private String id;
     private String name;
     private int age;

    public Person() {

    }

    public Person(String name, int age) {
     this.name = name;
     this.age = age;
     }

    public String getId() {
     return id;
     }

    public String getName() {
     return name;
     }

    public void setId(String id) {
     this.id = id;
     }

    public void setName(String name) {
     this.name = name;
     }

    public void setAge(int age) {
     this.age = age;
     }

    public int getAge() {
     return age;
     }

    @Override
     public String toString() {
     return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
     }

    }

然后我们定义一个执行操作的接口，和其实现类，这里可以看做是一个dao模式。在接口中我们只定义了保存对象和查询一条记录两个方法。

    package com.toozhao.mongo.repository;

    import com.toozhao.mongo.bean.Person;
    /**
     *
     * @author Junv
     *
     */
    public interface MongoAction {

     public void saveObject(Person objToSave);

     public Person findObject(String id);

    }

实现类：

    package com.toozhao.mongo.repository;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.mongodb.core.MongoOperations;
    import org.springframework.data.mongodb.core.query.Criteria;
    import org.springframework.data.mongodb.core.query.Query;
    import org.springframework.stereotype.Repository;

    import com.toozhao.mongo.bean.Person;

    @Repository
    public class PersonActionImp implements MongoAction {

    @Autowired
     MongoOperations operation;

    public void saveObject(Person objToSave) {
     operation.insert(objToSave);

    }

    public Person findObject(String id) {
     return operation.findOne(new Query(Criteria.where("_id").is(id)),
     Person.class);

    }

    }

@repository,和@autowired是spring框架中的，主要功能是起到类似反射的作用吧，具体我还没弄得很清楚。

写一个有main方法的java类，对功能进行简单测试：

    package com.toozhao.mongo;

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    import com.toozhao.mongo.bean.Person;
    import com.toozhao.mongo.repository.MongoAction;

    public class MainTest {

    private static final Log log = LogFactory.getLog(MainTest.class);

    public static void main(String[] args) {

    log.info("initial -----------------");
     ConfigurableApplicationContext context = null;
     //实例化appliaction Context对象
     context = new ClassPathXmlApplicationContext(
     "META-INF/spring/applicationContext.xml");
     //获取一个MongoAction Bean，以便后面执行相关操作
     MongoAction action = context.getBean(MongoAction.class);
     Person person = new Person("Tom", 11);

     action.saveObject(person);
     log.info("结果为：" + action.findObject(person.getId()));

    }

    }

最后，贴出applicationContext文档，里面主要对mongodb进行了简单的配置，和设置了repository的扫描目录（和@repository对应）。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:context="http://www.springframework.org/schema/context"
     xmlns:mongo="http://www.springframework.org/schema/data/mongo"
     xsi:schemaLocation=
     "http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context-3.0.xsd

    http://www.springframework.org/schema/data/mongo

    http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd

    http://www.springframework.org/schema/beans

    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

     <context:annotation-config/>

    <context:component-scan base-package="com.toozhao.mongo.repository">
     <context:exclude-filter type="annotation" expression="org.springframework.context.annotation.Configuration"/>
     </context:component-scan>

     <!-- Default bean name is 'mongo' -->
     <mongo:mongo host="localhost" port="27017">
     <mongo:options connections-per-host="8"
     threads-allowed-to-block-for-connection-multiplier="4"
     connect-timeout="1000"
     max-wait-time="1500"
     auto-connect-retry="true"
     socket-keep-alive="true"
     socket-timeout="1500"
     slave-ok="true"
     write-number="1"
     write-timeout="0"
     write-fsync="true"/>
     </mongo:mongo>
     <!-- xml 配置mongoTemplate-->
     <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
     <constructor-arg ref="mongo"/>
     <constructor-arg name="databaseName" value="junv"/>
     </bean>

     <!-- Use this post processor to translate any MongoExceptions thrown in @Repository annotated classes -->
     <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

    </beans>

当然你还需要做的就是运行这个项目，我们需要在pom.xml里面添加如下代码,<mainClass>为你需要运行的类：

    <plugin>
     <groupId>org.codehaus.mojo</groupId>
     <artifactId>exec-maven-plugin</artifactId>
     <version>1.1.1</version>
     <!-- 你需要执行的类， -->
     <configuration>
     <mainClass>com.toozhao.mongo.MainTest</mainClass>
     </configuration>
     </plugin>

最后，使用 mvn exec:java 就可以运行代码了，当然你在有main方法那个类，右键以java程序的方式也可以运行。结果就是你应该可以看到程序像数据库junv.person中插入了一条数据。

## 当这组长好累！

Posted on 2012-07-24 Edited on 2014-07-22 In 我说

这个月，领导说我对程序仓库方面比较了解，所以让我当这方面的一个项目组长，负责nexus仓库的使用和改造等。

我们小组有4个人，我和另外一个是实习生，还有另外两位是实训生。就是这样一个小组，我们担负的任务是改造nexus。

但是到现在我感觉到的只有累。

每天感觉就像生活在使用maven编译项目的过程中。

所有需求不明确，只是领导和我们小组一起讨论过一次。也没有讨论出什么东西。下来，我按照讨论结果大概写了一个想法和预期的总结。发给了领导。但是就再也没有回应了。

我那个东西写得很简略，我也不知道哪些东西可以要，哪些应该深入。我也拿不定主义，可就是这样，我被要求写需求，画流程图，画用例图，我觉得很不知所措，我都不知道哪些东西应该做，哪些不应该做，这叫我怎么实现出来。

我不明白。我也不知道需求怎么写。恼火。

在编译和大概看nexus的源码的过程中，我们小组都发现，要成功编译它，还真不是一件容易的事。在看他代码吧。几十个MAVEN项目，几乎没什么说明，代理里面注释也不标准，也看不懂代码是怎么样一个结构。我只是想说这个项目太大了，真的太大了。大到我们不能承受地步，而且，我在网上搜，搜不出一条关于它的源码的解析。

nexus 也很无赖，很多东西很乱，有些前端文字，在专门的js里面，有些又随意分布。更可恶的是，它还有实时从后台下载文字等信息，显示出来。感觉这个公司真的很流氓。

我不想当组长了，我只是想安心搞我的技术。我技术都不够成熟。我才大四不到啊。我还想继续搞 我的技术。请让我把技术能力提升了以后再说其他的吧。我好累。好累。

这个组长不好当，更何况要我做的不是用一个项目，而是改人家一个没什么注释的代码。我伤不起。

who can help me?

## HTML5 全屏(full screen)API

Posted on 2012-07-22 Edited on 2014-07-22 In HTML5

full screen (全屏)API,现在已经成为了HTML5的一个官方API，不过目前只是被chrome、firefox、safari浏览器实现了，且他们目前都是用的自行实现的函数，而非W3C官方标准的函数。建议在调用之前都检测一下！

full screen API主要有两个方法：一是执行全屏，另外一个则是退出全屏。他们的调用方法为：

执行全屏

    var element =  XXX      //这里你需要得到你的一个网页中的对象，可以是整个网页，或者其中一个节点

    element.requestFullscreen();     //W3C的方法

    element.mozRequestFullScreen();     //firefox实现的方法

    element.webkitRequestFullScreen();     //chrome 和safari实现的方法

退出全屏

    element.exitFullScreen();     //W3C

    element.mozCancelFullScreen();     //firefox

    element.webkitCancelFullScreen();  //chrome和safari

例如,我想全屏整个页面,那个就应该使用:

    var documentEle = document.documentElement;

    documentEle.webkitRequestFullScreen(); //chrome

此外我们还可以监听，full screen 事件，在其状态改变时执行相关操作。

    document.addEventListener("fullscreenchange", function () {}, false);  //w3c

    document.addEventListener("mozfullscreenchange",function(){},false); //firefox

    document.addEventListener("webkitfullscreenchange", function () {}, false);  //chrome 和safari

如果我们想获取当前某个对象数否处于全屏状态，就可以使用下面这个属性：

    document.fullScreen  //w3c

    document.mozFullScreen //firefox

    document.webkitIsFullScreen // chrome 和safari

经过我的测试（chrome 22），应该是HTML 里面所有对象都是可以被全屏的,如：