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

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;
}

相关源代码参见截图:
SPRING-REST和CXF-REST实现过程中的系列问题_第1张图片
SPRING-REST和CXF-REST实现过程中的系列问题_第2张图片
SPRING-REST和CXF-REST实现过程中的系列问题_第3张图片
备注:
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/

你可能感兴趣的:(spring)