paulwong

#

ubuntu 察看 java安装路径

有时候不知道java安装在哪里了 通过whereis java命令不能知道java真是的安装路径
可以通过 update-alternatives --config java 命令察看

bean@ubuntu :~$ update-alternatives --config java
There is only one alternative in 
link group java: /usr/lib/jvm/java-7-oracle/jre/bin/java
Nothing to configure
.
bean
@ubuntu :~

或者这种方法也可以:
进入到相应的目录:cd /usr/bin

查看java链接到了哪里:ls -l java

localhost:bin root# ls -l java
lrwxr-xr-x 1 root wheel 74 May 18 10:26 java -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java

posted @ 2014-05-04 11:43 paulwong 阅读(8157) | 评论 (0)编辑 收藏

Ubuntu Tips: How To Enable Root User ( Super User ) in Ubuntu


Question: I’m unable to do su – on Ubuntu. It says “su: Authentication failure”. How do I fix it? Also, is it possible for me to login to Ubuntu using root account directly?

Answer: Let us address these two question one by one.

Warning: Enabling root is not recommended. If possible, you should always try to perform all administrative tasks using sudo.

Question 1: I’m unable to login using su command. How to fix this?

By default, root account password is locked in Ubuntu. So, when you do su -, you’ll get Authentication failure error message as shown below.

$ su - Password: su: Authentication failure

Enable super user account password on Ubuntu

First, set a password for root user as shown below.

$ sudo passwd root [sudo] password for ramesh: Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully

Now with the new password you can login as super user with su command

posted @ 2014-05-03 21:26 paulwong 阅读(392) | 评论 (0)编辑 收藏

Jersey Exception Handling

使用JERSEY框架输出JSON,需捕获所有的HTTP错误,如404等,业务错误及其他未定义的错误,将这些错误输出JSON,而不是TOMCAT的错误。
JERSEY已和SPRING整合。

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee">

    <display-name>Restful Web Application</display-name>
    
    <servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>
            com.sun.jersey.spi.spring.container.servlet.SpringServlet
        </servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>restfullapi.rest.service,restfullapi.common.provider,restful.web</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    
 
     <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    
    <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>
    
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
    </context-param>
    
    <!-- spring logback -->
    <context-param>
        <param-name>logbackConfigLocation</param-name>
        <param-value>classpath:logback.xml</param-value>
    </context-param>  
    <listener>
        <listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class>
    </listener>

    <context-param>
        <param-name>webAppRootKey</param-name>
        <param-value>restfull-api</param-value>
    </context-param>
    
    <welcome-file-list>
        <welcome-file>/index.jsp</welcome-file>
    </welcome-file-list>
    

</web-app>


AbstractBaseRestfulException.java
public abstract class AbstractBaseRestfulException extends Exception{

    private static final long serialVersionUID = 6779508767332777451L;
    
    public AbstractBaseRestfulException()
    {
    }
    
    public AbstractBaseRestfulException(String message)
    {
        super(message);
    }

    public abstract String getErrcode();

    public abstract void setErrcode(String errcode);

    public abstract String getDescription();

    public abstract void setDescription(String description);
    

}


AbstractBaseRestfulExceptionMapper.java
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

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

import com.paul.common.exception.AbstractBaseRestfulException;
import com.paul.common.json.DefaultJsonResponse;

@Provider
public class AbstractBaseRestfulExceptionMapper implements ExceptionMapper<AbstractBaseRestfulException>{

    private Logger logger = LoggerFactory.getLogger(AbstractBaseRestfulExceptionMapper.class);
    
    public Response toResponse(AbstractBaseRestfulException exception) {
        
        logger.error(exception.getMessage(), exception);
        
        DefaultJsonResponse<Object> response = new DefaultJsonResponse<Object>();
        response.setDescription(exception.getDescription());
        response.setErrcode(exception.getErrcode());
        response.setResult(null);
            
        return Response.status(Status.BAD_REQUEST)
                .entity(response)
                .type(MediaType.APPLICATION_JSON + ";charset=utf-8")
                .build();
    }

}


