`
hdxiong
  • 浏览: 371788 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

SPRING-REST和CXF-REST实现过程中的系列问题

    博客分类:
  • Java
阅读更多
1、mybatis 数字用$,字符用#

2、cxf 关于JSONProvider 返回单个对象数组的问题。
app-rest.xml配置
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:jaxrs="http://cxf.apache.org/jaxrs"
	xsi:schemaLocation="
	http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/util
	http://www.springframework.org/schema/util/spring-util.xsd
	http://cxf.apache.org/jaxrs
	http://cxf.apache.org/schemas/jaxrs.xsd
	http://cxf.apache.org/core 
	http://cxf.apache.org/schemas/core.xsd">

	<import resource="classpath:META-INF/cxf/cxf.xml" />
	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
	<import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml" />

	<util:list id="jsonKeys">
		<value>app</value>
		<value>comment</value>
	</util:list>

	<util:list id="jsonTypes">
		<value>application/json</value>
		<value>application/jettison</value>
	</util:list>

	<bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.JSONProvider">
		<property name="arrayKeys" ref="jsonKeys" />
		<property name="serializeAsArray" value="true" />
		<property name="produceMediaTypes" ref="jsonTypes" />
		<property name="consumeMediaTypes" ref="jsonTypes" />
	</bean>

	<jaxrs:server id="commonsService" address="/">
		<jaxrs:extensionMappings>
			<entry key="json" value="application/json" />
			<entry key="xml" value="application/xml" />
		</jaxrs:extensionMappings>
		<jaxrs:serviceBeans>
			<ref bean="commentsServiceImpl" />
			<ref bean="userServiceImpl" />
			<ref bean="postServiceImpl" />
			<ref bean="contentRestImpl" />
			<ref bean="collectListRestImpl" />
			<ref bean="downloadListRestImpl" />
			<ref bean="rankServiceRestImpl" />
			<ref bean="appAddImpl" />
			<ref bean="appPush" />
		</jaxrs:serviceBeans>
		<jaxrs:providers>
			<ref bean="jsonProvider" />
		</jaxrs:providers>
	</jaxrs:server>
</beans>

javabean代码
import java.io.Serializable;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;

import sgh.comment.base.model.Comments;

//评论列表
@XmlAccessorType(XmlAccessType.FIELD)
public class CommentsResult implements Serializable {

	private static final long serialVersionUID = -6304211106650057160L;

	/**
	 * 总条数
	 */
	public Integer totalCount;
	
	/**
	 * 总页数
	 */
	public Integer totalPage;
	
	/**
	 * APP评论
	 */
	@XmlElement(name="comment")
	public List<Comments> commentList;
}

相关源代码参见截图:



备注:
a.arrayKeys和serializeAsArray组合使用,serializeAsArray=true表示arrayKeys中提到的属性值都以数组形式返回,解决单条数据不以数组形式返回的问题。
b.arrayKeys是值需要以数组形式返回的属性名字。如上是comment而不是commentList。

4、cxf关于数字类型的字符串自动被去掉引号的问题。
具体原因参见:org.codehaus.jettison.mapped.DefaultConverter和org.codehaus.jettison.mapped.SimpleConverter
方法1:SimpleConverter的实现去重写DefaultConverter。
方法2:修改配置使其默认用SimpleConverter即可。具体怎么配置目前还不知道。

5、spring mvc rest空对象也被返回的问题。
<property name="defaultViews">
	<list>
		<!-- for application/json -->
		<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
			<!-- 重新设置 objectMapper -->
			<property name="objectMapper">
				<bean class="org.codehaus.jackson.map.ObjectMapper">
					<!-- 设置objectMapper的serializationConfig的serializationInclusion属性,以忽略null对象 ,也可在vo上注解@JsonWriteNullProperties(false)-->
					<property name="serializationConfig.serializationInclusion">
						<value type="org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion">NON_NULL</value>
					</property>
				</bean>
			</property>
		</bean>
		
		<!-- for application/jsonp -->
		<bean class="org.springframework.web.servlet.view.jsonp.MappingJacksonJsonpView">
			<!-- 重新设置 objectMapper -->
			<property name="objectMapper">
				<bean class="org.codehaus.jackson.map.ObjectMapper">
					<!-- 设置objectMapper的serializationConfig的serializationInclusion属性,以忽略null对象 ,也可在vo上注解@JsonWriteNullProperties(false)-->
					<property name="serializationConfig.serializationInclusion">
						<value type="org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion">NON_NULL</value>
					</property>
				</bean>
			</property>
		</bean>
		
		<!-- for application/xml -->
		<!-- 
		<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
			<property name="marshaller" ref="castorMarshaller" />
		</bean>
		-->
	</list>
</property>


6、spring mvc rest支持jsonp的问题。
<!-- 设置为true以忽略对Accept Header的支持,默认false -->
<property name="ignoreAcceptHeader" value="false" />
<!-- 设置为true以开启对扩展名支持,默认true -->
<property name="favorPathExtension" value="true" />
<!-- 用于开启 /userinfo/123?format=json的支持,默认false -->
<property name="favorParameter" value="true" />
<!-- 在没有扩展名和参数时即: "/user/1" 时的默认展现形式 -->
<property name="defaultContentType" value="application/xml" />
<property name="mediaTypes">
	<map>
		<entry key="xml" value="application/xml" />
		<entry key="json" value="application/json" />
		<entry key="jsonp" value="application/javascript"/>
	</map>
</property>

重写MappingJacksonJsonpView 类
package org.springframework.web.servlet.view.jsonp;

import org.springframework.web.servlet.view.json.MappingJacksonJsonView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

public class MappingJacksonJsonpView extends MappingJacksonJsonView {

	/**
	 * Default content type. Overridable as bean property.
	 */
	public static final String DEFAULT_CONTENT_TYPE = "application/javascript";

	@Override
	public String getContentType() {
		return DEFAULT_CONTENT_TYPE;
	}

	/**
	 * Prepares the view given the specified model, merging it with static
	 * attributes and a RequestContext attribute, if necessary. Delegates to
	 * renderMergedOutputModel for the actual rendering.
	 * 
	 * @see #renderMergedOutputModel
	 */
	@Override
	public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
		if ("GET".equals(request.getMethod().toUpperCase())) {
			@SuppressWarnings("unchecked")
			Map<String, String[]> params = request.getParameterMap();
			if (params.containsKey("callback")) {
				response.getOutputStream().write(new String(params.get("callback")[0] + "(").getBytes());
				super.render(model, request, response);
				response.getOutputStream().write(new String(");").getBytes());
				response.setContentType("application/javascript");
			} else {
				super.render(model, request, response);
			}
		} else {
			super.render(model, request, response);
		}
	}
}


7、cxf rest 支持jsonp的问题。
参见:http://cxf.apache.org/docs/jax-rs-data-bindings.html#JAX-RSDataBindings-JSONWithPadding%28JSONP%29
One option for supporting "JSON With Padding" (JSONP) is to extend the default JSONProvider and override its writeTo method as follows:
@Produces("application/javascript")
class JsonpProvider extends JSONProvider {
		
    @Override
    public void writeTo(Object obj, Class<?> cls, Type genericType, Annotation[] anns, MediaType m, MultivaluedMap<String, Object> headers,
	OutputStream os) throws IOException {
	String prefix = getContext().getHttpServletRequest().getParameter("_jsonp");
	boolean hasPrefix = !isEmpty(prefix);
	if(hasPrefix) {
	    os.write(prefix.getBytes(HttpUtils.getSetEncoding(m, headers, "UTF-8")));
	    os.write('(');
	}
	super.writeTo(obj, cls, genericType, anns, m, headers, os);
	if(hasPrefix) {
		os.write(')');
	}
    }
}

Similar approach can work when Jackson is used.
Alternatively, a custom servlet filter can be used to support JSONP. Please read the Supporting JSONP blog post for more information.
Starting from CXF 2.3.4 and 2.4.0, JSONP can be supported with the help of CXF in/out interceptors:
<jaxrs:server id="bookJsonp" address="/jsonp">
    <jaxrs:serviceBeans>
      <ref bean="serviceBean" />
    </jaxrs:serviceBeans>		  

    <jaxrs:inInterceptors>
       <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpInInterceptor"/>
    </jaxrs:inInterceptors>
    <jaxrs:outInterceptors>
       <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpPreStreamInterceptor"/>
       <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpPostStreamInterceptor"/>
    </jaxrs:outInterceptors> 
</jaxrs:server>

JsonpInInterceptor checks if a JSONP callback query parameter is available (default is _jsonp) and if yes then it saves its value on the current exchange for out interceptors to know if they have to write the paddings or not. The name of the expected callback parameter can be customized. JsonpPreStreamInterceptor and JsonpPostStreamInterceptor ensure the actual JSON stream is 'padded' properly. JsonpPreStreamInterceptor will also set Content-Type to "application/x+javascript" by default but this can be changed:
<jaxrs:server id="bookJsonp" address="/jsonp">
    <jaxrs:serviceBeans>
      <ref bean="serviceBean" />
    </jaxrs:serviceBeans>		  

    <jaxrs:inInterceptors>
       <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpInInterceptor">
          <property name="callbackParam" value="myjsonp"/>
       </bean> 
    </jaxrs:inInterceptors>
    <jaxrs:outInterceptors>
       <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpPreStreamInterceptor">
           <property name="mediaType" value="text/x+javascript"/>
       </bean>
       <bean class="org.apache.cxf.jaxrs.provider.jsonp.JsonpPostStreamInterceptor">
           <!-- default is ');' -->
           <property name="paddingEnd" value=")"/>
       </bean>
    </jaxrs:outInterceptors> 
</jaxrs:server>


8、关于ThreadLocal与线程池的问题。
Web服务器使用线程池,所以会有重用线程的问题,而ThreadLocal是根据线程ID来区分的。
http://blog.csdn.net/comliu/article/details/3186778
http://hi.baidu.com/sqxxr/item/e9946b34427c5ec02e8ec294

9、安装tomcat支持apr
cd /usr/local/apache-tomcat-6.0.18/bin/tomcat-native-1.1.14-src/jni/native/
 ./configure --prefix=/usr/local/apr
 ./configure --with-apr=/usr/local/apr
 make
 make install

http://blog.163.com/chhj_292/blog/static/12229472008101434124476/
  • 大小: 44.9 KB
  • 大小: 43.8 KB
  • 大小: 41.7 KB
分享到:
评论
2 楼 fengfujie 2013-08-07  
cxf rest 支持jsonp的问题。我按照你这个方式返回的数据是这样的怎么回事
callback(<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ats><city_list><city><adcode>100000</adcode><citycode></citycode><enable>1</enable><latitude>39.915085</latitude><longitude>116.3683244</longitude><name_en>The People's Republic of China</name_en><name_zh>中华人民共和国</name_zh><pinyin>ZhongHuaRenMinGongHeGuo</pinyin><short_code>ZHRMGHG</short_code></city><city><adcode>110000</adcode><citycode>010</citycode><enable>1</enable><latitude>39.904989</latitude><longitude>116.405285</longitude><name_en>Beijing City</name_en><name_zh>北京市</name_zh><pinyin>BeiJingShi</pinyin><short_code>BJ</short_code></city><city><adcode>110101</adcode><citycode>010</citycode><enable>1</enable><latitude>39.917544</latitude><longitude>116.418757</longitude><name_en>Dongcheng District</name_en><name_zh>东城区</name_zh><pinyin>DongChengQu</pinyin><short_code>DC</short_code></city><city><adcode>110102</adcode><citycode>010</citycode><enable>1</enable><latitude>39.915309</latitude><longitude>116.366794</longitude><name_en>Xicheng District</name_en><name_zh>西城区</name_zh><pinyin>XiChengQu</pinyin><short_code>XC</short_code></city><city><adcode>110105</adcode><citycode>010</citycode><enable>1</enable><latitude>39.921489</latitude><longitude>116.486409</longitude><name_en>Chaoyang District</name_en><name_zh>朝阳区</name_zh><pinyin>ChaoYangQu</pinyin><short_code>CY</short_code></city><city><adcode>110106</adcode><citycode>010</citycode><enable>1</enable><latitude>39.860337</latitude><longitude>116.312765</longitude><name_en>Fengtai District</name_en><name_zh>丰台区</name_zh><pinyin>FengTaiQu</pinyin><short_code>FS</short_code></city><city><adcode>110107</adcode><citycode>010</citycode><enable>1</enable><latitude>39.926085</latitude><longitude>116.186736</longitude><name_en>Shijingshan District</name_en><name_zh>石景山区</name_zh><pinyin>ShiJingShanQu</pinyin><short_code>SJS</short_code></city><city><adcode>110108</adcode><citycode>010</citycode><enable>1</enable><latitude>39.956074</latitude><longitude>116.310316</longitude><name_en>Haidian District</name_en><name_zh>海淀区</name_zh><pinyin>HaiDianQu</pinyin><short_code>HD</short_code></city><city><adcode>110109</adcode><citycode>010</citycode><enable>1</enable><latitude>39.937183</latitude><longitude>116.105381</longitude><name_en>Mentougou District</name_en><name_zh>门头沟区</name_zh><pinyin>MenTouGouQu</pinyin><short_code>MTG</short_code></city><city><adcode>110111</adcode><citycode>010</citycode><enable>1</enable><latitude>39.735535</latitude><longitude>116.139157</longitude><name_en>Fangshan District</name_en><name_zh>房山区</name_zh><pinyin>FangShanQu</pinyin><short_code>FS</short_code></city><city><adcode>110112</adcode><citycode>010</citycode><enable>1</enable><latitude>39.902486</latitude><longitude>116.658603</longitude><name_en>Tongzhou District</name_en><name_zh>通州区</name_zh><pinyin>TongZhouQu</pinyin><short_code>TZ</short_code></city><city><adcode>110113</adcode><citycode>010</citycode><enable>1</enable><latitude>40.128936</latitude><longitude>116.653525</longitude><name_en>Shunyi District</name_en><name_zh>顺义区</name_zh><pinyin>ShunYiQu</pinyin><short_code>SY</short_code></city><city><adcode>110114</adcode><citycode>010</citycode><enable>1</enable><latitude>40.218085</latitude><longitude>116.235906</longitude><name_en>Changping District</name_en><name_zh>昌平区</name_zh><pinyin>ChangPingQu</pinyin><short_code>CP</short_code></city><city><adcode>110115</adcode><citycode>010</citycode><enable>1</enable><latitude>39.755477</latitude><longitude>116.337733</longitude><name_en>Daxing District</name_en><name_zh>大兴区</name_zh><pinyin>DaXingQu</pinyin><short_code>DX</short_code></city><city><adcode>110116</adcode><citycode>010</citycode><enable>1</enable><latitude>40.324272</latitude><longitude>116.637122</longitude><name_en>Huairou District</name_en><name_zh>怀柔区</name_zh><pinyin>HuaiRouQu</pinyin><short_code>HR</short_code></city><city><adcode>110117</adcode><citycode>010</citycode><enable>1</enable><latitude>40.144783</latitude><longitude>117.112335</longitude><name_en>Pinggu District</name_en><name_zh>平谷区</name_zh><pinyin>PingGuQu</pinyin><short_code>PG</short_code></city><city><adcode>110228</adcode><citycode>010</citycode><enable>1</enable><latitude>40.377362</latitude><longitude>116.843352</longitude><name_en>Miyun County</name_en><name_zh>密云县</name_zh><pinyin>MiYunXian</pinyin><short_code>MY</short_code></city><city><adcode>110229</adcode><citycode>010</citycode><enable>1</enable><latitude>40.465325</latitude><longitude>115.985006</longitude><name_en>Yanqing County</name_en><name_zh>延庆县</name_zh><pinyin>YanQingXian</pinyin><short_code>YQ</short_code></city><city><adcode>120000</adcode><citycode>022</citycode><enable>1</enable><latitude>39.125596</latitude><longitude>117.190182</longitude><name_en>Tianjin City</name_en><name_zh>天津市</name_zh><pinyin>TianJinShi</pinyin><short_code>TJ</short_code></city><city><adcode>120101</adcode><citycode>022</citycode><enable>1</enable><latitude>39.118327</latitude><longitude>117.195907</longitude><name_en>Heping District</name_en><name_zh>和平区</name_zh><pinyin>HePingQu</pinyin><short_code>HP</short_code></city></city_list><code>1</code><message>Successful.</message><result>true</result><timestamp>1375858376</timestamp><total>3223</total><version>2.0 - 2.0.3218.1805</version></ats>)
1 楼 苹果超人 2013-07-21  
请问一下cxf-extension-jaxrsbinding.xml在哪个jar包中,我一直缺这个文件。

相关推荐

Global site tag (gtag.js) - Google Analytics