分类目录归档:Java

andriod读取php的json时出现的bom问题

总是提示项目解析json数据时发现报
10-12 02:36:35.964: W/System.err(323): org.json.JSONException: Value  of type java.lang.String cannot be converted to JSONObject
错误异常,无论更改header的编码还是用纯英文数据都依然提示,搜索一下错误提示,发现有人说是记事本(notepad.exe)保存的php文件保存时带有bom头,解决方案大概有下面几种:
1.继续用记事本保存成ansi就没问题了;
2.换个编辑器重新保存;
3.前面两种情况还是防不胜防,据说在andriod4.0里已有解决方案:
[java]
public JSONTokener(String in) {
// consume an optional byte order mark (BOM) if it exists
if (in != null && in.startsWith("\ufeff")) {
in = in.substring(1);
}
this.in = in;
}
[/java]
具体用法类似
[java]
String json = "{"
+ " \"query\": \"Pizza\", "
+ " \"locations\": [ 94043, 90210 ] "
+ "}";

JSONObject object = (JSONObject) new JSONTokener(json).nextValue();
String query = object.getString("query");
JSONArray locations = object.getJSONArray("locations");
[/java]

java调用.net webservice的完整实例

Java客户端调用Web Service的一般有以下三种方式:
生成的stub、proxy(动态代理)以及dispatch(动态调用接口)。dispatch又分为payload和message两种方式。
这个实例仅就dispatch的message方式进行介绍。

C#代码
[csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Services.Description;

namespace WebService1
{
/// <summary>
/// Service1 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
// [System.Web.Script.Services.ScriptService]
[SoapDocumentService(RoutingStyle = SoapServiceRoutingStyle.RequestElement)]
public class Service1 : System.Web.Services.WebService
{

[WebMethod]
public string HelloWorld(string strHost)
{
return "Hello World, "+strHost;
}
}
}
[/csharp]

Java调用程序
[java]
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.soap.SOAPBinding;

public class WebServiceTest {

/**
* @param args
*/
public static final String targetNamespace = "http://tempuri.org/";
//服务名
public static final String serName = "Service1";
//端口名
public static final String pName = "5756";
//服务地址
public static final String endpointAddress = "http://localhost:5756/Service1.asmx?wsdl";
//方法名
public static final String OPER_NAME = "HelloWorld";
//参数名
public static final String INPUT_NMAE = "strHost";

public static void main(String[] args) throws Exception {
QName serviceName = new QName(targetNamespace, serName);
QName portName = new QName(targetNamespace, pName);

javax.xml.ws.Service service = Service.create(serviceName);
service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);

Dispatch<SOAPMessage> dispatch = service.createDispatch(portName,
SOAPMessage.class, Service.Mode.MESSAGE);

BindingProvider bp = (BindingProvider) dispatch;
Map<String, Object> rc = bp.getRequestContext();
rc.put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
rc.put(BindingProvider.SOAPACTION_URI_PROPERTY, OPER_NAME);
MessageFactory factory = ((SOAPBinding)bp.getBinding()).getMessageFactory();

SOAPMessage request = factory.createMessage();
SOAPBody body = request.getSOAPBody();
QName payloadName = new QName(targetNamespace, OPER_NAME);
SOAPBodyElement payload = body.addBodyElement(payloadName);

SOAPElement message = payload.addChildElement(INPUT_NMAE);
message.addTextNode("xyz");
SOAPMessage reply = null;

try
{
reply = dispatch.invoke(request);
}
catch (WebServiceException wse)
{
wse.printStackTrace();
}
SOAPBody soapBody = reply.getSOAPBody();
SOAPBodyElement nextSoapBodyElement = (SOAPBodyElement)soapBody.getChildElements().next ();
SOAPElement soapElement = (SOAPElement)nextSoapBodyElement.getChildElements().next();

System.out.println("获取回应信息为:" + soapElement.getValue());
}
}
[/java]

java调用c#写的webservice,服务器未能识别 HTTP 头 SOAPAction 的值[转]

今天用CXF去调用.net写的一个webservice服务报错,网上搜个解决办法,做个记录

服务器未能识别 HTTP 头 SOAPAction 的值 - 小玩子 - 世界任我行!

解决办法:服务器未能识别 HTTP 标头 SOAPAction 的值