OtherExceptionMapper.java
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

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

import com.paul.common.json.DefaultJsonResponse;
import com.paul.common.json.JsonResponseStatus;

@Provider
public class OtherExceptionMapper implements ExceptionMapper<Exception>{
    
    private Logger logger = LoggerFactory.getLogger(OtherExceptionMapper.class);

    public Response toResponse(Exception exception) {
        
        logger.error(exception.getMessage(), exception);
        
        DefaultJsonResponse<Object> response = new DefaultJsonResponse<Object>();
        response.setDescription(JsonResponseStatus.OTHER_ERROR.getMessage() + exception.getMessage());
        response.setErrcode(JsonResponseStatus.OTHER_ERROR.getCode());
        response.setResult(null);
            
        return Response.status(Status.BAD_REQUEST)
                .entity(response)
                .type(MediaType.APPLICATION_JSON + ";charset=utf-8")
                .build();
    }

}


WebApplicationExceptionMapper.java
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

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

import com.paul.common.json.DefaultJsonResponse;

@Provider
public class WebApplicationExceptionMapper implements ExceptionMapper<WebApplicationException >{

    private Logger logger = LoggerFactory.getLogger(WebApplicationExceptionMapper.class);
    
    public Response toResponse(WebApplicationException exception) {
        
        logger.error(exception.getMessage(), exception);
        
        DefaultJsonResponse<Object> response = new DefaultJsonResponse<Object>();
        response.setDescription(exception.getMessage());
        response.setErrcode(String.valueOf(exception.getResponse().getStatus()));
        response.setResult(null);
            
        return Response.status(exception.getResponse().getStatus())
                .entity(response)
                .type(MediaType.APPLICATION_JSON + ";charset=utf-8")
                .build();
    }

}


Controller中无须再处理异常
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.paul.common.json.DefaultJsonResponse;
import com.paul.common.json.JsonResponseStatus;
import com.paul.program.stbstart.valueobject.StbStart;
import com.paul.stbstart.valueobject.StbStartRequest;
import com.paul.restfullapi.rest.service.AdvertisementRestfulService;

@Path("/advertisement")
@Controller
public class AdvertisementRestfulController {
    
    private Logger logger = LoggerFactory.getLogger(AdvertisementRestfulController.class);
    
    @Autowired
    AdvertisementRestfulService advertisementRestfulService;
    
    @Path("/getAdvertisement")
    @Produces({MediaType.APPLICATION_JSON + ";charset=utf-8"})
    @GET
    public DefaultJsonResponse<StbStart> getAdvertisement(
            @DefaultValue("") @QueryParam("version")String version,
            @QueryParam("token")String token) throws Exception
    {
        DefaultJsonResponse<StbStart> response = new DefaultJsonResponse<StbStart>();
        StbStartRequest request = new StbStartRequest();
        logger.info(version);
        request.setVersion(version);
        request.setToken(token);
        StbStart result = advertisementRestfulService.findByVersion(request);
        response.setResult(result);
        response.setDescription(JsonResponseStatus.SUCCESS.getMessage());
        response.setErrcode(JsonResponseStatus.SUCCESS.getCode());
        
        logger.info("----------------");
//        double i = 1/0;
        return response;
    }
    

}







posted @ 2014-04-28 14:44 paulwong 阅读(1261) | 评论 (0)编辑 收藏

Mongodb数据更新命令、操作符

一、Mongodb数据更新命令

Mongodb更新有两个命令:update、save。

1.1update命令

update命令格式:

db.collection.update(criteria,objNew,upsert,multi)

参数说明:

criteria:查询条件

objNew:update对象和一些更新操作符

upsert:如果不存在update的记录,是否插入objNew这个新的文档,true为插入,默认为false,不插入。

multi:默认是false,只更新找到的第一条记录。如果为true,把按条件查询出来的记录全部更新。

 

示例:

