- InjectorFactory:负责创建注入的工厂,比如ValueInject、MethodInjector
- ValueInjector:处理参数解析
要扩展自定义的参数解析,基本思路是这样,使用特定的InejectorFactory创建自定义的ValueInjector。
resteasy框架允许我们使用自已的InjectorFactory,默认是使用InjectorFactoryImpl。如果我们想改变其默认实现,需要在web.xml中指定具体的实现类,这部分的源码在ConfigurationBootstrap#createDeployment方法中,支持自定义的InjectorFactory
web.xml
<context-param>
<param-name>resteasy.injector.factory</param-name>
<param-value>net.dwade.plugins.resteasy.PaymentInjectorFactory</param-value>
</context-param>
编写PaymentInjectorFactory实现类,继承InjectorFactoryImpl,重写createParameterExtractor方法,返回自定义的ValueInjector实现类。
PaymentInjectorFactory.java
/**
* 扩展resteasy的{@link InjectorFactory},用于实现自定义参数解析、参数验证,
* 如果使用{@link SpringResteasyBootstrap}作为ServletContextListener启动,默认会使用该InjectorFactory,
* 否则需要在web.xml中指定resteasy.injector.factory参数, eg:
* <pre>
* <context-param>
* <param-name>resteasy.injector.factory</param-name>
* <param-value>com.sitech.miso.payment.common.support.rest.PaymentInjectorFactory</param-value>
* </context-param>
* </pre>
* @see SpringResteasyBootstrap
* @see ResteasyBootstrap
* @see ListenerBootstrap#createDeployment()
* @author huangxf
* @date 2017年4月21日
*/
public class PaymentInjectorFactory extends InjectorFactoryImpl {
@Override
public ValueInjector createParameterExtractor(Parameter parameter,
ResteasyProviderFactory providerFactory) {
boolean isDataBody = hasAnnotation( parameter, RequestDataBody.class );
if ( isDataBody ) {
return new RequestDataInjector( parameter, providerFactory );
}
return super.createParameterExtractor(parameter, providerFactory);
}
/**
* 返回{@link PaymentMethodInjector}
*/
@Override
public MethodInjector createMethodInjector(ResourceLocator method,
ResteasyProviderFactory factory) {
return new PaymentMethodInjector( method, factory );
}
@SuppressWarnings("rawtypes")
protected boolean hasAnnotation( Parameter parameter, Class annotation ) {
Annotation[] annotations = parameter.getAnnotations();
if ( annotations == null ) {
return false;
}
for ( Annotation anno : annotations ) {
boolean is = annotation.isInstance( anno );
if ( is ) {
return true;
}
}
return false;
}
}
实现ValueInjector接口,完成参数解析的逻辑,这里以获取json报文中的data节点为例。
RequestDataInjector.java
/**
* 支持resteasy对{@link RequestDataBody}注解的参数解析
* @see RequestDataBody
* @author huangxf
* @date 2017年4月21日
*/
public class RequestDataInjector implements ValueInjector {
private Parameter paramerter;
private ResteasyProviderFactory providerFactory;
private Logger logger = LoggerFactory.getLogger( this.getClass() );
/**
* 保存请求json数据的key,value为JSONObject
*/
public static final String JSON_KEY = RequestDataInjector.class.getName();
public RequestDataInjector(Parameter parameter, ResteasyProviderFactory providerFactory) {
this.paramerter = parameter;
this.providerFactory = providerFactory;
}
@Override
public Object inject( HttpRequest request, HttpResponse response ) {
Throwable ex = null;
try {
checkJsonRequest( request );
JSONObject jsonObject = (JSONObject)request.getAttribute( JSON_KEY );
//说明方法中的参数未被解析,因为可能需要对Sign进行解析
if ( jsonObject == null ) {
//获取请求数据中的json
String json = JSON.parseObject( request.getInputStream(), StandardCharsets.UTF_8, String.class );
logger.info( "解析Json数据:{}", json );
//转换成json对象
jsonObject = JSONObject.parseObject( json );
//保存至上下文中,便于其他参数的解析
request.setAttribute( JSON_KEY, jsonObject );
}
//将data节点下面的数据返回
return jsonObject.getJSONObject( "data" ).toJavaObject( paramerter.getType() );
} catch ( Exception e ) {
ex = e;
logger.warn( "请求参数有误.", e );
}
throw new IllegalArgumentException( "Request param error.", ex );
}
/**
* 检验是否传递的是json数据
*/
protected void checkJsonRequest( HttpRequest request ) {
String contentType = request.getHttpHeaders().getHeaderString( "Content-Type" );
//匹配application/json,text/json
if ( StringUtils.containsIgnoreCase( contentType, "json" ) ) {
return;
}
throw new IllegalArgumentException( "Not json request." );
}
@Override
public Object inject() {
throw new RuntimeException("Not allowed to inject.");
}
}