本文主要探讨跨平台调用 Web Service 出现: ” 服务器未能识别 HTTP 标头 SOAPAction 的值 ” 的解决办法。

症状一:

Web Service + ASP.NET 应用程序部署到服务器默认目录中,在 IE 中用 http://< 服务器地址 >/< 程序目录名 >/< 默认启动页面名 > 发 生 “ 服务器未能识别 HTTP 标头 SOAPAction 的值 ” 错误。

症状二:

在 Java 平台上调用 .NET Web Service 的服务时,出现 ” 服务器未能识别 HTTP 标头 SOAPAction 的值 ” 。

症状三:

在 Java 平台下调用 .NET WEB Service ,出现数据时有时无。

解决对策:

给 .NET 的 WebService 类(即 .asmx 文件下的类)添加属性[SoapDocumentService(RoutingStyle=SoapServiceRoutingStyle.RequestElement)]

以下是NET代码,

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

namespace WebService
{
/// <summary>
/// Service1 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
// [System.Web.Script.Services.ScriptService]
  [SoapDocumentService(RoutingStyle = SoapServiceRoutingStyle.RequestElement)] 
public class Service1 : System.Web.Services.WebService
{

[WebMethod]
public string HelloWorld()
{
return “Hello World”;
}
[WebMethod]
public USER GetObj()
{
USER user = new USER();
user.Name = “习明凡”;
user.Pass = “123456″;
return user;
}
}
}

小知识:

什么是 SoapAction ?它在 WSDL 中有何作用?

SOAPAction HTTP request header 被用来标识 SOAP HTTP 请求的目的地,其值是个 URI 地址。 SOAP 发送并不限制格式、 URI 特征或其必须可解析,那么在这种情况下,发送一个 HTTP SOAP 请求时,其 HTTP 客户端必须使用 / 指明 SOAPAction HTTP request header 。

SOAPAction header 的内容可以被用在服务端,诸如:防火墙适当的过滤基于 HTTP 的 SOAP 请求消息等场景。 SOAPAction header 的值为空串 (“”) 表示 SOAP 消息的目的地由 HTTP 请求的 URI 标识;无值则表示没有指定这条消息的目的地。

java代码:
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.tempuri.Service1Soap;
import org.tempuri.USER;