Shell代码  收藏代码
  1. > db.classes.insert({"name":"c1","count":30})  
  2. > db.classes.insert({"name":"c2","count":30})  
  3. > db.classes.find()  
  4. { "_id" : ObjectId("5030f3a3721e16c4ab180cd9"), "name" : "c1", "count" : 30 }  
  5. { "_id" : ObjectId("5030f3ab721e16c4ab180cda"), "name" : "c2", "count" : 30 }  
  6. >   

示例1:把count大于20的class name修改为c3

Shell代码  收藏代码
  1. > db.classes.update({"count":{$gt:20}},{$set:{"name":"c3"}})  
  2. > db.classes.find()  
  3. { "_id" : ObjectId("5030f3a3721e16c4ab180cd9"), "name" : "c3", "count" : 30 }  
  4. { "_id" : ObjectId("5030f3ab721e16c4ab180cda"), "name" : "c2", "count" : 30 }  
  5. >   

由于没有指定upsert和multi的值,所以全部默认为false,由结果可以看出,只修改了第一条符合条件的记录。

示例2:把count大于20的class name修改为c4,设置multi为true

Shell代码  收藏代码
  1. > db.classes.update({"count":{$gt:20}},{$set:{"name":"c4"}},false,true)  
  2. > db.classes.find()  
  3. { "_id" : ObjectId("5030f3a3721e16c4ab180cd9"), "name" : "c4", "count" : 30 }  
  4. { "_id" : ObjectId("5030f3ab721e16c4ab180cda"), "name" : "c4", "count" : 30 }  
  5. >   

由于指定了multi为true,所以对两条符合条件的记录都进行了更新。

示例3: 把count大于50的class name修改为c5,设置upsert为true

Shell代码  收藏代码
  1. > db.classes.update({"count":{$gt:50}},{$set:{"name":"c5"}},true,false)  
  2. > db.classes.find()  
  3. { "_id" : ObjectId("5030f3a3721e16c4ab180cd9"), "name" : "c4", "count" : 30 }  
  4. { "_id" : ObjectId("5030f3ab721e16c4ab180cda"), "name" : "c4", "count" : 30 }  
  5. { "_id" : ObjectId("5030f589ce8fa8884e6cd441"), "name" : "c5" }  
  6. >   

在集合中没有count大于50的记录,但是由于指定了upsert为true,如果找不到则会插入一条新记录。

1.2save命令

Mongodb另一个更新命令是save,格式如下:

db.collection.save(obj)

obj代表需要更新的对象,如果集合内部已经存在一个和obj相同的"_id"的记录,Mongodb会把obj对象替换集合内已存在的记录,如果不存在,则会插入obj对象。

这条命令比较简单,示例就省略了。

 

二、数据更新操作符

1.$inc

用法:{$inc:{field:value}}

作用:对一个数字字段的某个field增加value

示例:将name为chenzhou的学生的age增加5

Shell代码  收藏代码
  1. > db.students.find()  
  2. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "name" : "chenzhou", "age" : 22 }  
  3. #查询结果显示年龄为22  
  4. > db.students.update({name:"chenzhou"},{$inc:{age:5}})  
  5. #执行修改,把age增加5  
  6. > db.students.find()  
  7. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "name" : "chenzhou", "age" : 27 }  
  8. >   
  9. #查询结果显示年龄为27,修改成功  

2.$set

用法:{$set:{field:value}}

作用:把文档中某个字段field的值设为value

示例: 把chenzhou的年龄设为23岁

Shell代码  收藏代码
  1. > db.students.find()  
  2. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "name" : "chenzhou", "age" : 27 }  
  3. > db.students.update({name:"chenzhou"},{$set:{age:23}})  
  4. > db.students.find()  
  5. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "name" : "chenzhou", "age" : 23 }  
  6. >   

从结果可以看到,更新后年龄从27变成了23

3.$unset

用法:{$unset:{field:1}}

作用:删除某个字段field

示例: 将chenzhou的年龄字段删除

