前一篇介绍了RPC大体的流程,核心方法是RemoteServiceServlet类中的processPost方法
这是一个final方法,无法覆写。不过GWT为我们提供了前置后置方法,供我们覆写:
onBeforeRequestDeserialized 请求反序列化之前的处理
onAfterResponseSerialized 响应序列化之后的处理
下面我们深入这三个步骤
1. readContent(request)
这里调用了内部的一个方法
解析的工作由RPCServletUtils来处理,进入此方法
调用了同名方法,添加了2个参数,分别是请求格式(text/x-gwt-rpc) 编码(utf-8)
进入
此处拿到request的输入流,并将内容转换为String类型返回。
至此readContent结束。
2. processCall(String payload)
处理这个请求的RPC调用
RPC.decodeRequest()方法对提交上来的文本解析,生成一个RPCRequest对象
进入此方法
获得了RPCRequest对象后,通过RPC.invokeAndEncodeResponse()调用业务对象完成RPC
拿到需要返回的序列化结果后,将其写入response
3. writeResponse
在写入response时,还判断浏览器是否支持gzip压缩,如果支持,则调用RPCServletUtils.writeResponse方法时,传参gzipEncod=true
当然内容还会判断,如果响应内容长度小于255,还是不会压缩的。
- public final void processPost(HttpServletRequest request,
- HttpServletResponse response) throws IOException, ServletException,
- SerializationException {
- // Read the request fully.
- //
- String requestPayload = readContent(request);
- // Let subclasses see the serialized request.
- //
- onBeforeRequestDeserialized(requestPayload);
- // Invoke the core dispatching logic, which returns the serialized
- // result.
- //
- String responsePayload = processCall(requestPayload);
- // Let subclasses see the serialized response.
- //
- onAfterResponseSerialized(responsePayload);
- // Write the response.
- //
- writeResponse(request, response, responsePayload);
- }
这是一个final方法,无法覆写。不过GWT为我们提供了前置后置方法,供我们覆写:
onBeforeRequestDeserialized 请求反序列化之前的处理
onAfterResponseSerialized 响应序列化之后的处理
下面我们深入这三个步骤
1. readContent(request)
这里调用了内部的一个方法
- protected String readContent(HttpServletRequest request)
- throws ServletException, IOException {
- return RPCServletUtils.readContentAsGwtRpc(request);
- }
解析的工作由RPCServletUtils来处理,进入此方法
- public static String readContentAsGwtRpc(HttpServletRequest request)
- throws IOException, ServletException {
- return readContent(request, GWT_RPC_CONTENT_TYPE, CHARSET_UTF8);
- }
调用了同名方法,添加了2个参数,分别是请求格式(text/x-gwt-rpc) 编码(utf-8)
进入
- public static String readContent(HttpServletRequest request,
- String expectedContentType, String expectedCharSet)
- throws IOException, ServletException {
- if (expectedContentType != null) {
- checkContentTypeIgnoreCase(request, expectedContentType);
- }
- if (expectedCharSet != null) {
- checkCharacterEncodingIgnoreCase(request, expectedCharSet);
- }
- /*
- * Need to support 'Transfer-Encoding: chunked', so do not rely on
- * presence of a 'Content-Length' request header.
- */
- InputStream in = request.getInputStream();
- byte[] buffer = new byte[BUFFER_SIZE];
- ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
- try {
- while (true) {
- int byteCount = in.read(buffer);
- if (byteCount == -1) {
- break;
- }
- out.write(buffer, 0, byteCount);
- }
- String contentCharSet = expectedCharSet != null
- ? expectedCharSet : CHARSET_UTF8;
- return out.toString(contentCharSet);
- } finally {
- if (in != null) {
- in.close();
- }
- }
- }
此处拿到request的输入流,并将内容转换为String类型返回。
至此readContent结束。
2. processCall(String payload)
处理这个请求的RPC调用
- public String processCall(String payload) throws SerializationException {
- // First, check for possible XSRF situation
- checkPermutationStrongName();
- try {
- RPCRequest rpcRequest = RPC.decodeRequest(payload, delegate.getClass(), this);
- onAfterRequestDeserialized(rpcRequest);
- return RPC.invokeAndEncodeResponse(delegate, rpcRequest.getMethod(),
- rpcRequest.getParameters(), rpcRequest.getSerializationPolicy(),
- rpcRequest.getFlags());
- } catch (IncompatibleRemoteServiceException ex) {
- log(
- "An IncompatibleRemoteServiceException was thrown while processing this call.",
- ex);
- return RPC.encodeResponseForFailure(null, ex);
- }
- }
RPC.decodeRequest()方法对提交上来的文本解析,生成一个RPCRequest对象
进入此方法
- public static RPCRequest decodeRequest(String encodedRequest, Class<?> type,
- SerializationPolicyProvider serializationPolicyProvider) {
- //….. 省略部分代码
- ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
- try {
- ServerSerializationStreamReader streamReader = new ServerSerializationStreamReader(
- classLoader, serializationPolicyProvider);
- streamReader.prepareToRead(encodedRequest);
- //省略大量代码
- //此处通过序列化读入流,解析文本,得出请求中需要调用的类名,方法名,已经方法签名数据 根据这些参数创建RPCRequest对象返回
- return new RPCRequest(method, parameterValues, serializationPolicy,
- streamReader.getFlags());
- } catch (NoSuchMethodException e) {
- throw new IncompatibleRemoteServiceException(
- formatMethodNotFoundErrorMessage(serviceIntf, serviceMethodName,
- parameterTypes));
- }
- } catch (SerializationException ex) {
- throw new IncompatibleRemoteServiceException(ex.getMessage(), ex);
- }
- }
获得了RPCRequest对象后,通过RPC.invokeAndEncodeResponse()调用业务对象完成RPC
- public static String invokeAndEncodeResponse(Object target,
- Method serviceMethod, Object[] args,
- SerializationPolicy serializationPolicy, int flags)
- throws SerializationException {
- if (serviceMethod == null) {
- throw new NullPointerException("serviceMethod");
- }
- if (serializationPolicy == null) {
- throw new NullPointerException("serializationPolicy");
- }
- String responsePayload;
- try {
- //利用反射,完成对业务对象的调用
- Object result = serviceMethod.invoke(target, args);
- //把业务对象调用的返回结果序列化编码 并返回
- responsePayload = encodeResponseForSuccess(serviceMethod, result,
- serializationPolicy, flags);
- } catch (IllegalAccessException e) {
- SecurityException securityException = new SecurityException(
- formatIllegalAccessErrorMessage(target, serviceMethod));
- securityException.initCause(e);
- throw securityException;
- } catch (IllegalArgumentException e) {
- SecurityException securityException = new SecurityException(
- formatIllegalArgumentErrorMessage(target, serviceMethod, args));
- securityException.initCause(e);
- throw securityException;
- } catch (InvocationTargetException e) {
- // Try to encode the caught exception
- //
- Throwable cause = e.getCause();
- responsePayload = encodeResponseForFailure(serviceMethod, cause,
- serializationPolicy, flags);
- }
- return responsePayload;
- }
拿到需要返回的序列化结果后,将其写入response
3. writeResponse
- private void writeResponse(HttpServletRequest request,
- HttpServletResponse response, String responsePayload) throws IOException {
- boolean gzipEncode = RPCServletUtils.acceptsGzipEncoding(request)
- && shouldCompressResponse(request, response, responsePayload);
- RPCServletUtils.writeResponse(getServletContext(), response,
- responsePayload, gzipEncode);
- }
在写入response时,还判断浏览器是否支持gzip压缩,如果支持,则调用RPCServletUtils.writeResponse方法时,传参gzipEncod=true
当然内容还会判断,如果响应内容长度小于255,还是不会压缩的。
至此RPC整个请求响应完成
源自:http://jc-dreaming.iteye.com/blog/1096732