public class Test {

public static void main(String[] args) {

JaxWsProxyFactoryBean soapFactoryBean = new JaxWsProxyFactoryBean();
soapFactoryBean.setAddress(“http://10.8.0.143/webservice/Service1.asmx“);
soapFactoryBean.setServiceClass(Service1Soap.class);
Object o = soapFactoryBean.create();
Service1Soap soap = (Service1Soap)o;
System.out.println(soap.helloWorld());

USER user = soap.getObj();
System.out.println(user.getName());
}
}

htmlunit出现com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException: Too much redirect for 错误

今天在抓取一个页面的时候,报了一个too much redirect for的异常,我的代码如下:

[java]
WebClient wc = new WebClient(BrowserVersion.FIREFOX_3_6);
wc.getOptions().setRedirectEnabled(true);
[/java]

看样是跳转太多,既然不能自动跳,那就一个一个跳吧。

[java]
HtmlPage loginPage = (HtmlPage)wc.getPage(loginUrl);
HtmlForm loginForm = (HtmlForm)loginPage.getHtmlElementById("loginForm");

HtmlInput username = loginForm.getInputByName("username");
HtmlInput password = loginForm.getInputByName("password");
HtmlInput submit = loginForm.getInputByValue("login");
username.setValueAttribute( "username");
password.setValueAttribute("password");
WebResponse response = submit.click().getWebResponse();
String location = response.getResponseHeaderValue("Location");
response = wc.getPage(location).getWebResponse();
[/java]

以此类推,终究能完成自动登录。

Htmlunit操作cookie

HtmlUnit has its mechanism to handle Cookies which is useful for our Web Application testing.

1. Enable/disable Cookies with HtmlUnit.

webClient.getCookieManager().setCookiesEnabled(true);//enable cookies

webClient.getCookieManager().setCookiesEnabled(false);//disable cookies
To see if Cookies is enabled:

webClient.getCookieManager().isCookiesEnabled();

2. Get Cookies values with HtmlUnit.

public String getCookieValue(String cookieName) {
Cookie cookie = webClient.getCookieManager().getCookie(cookieName);
if(cookie != null){
return cookie.getValue();
}
return “”;
}
Two other methods:

webClient.getCookieManager().getCookies(); //Returns the currently configured cookies, in an unmodifiable set.

webClient.getCookieManager().getCookies(URL url); //Returns the currently configured cookies applicable to the specified URL, in an unmodifiable set.

3. Set cookies values with HtmlUnit.

public void setCookieValue(String cookieName, String value){
Cookie cookie = new Cookie(cookieName, value);
this.webClient.getCookieManager().addCookie(cookie);
}
4. Remove Cookies with HtmlUnit.

public void removeCookies(String cookieName, String value){
Cookie cookie = new Cookie(cookieName, value);
webClient.getCookieManager().removeCookie(cookie);
}
To clear all cookies with HtmlUnit:

public void clearCookies(){
webClient.getCookieManager().clearCookies();
}

Tokyo Tyrant(ttserver) java api的安装【转】

Tokyo Tyrant(ttserver)的安装请看我的上一篇文章http://gqf2008.iteye.com/admin/blogs/366963

 

 

编译java api

http://tokyocabinet.sourceforge.net/javapkg/tokyocabinet-java-1.18.tar.gz

tar zxvf tokyocabinet-java-1.18.tar.gz

cd tokyocabinet-java-1.18

编译时一定要设置JAVA_HOME环境变量,不然会报找不到jni.h错误

export JAVA_HOME=…..

./configure

make

make install

编辑当前用户的环境变量,增加一下这些参数

CLASSPATH=$CLASSPATH:/usr/local/lib/tokyocabinet.jar

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

export CLASSPATH LD_LIBRARY_PATH

重新登陆让环境变量生效,或者执行source ~/.bashrc (ubuntu下是这个文件)

 

跑一下例子

cd example

javac *.java

java TCBDBEX

hop

bar:step

baz:jump

foo:hop

 

java TCFDBEX

one

1:one

12:twelve

144:one forty four

 

java TCHDBEX

hop

foo:hop

bar:step

baz:jump

转自:http://gqf2008.iteye.com/blog/372753

tokyotyrant-java客户端[转]

目录:

概述
演示
[一]、概述

java实现了对ttserver服务端的连接和访问。相关的源代码和jar包可以到其官网下载。

官网地址:http://code.google.com/p/tokyotyrant-java/

如果是maven构建项目的,在pom.xml 的节点中增加如下依赖配置即可:
[xml]
<dependency>
<groupId>tokyotyrant</groupId>
<artifactId>tokyotyrant</artifactId>
<version>0.11</version>
</dependency>
<dependency>
<groupId>org.jboss.netty</groupId>
<artifactId>netty</artifactId>
<version>3.1.5.GA</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.6</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
[/xml]
[二]、演示

1.RDB :官方Tokyo Tyrant API的实现

演示代码:RDBExample.java

[java]
package com.micmiu.nosql.ttserver;

import java.io.IOException;
import java.net.InetSocketAddress;

import tokyotyrant.RDB;
import tokyotyrant.transcoder.DoubleTranscoder;
import tokyotyrant.transcoder.IntegerTranscoder;

/**
*
* blog http://www.micmiu.com
*
* @author Michael
*
*/
public class RDBExample {

public static void main(String[] args) throws IOException {

RDB db = new RDB();
try {
// connect to the server
// db.open(new NodeAddress("tcp://192.168.126.134:1978"));
db.open(new InetSocketAddress("192.168.126.134", 1978));

Object key;
Object value;
// store records
if (db.put("my_firstname", "Sun")) {
System.out.println("db put my_firstname successful.");
} else {
System.out.println("db put my_firstname error.");
}

if (db.put("my_lastname", "Michael")) {
System.out.println("db put my_lastname successful.");
} else {
System.out.println("db put my_lastname error.");
}

if (db.put("my_blogurl", "www.micmiu.com")) {
System.out.println("db put my_blogurl successful.");
} else {
System.out.println("db put my_blogurl error.");
}

if (db.put("my_weibo", "www.sina.com/ctosun")) {
System.out.println("db put my_weibo successful.");
} else {
System.out.println("db put my_weibo error.");
}

// retrieve records
value = db.get("my_blogurl");
System.out.println("test_blogurl =: " + value);

value = db.get("test_noexit");
System.out.println("test_noexit =: " + value);

System.out.println("===== test repeat put ");
db.put("test_desc", "hello world");
System.out.println("test_desc =: " + db.get("test_desc"));
db.put("test_desc", "repeat put value is hello Michael");
System.out.println("test_desc =: " + db.get("test_desc"));

// Initialize the iterator
System.out.println("===== access all key ");
db.iterinit();
while ((key = db.iternext()) != null) {
value = db.get(key);
System.out.println(key + " =: " + value);
}
System.out.println("===== test int double ");
// add int
db.put("int_i", 3, new IntegerTranscoder());
int i = db.addint("int_i", 4);
System.out.println(" i =: " + i);
System.out.println("int_i =: "
+ db.get("int_i", new IntegerTranscoder()));

// add double
db.put("dou_d", 3.0D, new DoubleTranscoder());
double d = db.adddouble("dou_d", 4.0D);
System.out.println(" d =: " + d);
System.out.println("dou_d =: "
+ db.get("dou_d", new DoubleTranscoder()));

} catch (Exception e) {
e.printStackTrace();
} finally {
// close the connection
db.close();
}
}
}
[/java]
运行日志如下:

db put my_firstname successful.
db put my_lastname successful.
db put my_blogurl successful.
db put my_weibo successful.
test_blogurl =: www.micmiu.com
test_noexit =: null
===== test repeat put
test_desc =: hello world
test_desc =: repeat put value is hello Michael
===== access all key
my_firstname =: Sun
my_lastname =: Michael
my_blogurl =: www.micmiu.com
my_weibo =: www.sina.com/ctosun
test_desc =: repeat put value is hello Michael
===== test int double
i =: 7
int_i =: 7
d =: 7.0
dou_d =: 7.0

2.MRDB :用于多数据源,可复制、可靠性高、响应快等特点

演示代码:MRDBExample.java

[java]
package com.micmiu.nosql.ttserver;

import tokyotyrant.MRDB;
import tokyotyrant.networking.NodeAddress;

/**
*
* blog http://www.micmiu.com
*
* @author Michael
*
*/
public class MRDBExample {

/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {

MRDB db = null;
try {
db = new MRDB();
// connect to the server
db.open(NodeAddress.addresses("tcp://192.168.126.134:1978"));
Object value;
// store records
if (db.await(db.put("my_firstname", "Sun"))) {
System.out.println("MRDB put my_firstname successful.");
} else {
System.out.println("MRDB put my_firstname error.");
}

if (db.await(db.put("my_lastname", "Michael"))) {
System.out.println("MRDB put my_lastname successful.");
} else {
System.out.println("MRDB put my_lastname error.");
}

if (db.await(db.put("my_blogurl", "www.micmiu.com"))) {
System.out.println("MRDB put my_blogurl successful.");
} else {
System.out.println("MRDB put my_blogurl error.");
}

if (db.await(db.put("my_weibo", "www.sina.com/ctosun"))) {
System.out.println("MRDB put my_weibo successful.");
} else {
System.out.println("MRDB put my_weibo error.");
}

// retrieve records
value = db.await(db.get("my_blogurl"));
System.out.println("test_blogurl =: " + value);

value = db.await(db.get("test_noexit"));
System.out.println("test_noexit =: " + value);

System.out.println("===== test repeat put ");
db.put("test_desc", "hello world");
System.out.println("test_desc =: " + db.await(db.get("test_desc")));
db.put("test_desc", "repeat put value is hello Michael");
System.out.println("test_desc =: " + db.await(db.get("test_desc")));

// add int
db.put("int_i", 4);
// add double
db.put("dou_d", 8.8D);

// Initialize the iterator
System.out.println("===== access all key ");
Object[] keys = db
.await(db.fwmkeys("", db.size().get().intValue()));
for (Object keyObj : keys) {
System.out.println(keyObj + " =: " + db.await(db.get(keyObj)));
}

} catch (Exception e) {
e.printStackTrace();
} finally {
// close the connection
db.close();
}
}
}
[/java]
运行结果:

[16:42:42] INFO [tokyotyrant.networking.nio.NioNode] – Connect tcp://192.168.126.134:1978
MRDB put my_firstname successful.
MRDB put my_lastname successful.
MRDB put my_blogurl successful.
MRDB put my_weibo successful.
test_blogurl =: www.micmiu.com
test_noexit =: null
===== test repeat put
test_desc =: hello world
test_desc =: repeat put value is hello Michael
===== access all key
my_firstname =: Sun
my_lastname =: Michael
my_blogurl =: www.micmiu.com
my_weibo =: www.sina.com/ctosun
int_i =: 4
test_desc =: repeat put value is hello Michael
dou_d =: 8.8
[16:42:42] INFO [tokyotyrant.networking.nio.NioNode] – Disconnect tcp://192.168.126.134:1978
[16:42:42] INFO [tokyotyrant.networking.nio.NioNetworking] – Stopped. So will not handle IO. 0 keys will be ignored
————————

转自:http://www.micmiu.com/nosql/tokyotyrant-java-client/

麻雀虽小,五脏俱全:JSR311让Restful WebService变简单[转]

需求
公司有一个产品,包括前台WEB界面和多个后台服务,各个服务都需要在前面界面中进行配置和控制,以调整服务的行为。以前,配置文件都存放在数据库中,界面上修改配置后入库,并发送消息(Socket)通知特定的服务重新加载配置。这样有些问题,一方面自己维护Socket带来很多麻烦,二来数据库重建的时候,需要备份/恢复这些配置数据。

所以,我们想把配置文件局部化到各个服务(比如用本地文件存储),然后在界面上修改的时候,实时向服务请求当前配置数据(XML格式),修改完毕后,再直接发给服务进行更新和存储。而在通信方式上,我们希望各个服务提供Web Service接口来实现配置的检索和更新。

但Web Service通常需要在Web Container(比如,tomcat, jboss)中实现,而我们不想把所有的服务都跑在tomcat里,于是想找到一种更加轻量级的方式。

今天偶然看到JSR311,进而发现在Java后台服务中内嵌grizzly(基于NIO的实现)和Jersey(Sun的JSR311参考实现)来提供Restful Web Service能力,是非常方便的。个人认为这种方式适用于后台Java程序的控制、配置和监视,其作用有些类似于JMX,但比实现JMX要简单的多(JSR311基于POJO)。

背景知识
Representational state transfer (REST) Web Service:
它是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。在目前三种主流的Web Service实现方案中,因为REST与SOAP和XML-RPC相比显的更加简洁,因此越来越多的Web Service开始采用REST风格设计和实现。

参考资料:http://en.wikipedia.org/wiki/Representational_State_Transfer

Jersey:
它是Sun对JSR311的官方参考实现,而JSR311是java中实现Restful Web Service的API规范(JSR311: JAX-RS: The Java API for RESTful Web Services)。JSR311有一个重要目标:使用注解(annotation)把POJO暴露成Web Service,这样就比较轻量级。

参考资料:https://jsr311.dev.java.net/nonav/releases/1.0/spec/index.html

Grizzly:
Grizzly于2004年诞生在GlassFish中,开始目的是要建构一个HTTP Web服务器,用来代替Tomcat的Coyote连接器和Sun WebServ er6.1。后来,Grizzly成为一种应用程序框架,专门解决编写成千上万用户访问服务器时候产生的各种问题。使用JAVA NIO作为基础,并隐藏其编程的复杂性。在本例中,我们将其用作内嵌的Servlet Container。

参考资料:https://grizzly.dev.java.net/

准备工作
首先,下载grizzly和jersey。其中,grizzly的下载地址为:http://download.java.net/maven/2/com/sun/grizzly/grizzly-servlet-webserver/1.9.18a/grizzly-servlet-webserver-1.9.18a.jar,jersey的下载地址为:http://download.java.net/maven/2/com/sun/jersey/jersey-archive/1.1.2-ea/jersey-archive-1.1.2-ea.zip

在Eclipse中建一个Java工程,名为jsr331,然后把下载的jersey-archive-1.1.2-ea.zip解压,将jersey-archive-1.1.2-ea/contribs、jersey-archive-1.1.2-ea/lib两个目录下的jar包,连同下载的grizzly-http-webserver-1.9.18a.jar都拷贝到jsr331工程下的lib目录,并加入到该工程的Build Path。(实测中,发现还需要引入一个包,下载地址:http://repository.jboss.org/maven2/org/jvnet/mimepull/1.2/mimepull-1.2.jar)

编写最简单的服务
JSR331把准备提供Web Service的类称为Resource class。Resource class是一个普通类(POJO),但是按照规范要求增加了特定的注解(annotation)。我们首先实现最简单的hello world服务。

在jinxfei.test.jsr311.service下,建立HelloService类,内容如下:

 

[java][/java] view plaincopy

  1. package jinxfei.test.jsr311.service;  
  2.   
  3. import javax.ws.rs.GET;  
  4. import javax.ws.rs.Path;  
  5. import javax.ws.rs.Produces;  
  6.   
  7. @Path(“/hello”)  
  8. public class HelloService {  
  9.     @GET   
  10.     @Produces(“text/plain”)  
  11.     public String helloWorld(){  
  12.         return ”Hello world!”;  
  13.     }     
  14. }  

 

代码中的注解(annotation)决定了程序发布成Web Service后的行为和特性。其中,HelloService类前面的@PATH,表明该Service的URL路径,这种类名前面带@PATH注解的类被称为Root Resource Class,因为他们决定了访问Service时URI中的第一级路径;@GET表示访问该服务使用HTTP GET方法;@Produces规定该服务返回结果的类型,这里的”text/plain”表名返回纯文本。

发布服务
实现服务类后,我们要启动一个内嵌的grizzly servlet container,并把HelloService发布到该Container中,这样就能通过HTTP协议访问该服务。Jersey提供了两种发布方式,标准的做法需要在web.xml中做配置,所以比较适用于部署在独立的Web Container下的应用,本文不做深入介绍,可参见:http://docs.sun.com/app/docs/doc/820-4867/6nga7f5o4?l=en&a=view。本例与grizzly整合,所以使用grizzly的工具类,通过代码进行部署配置。

在jinxfei.test.jsr311包下创建ServiceDeployer类,内容如下:

 

[java][/java] view plaincopy

  1. package jinxfei.test.jsr311;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.URI;  
  5. import java.util.HashMap;  
  6. import java.util.Map;  
  7. import javax.ws.rs.core.UriBuilder;  
  8. import com.sun.grizzly.http.SelectorThread;  
  9. import com.sun.jersey.api.container.grizzly.GrizzlyWebContainerFactory;  
  10.   
  11. public class ServiceDeployer {  
  12.       
  13.     public static void main(String[] args) throws IOException {  
  14.         URI ServerURI=UriBuilder.fromUri(“http://localhost/”).port(9876).build();  
  15.         startServer(ServerURI);  
  16.         System.out.println(“服务已启动,请访问:”+ServerURI);  
  17.     }      
  18.       
  19.     protected static SelectorThread startServer(URI serverURI) throws IOException {  
  20.         final Map<String, String> initParams = new HashMap<String, String>();  
  21.         initParams.put(“com.sun.jersey.config.property.packages”,”jinxfei.test.jsr311.service”);  
  22.         System.out.println(“Grizzly 启动中…”);  
  23.         SelectorThread threadSelector = GrizzlyWebContainerFactory.create(serverURI, initParams);       
  24.         return threadSelector;  
  25.     }      
  26. }  

代码很简单,其中:initParams.put(“com.sun.jersey.config.property.packages” , “jinxfei.test.jsr311.service”); 这一行的第二个参数表明服务实现类所在的包名,系统会自动搜索做了注解的类并将其发布成服务。

 

在Eclipse中运行该类,控制台上打印“服务已启动”字样,表示系统启动成功,打开浏览器,输入:http://localhost:9876/hello,即可看到效果,如下图所示:

clip_image002

让功能再强一点点
接下来,我们要让服务能够接受参数,并根据参数打印不同的信息,最简单的就是回显(Echo)。为了实现这一功能,我们给HelloService类增加一个方法:

 

[java][/java] view plaincopy

  1. @POST @Path(“echo”)
  2.     @Consumes(“application/x-www-form-urlencoded”)
  3.     public String echo(@FormParam(“msg”) String message){
  4.         return ”Are you saying:”+message;
  5.     }

 

@POST表明该方法要用HTTP Post来访问,@Path表明访问该方法的相对路径是echo,@Consumes表明该方法处理HTTP Post请求中何种类型的数据。该方法参数中的注解@FormParam(“msg”)说明后面的“String message”参数取自表单提交数据中的msg。

由于该方法需要Post访问,且需要通过表单提交数据,所以我们创建一个test.htm,在其中写一个简单的Form:

[xhtml][/xhtml] view plaincopy

  1. <form action=”http://localhost:9876/hello/echo” method=”post”>
  2. <input type=”text” name=”msg”>
  3. <input type=”submit” value=”submit”>
  4. </form>

 

重启ServiceDeployer,然后在浏览器中打开test.htm,表单中输入任意信息:
clip_image004

然后点提交按钮,可以看到如下信息:
clip_image006

这说明HelloService已经提取了表单参数,并回显给用户。

深入学习
请参考官方资料:
JSR311规范:https://jsr311.dev.java.net/nonav/releases/1.0/spec/index.html
JSR311参考实现的主要特性:http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features

转自:http://blog.csdn.net/jinxfei/article/details/4714809

如何保证一个项目可持续集成发布[转]

这俩天稍微有点空,赶紧补补功课。

持续集成就是利用所谓的cc,cruisecontrol工具对我们的项目进行持续的测试,得以保证项目可以保持持续的可发布状态。

但是光靠一个cc,肯定是无法解决这个问题的,还需要一套机制,这个就是敏捷管理。
需要我们把项目的需要开始调研做起,就要专业有深度,过程一丝不苟,进行严格的质量管控和结果输出,对于正式发布上线要严肃认真做好各种意外准备。从代码角度而言,要保证代码必须有测试代码,测试代码必须达到一定的覆盖率才有意义。而测试代码的加入必须意味着我们的项目必须层次清晰,结构分明,即所谓的mvc分层体系,方便测试用例针对各个层次进行不同的场景模拟和测试。

集成员通过配置CruiseControl工具,可以将部分较为简单、不需要人工干预和希望经常重复执行的集成工作交给工具来自动完成。集成员可以配置多个持续集成项目,包括若干个多人同时在开发的子构件、最终发布的集成包等。
CruiseControl在活动时段,循环执行各构建周期,包含:引导初始化—〉检测源码变化—〉集成构建—〉单元测试—〉发布构建和测试结果等步骤。
每当实施员在私有开发工作站上,将源码检入(Checkin)、加入源码控制(Add to Source Control)、或者向集成流(Stream)提交成果(delivery)时,CruiseControl在随后的构建周期循环中,将通过检测源码变化步骤检测到这一变化,CruiseControl此时会等待预定的间隔,看看是否有新的源码变化出现,避免实施员批量检入或加入源码控制时遗漏后续变更;CruiseControl开始调用Ant封装(wrapper)配置文件执行构建,它首先更新目标源码目录下的所有内容(调用ClearCase ccupdate指令),以同步变化的源码,再进行编译、链接,完成预定的冒烟测试,并将结果记录到相应的日志中;CruiseControl在构建完成后,通过e-mail将成功或失败的结果通知提交源码变更的实施员、以及指定的其他人员,并生成构建报告网页,相关人员通过e-mail接受通知的同时,也可以登陆CruiseControl的发布网页来浏览构建报告详细信息。

其他方面就不说了。附上一些关于cc的使用注意点。

CC可能需要用到下面一些工具
Ø CruiseControl
Ø Tomcat 或者 JETTY
Ø VisualSVN server
Ø Svnant
Ø svn-win32-1.6.5.zip
Ø TortoiseSVN(可选)
Ø Eclipse + subclipse插件(可选)

CC主要就是利用JAVA的一些特性和ANT工具以及SVN对我们的项目进行自动编译,自动检验,自动测试,自动生成一些测试报告,自动部署发布的一系列工作的应用程序。

linux下的部署反而相对方便些,在window下需要主要引入SVN的环境变量,否则无法使用SVN自动更新,windown下安装Subversion,然后把bin路径加入到环境变量中区,在cmd中输入svn试试,如果有结果说明SVN环境已经安装成功,然后就可以在config.xml中构建我们的CC环境。

CC主要包括几个东西,一个是时间控制器,用于管理执行的时间要求。一个是ANT的脚本的调用,可以调用具体的项目中的target任务执行。一个是java工具的使用,包括编译、打包等。一个是LOG日志的输出,可以产生各种格式的报表日志。另外支持一些插件,比如htmlmail插件,支持自动发送结果邮件到具体的邮箱。另外CC包括一个控制台,在控制台中可以查看各个项目执行测试的结果。

不说了,这个工具很重要,用过的人都知道的。

转自:http://xosadan.iteye.com/blog/1068938