Shell代码  收藏代码
  1. > db.students.find()  
  2. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "name" : "chenzhou", "age" : 23 }  
  3. > db.students.update({name:"chenzhou"},{$unset:{age:1}})  
  4. > db.students.find()  
  5. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "name" : "chenzhou" }  
  6. >   

4.$push

用法:{$push:{field:value}}

作用:把value追加到field里。注:field只能是数组类型,如果field不存在,会自动插入一个数组类型

示例:给chenzhou添加别名"michael"

Shell代码  收藏代码
  1. > db.students.find()  
  2. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "name" : "chenzhou" }  
  3. > db.students.update({name:"chenzhou"},{$push:{"ailas":"Michael"}})  
  4. > db.students.find()  
  5. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ "Michael" ], "name" : "chenzhou" }  
  6. >   

由结果可以看到,记录中追加了一个数组类型字段alias,且字段有一个为"Michael"的值

5.pushAll

用法:{$pushAll:{field:value_array}}

作用:用法同$push一样,只是$pushAll可以一次追加多个值到一个数组字段内。

示例:给chenzhou追加别名A1,A2

 

Shell代码  收藏代码
  1. > db.students.find()  
  2. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ "Michael" ], "name" : "chenzhou" }  
  3. > db.students.update({name:"chenzhou"},{$pushAll:{"ailas":["A1","A2"]}})  
  4. > db.students.find()  
  5. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ "Michael", "A1", "A2" ], "name" : "chenzhou" }  
  6. >   

6.$addToSet

用法:{$addToSet:{field:value}}

作用:加一个值到数组内,而且只有当这个值在数组中不存在时才增加。

示例:往chenzhou的别名字段里添加两个别名A3、A4 

Shell代码  收藏代码
  1. > db.students.find()  
  2. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ "Michael", "A1", "A2" ], "name" : "chenzhou" }  
  3. > db.students.update({name:"chenzhou"},{$addToSet:{"ailas":["A3","A4"]}})  
  4. > db.students.find()  
  5. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ "Michael", "A1", "A2", [ "A3", "A4" ] ], "name" : "chenzhou" }  
  6. >   

由结果可以看出,更新后ailas字段里多了一个对象,这个对象里包含2个数据,分别是A3、A4

7.$pop

用法:删除数组内第一个值:{$pop:{field:-1}}、删除数组内最后一个值:{$pop:{field:1}}

作用:用于删除数组内的一个值

示例: 删除chenzhou记录中alias字段中第一个别名

Shell代码  收藏代码
  1. > db.students.find()  
  2. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ "Michael", "A1", "A2", [ "A3", "A4" ] ], "name" : "chenzhou" }  
  3. > db.students.update({name:"chenzhou"},{$pop:{"ailas":-1}})  
  4. > db.students.find()  
  5. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ "A1", "A2", [ "A3", "A4" ] ], "name" : "chenzhou" }  
  6. >   

由结果可以看书,第一个别名Michael已经被删除了。

我们再使用命令删除最后一个别名:

Shell代码  收藏代码
  1. > db.students.find()  
  2. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ "A1", "A2", [ "A3", "A4" ] ], "name" : "chenzhou" }  
  3. > db.students.update({name:"chenzhou"},{$pop:{"ailas":1}})  
  4. > db.students.find()  
  5. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ "A1", "A2" ], "name" : "chenzhou" }  
  6. >   

由结果可以看出,alias字段中最后一个别名["A3","A4"]被删除了。

8.$pull

用法:{$pull:{field:_value}}

作用:从数组field内删除一个等于_value的值

示例:删除chenzhou记录中的别名A1

Shell代码  收藏代码
  1. > db.students.find()  
  2. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ "A1", "A2" ], "name" : "chenzhou" }  
  3. > db.students.update({name:"chenzhou"},{$pull:{"ailas":"A1"}})  
  4. > db.students.find()  
  5. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ "A2" ], "name" : "chenzhou" }  
  6. >   

9.$pullAll

用法:{$pullAll:value_array}

作用:用法同$pull一样,可以一次性删除数组内的多个值。

示例: 删除chenzhou记录内的所有别名

Shell代码  收藏代码
  1. > db.students.find()  
  2. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ "A1", "A2" ], "name" : "chenzhou" }  
  3. > db.students.update({name:"chenzhou"},{$pullAll:{"ailas":["A1","A2"]}})  
  4. > db.students.find()  
  5. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ ], "name" : "chenzhou" }  
  6. >   

可以看到A1和A2已经全部被删除了

10.$rename

用法:{$rename:{old_field_name:new_field_name}}

作用:对字段进行重命名

示例:把chenzhou记录的name字段重命名为sname

Shell代码  收藏代码
  1. > db.students.find()  
  2. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ ], "name" : "chenzhou" }  
  3. > db.students.update({name:"chenzhou"},{$rename:{"name":"sname"}})  
  4. > db.students.find()  
  5. { "_id" : ObjectId("5030f7ac721e16c4ab180cdb"), "ailas" : [ ], "sname" : "chenzhou" }  
  6. >   

由结果可以看出name字段已经被更新为sname了。

posted @ 2014-04-22 16:10 paulwong 阅读(282) | 评论 (0)编辑 收藏

整合测试

http://arquillian.org/guides/getting_started_zh_cn/

posted @ 2014-04-20 10:33 paulwong 阅读(596) | 评论 (0)编辑 收藏

REST client 基于浏览器的测试工具

  以前在开发webservice服务,都是自己基于HTTP协议,自己写一个测试程序来进行测试,最近在研究RestFul,对以前webservice服务进行了重构,总结了不少经验,今天就给大家介绍下几款Rest Client的测试工具。

REST介绍

  所谓REST,是Representational State Transfer,这个词汇的中文翻译很不统一,而且很晦涩,有叫“具象状态传输”,有叫“表象化状态转变”,等等。

  REST风格的Web服务,是通过一个简洁清晰的URI来提供资源链接,客户端通过对URI发送HTTP请求获得这些资源,而获取和处理资源的过程让客户端应用的状态发生改变(不像那些远程过程调用那么直接地发生改变)。

  常用的对资源进行CRUD(Create, Read, Update 和 Delete)的四种HTTP方法分别是POST, GET, PUT, DELETE。

基于浏览器的Rest Client工具

  在chrome或者firefox浏览器都有很多插件,我一般都是使用chrome浏览器,在chrome的webstore中可以搜索到自己想要的插件。这里就讲讲Advance REST Client,Postman-REST Client,DEV HTTP CLIENT,Simple REST Client,火狐下的RESTClient插件

Advanced REST client

  网页开发者辅助程序来创建和测试自定义HTTP请求。它是一款非常强大,使用简单的客户端测试工具,得到了程序员的好评。每周超过50k的开发者使用此应用程序。如此多的人是不会错的! 

支持的功能

  1. Make a HTTP request (via XmlHttpRequest level 2)
  2. Debug socket (via web socket API).
  3. JSON response viewer
  4. XML response viewer
  5. set custom headers - even does not supported by XmlHttpRequest object
  6. help with filling HTTP headers (hint + code completion)
  7. add headers list as raw data or via form
  8. construct POST or PUT body via raw input, form or send file(s) with request
  9. set custom form encoding
  10. remember latest request (save current form state and restore on load)
  11. save (Ctrl+S) and open (Ctrl+O) saved request forms
  12. history support
  13. data import/export

Postman -REST client

  Postman可以帮助你更有效的针对API工作。Postman是一个scratch-your-own-itch项目。它需要的是开发者有效的在项目中创建APIS,能够对API测试进行收藏保留。 

支持功能

  1. HTTP requests 支持文件上传
  2. 格式化API响应的JSON and XML
  3. 打开 responses 的HTML文件在一个新窗口展示
  4. 支持REST准则的超媒体应用状态的引擎- HATEOS
  5. 图像预览
  6. Request history
  7. 基本oauth 1.0助手
  8. Autocomplete for URL and header values
  9. 可以在URL参数中使用 key/value编辑添加参数或header值
  10. 使用环境变量容易转移之间设置。可用于测试,生产,分期或本地设置。
  11. 使用全局变量的值是在整个 APIs
  12. 使用快速查找功能预览变量和它们的值使用状况
  13. 键盘快捷方式,最大限度地提高您的生产力

Simple REST Client

  Simple REST Client插件,提供了一个简单的表单进行各种HTTP操作,并可以看到返回的信息。构建自定义HTTP请求直接测试您的网络服务。 

Firefox下的RESTClient

  FirefoxRESTClient的插件,这款插件由国人开发,功能上支持Basic和OAuth的登录header发送,并且对于返回的XML数据还可以高亮显示

Linux常用的工具CURL

  CURL是一个很强大的支持各种协议的文件传输工具,用它来进行RESTful Web Services的测试简直是小菜一碟。

CURL的命令参数非常多,一般用于RESTful Web Services测试要用到下面四种参数:

  • -d/–data :POST数据内容
  • -X/–request :指定请求的方法(使用-d时就自动设为POST了)
  • -H/–header  :设定header信息
  • -I/–head:只显示返回的HTTP头信息

Java GUI rest-client

  这是一个用Java写的测试小工具,项目主页上提到它有命令行和GUI两种版本。为了方便操作我们选择GUI版本来看看。既然是一款软件,显然就比刚才介绍的浏览器插件功能更加强大。它支持应答正文的JSON和XML缩排和高亮,还可以一键搭建一个RESTful服务端,另外还提供了单元测试的功能。

格式化JSON数据
https://chrome.google.com/webstore/detail/jsonview-jsonviewer-json/hdmbdioamgdkppmocchpkjhbpfmpjiei

posted @ 2014-04-19 18:45 paulwong 阅读(41367) | 评论 (1)编辑 收藏

Java EE 应用开发平台 Koala

Koala (考拉) 是一款应用在 Java EE 企业级应用开发领域,用于帮助架构师简化系统设计,降低框架耦合度,提高系统灵活性,提供开发工程师工作效率,降低成本的平台工具。

为什么使用 Koala:

  • 开源免费的开发平台,允许你任意修改源码并扩展功能
  • 以DDD领域驱动思想为核心,抛弃传统的以数据库为中心的四层编码模型
  • 丰富的基础组件支持,包括:国际化、异常、缓存等
  • 向导式的搭建项目过程,支持各种技术选择,JPA,Mybstis,SpringMVC,struts2MVC等
  • 向导式的数据库到实体的生成过程
  • 向导式的实体生成CURD功能
  • 向导式的服务发布一键无缝发布成war、EJB、webservice(SOAP/REST) 多种服务形式
  • 基于RBAC3模型的权限子系统
  • 监控子系统轻松协助你监控URL,方法,数据库,内存等状态
  • 使用通用查询子系统轻松定制完成查询功能
  • 基于IP过滤,用户名验证及方法权限控制的WS安全子系统
  • 基于JBPM5的流程子系统

http://wiki.openkoala.org/pages/viewpage.action?pageId=3932164

posted @ 2014-04-17 09:18 paulwong 阅读(678) | 评论 (0)编辑 收藏

微信公众平台开发资源

http://blog.csdn.net/lyq8479/article/category/1366622/2

微信JAVA工具集
https://github.com/chanjarster/weixin-java-tools






posted @ 2014-04-09 21:57 paulwong 阅读(337) | 评论 (0)编辑 收藏

javaee7-samples

http://git.oschina.net/ld/javaee7-samples

posted @ 2014-04-06 08:33 paulwong 阅读(559) | 评论 (0)编辑 收藏

也谈基于Web的含工作流项目的一般开发流程(转)

该项目包含的通用模块代码等我有时间一并剥离贡献出来(基于WebSocket的通知引擎,工作流整合模块,自定义表单(详见这里),基于RBAC权限设计),最近太忙了,Web项目有一段时间没碰,有点生疏的感觉,主要在忙GQT项目,一套基于桌面开发的框架,详见这里,写代码写的有点手酸的感觉。  

基于Web的含工作流的项目看起来并不如想象的那么简单,主要需求:
  1. 灵活定制工作流,并跟踪流程进度;
  2. 每个Order含有历史轨迹记录,可在历史中查看;
  3. 工作流的Action灵活,认领任务不一定非要先提取表单,因为很多节点都只有几个动作,直接按钮操作即可;
  4. 待办事宜列表在不刷新页面情况下也能变动;
项目要求:
  1. 操作简单高效;
  2. 权限细节到按钮级别;
  3. 并发数少,不超过3000个在线用户;
主要可能使用到技术:
  1. 工作流引擎,我这里选用Activiti5,很灵活好用;
  2. 权限使用Spring Security,基于标签式管理权限很方便;
  3. 通知引擎使用WebSocket,基于Flash实时通信,基于socket.io;
  4. 权限粒度基于经典的RBAC;
  5. 总体框架Spring MVC+Mybatis;
实现的WebSocket的总体思路:
  1. WebSocket Server独立于Web项目,Web Server与WebSocket Server之间的局域网通信基于简单的Socket通信,这样这个组件可以完全解耦和通用;
  2. 当Web项目要Push消息到Client时,通过Web Server的Socket Client向WebSocket Server的Socker Server发送消息,然后WebSocket Server收到消息后解码,广播到所有浏览器;
我们实现的事件通知非常简单,设定全局变量并让浏览器侦听:
var G_WebSocket=false; 
var EVENT_ORDER_CHANGE_STATUS = "orderChange";
var EVENT_ORDER_CHANGE_AMOUNT = "amountChange";
var EVENT_ORDER_CHANGE_REFUND = "refundChange";
WebSocket.init = function(callbackFunc){
socket = io.connect(connUrl, connOptions);
socket.on('connect', function() {
G_WebSocket=true;
callbackFunc("connect",null);
});
socket.on('disconnect', function() {
G_WebSocket=false;
callbackFunc("disconnect",null);
});
socket.on('clientQuit', function(obj){
G_WebSocket=false;
callbackFunc("clientQuit",obj);
});
socket.on('broadcast', function(obj) {
callbackFunc("broadcast",obj);
});
};
 
在需要侦听WebSocket接受Web Server推送消息的地方加上一个函数即可:
	WebSocket.init(function(command,jsonObj){ 
if(command=="broadcast"){
if(jsonObj.e == EVENT_ORDER_CHANGE_STATUS){
//TODO:write your code here
}else if(jsonObj.e == EVENT_ORDER_CHANGE_AMOUNT){
//TODO:write your code here
}else if(jsonObj.e == EVENT_ORDER_CHANGE_REFUND){
//TODO:write your code here
}
}
});

这样的结构要扩展推送服务很简单,比如按频道推送等,都可以很容易的扩展。
再看看看工作流,我们实现了activiti通用的申请提交任务流程和自定义表单功能,提取跟踪流程图功能等,这样你要设计一个新流程也变得非常简单,只需要在eclipse里划上工作流图,在后台发布,然后通过SpringMVC的RestAPI启动实例流程,申领完成任务等,如下图:




流程走到了分支的两个节点上,这样对后续新增的工作流提供了极大的遍历。

最后说说Spring Security,基于RBAC的权限体系搭建好后(可以用在任何管理系统中),要在页面中访问一个资源,首先判断一下是否有权限,如下HTML:


<sec:authorize ifAllGranted="r_pd"> 
<a href="#">resource access here</a>
</sec:authorize>

 

<sec:authorize url="/XXX/XXX/XXX.html"> 
<a href="XXX/XXX/XXX.html'">
<span>XXX功能</span>
</a>
</sec:authorize>

  

前台由于项目比较小,没有用到js的MVC框架,如backbone等,这里就不再记录了。

posted @ 2014-04-04 08:23 paulwong 阅读(548) | 评论 (0)编辑 收藏

仅列出标题
共112页: First 上一页 51 52 53 54 55 56 57 58 59 下一页 Last