`
gwbasic
  • 浏览: 56168 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

GWT和AOP

    博客分类:
  • gwt
阅读更多
上文http://gwbasic.iteye.com/admin/show/39079提到的GWTSpringController.java,继承的是GWT中的RemoteServiceServlet类,在使用过程中发现这个类不支持AOP,原因
public String processCall(String payload) throws SerializationException {
  // .............
  // ............
      // Actually get the service interface, so that we can query its methods.
    //
    Class serviceIntf; 
    try {
      // 此处的serviceIntf,是用getClassForName获取的,没有经过proxy代理
      serviceIntf = getClassFromName(serviceIntfName);
    } catch (ClassNotFoundException e) {
      throw new SerializationException("Unknown service interface class '"
          + serviceIntfName + "'", e);
    }

    // Read the method name.
    //
    String methodName = streamReader.readString();

    // Read the number and names of the parameter classes from the stream.
    // We have to do this so that we can find the correct overload of the
    // method.
    //
    int paramCount = streamReader.readInt();
    Class[] paramTypes = new Class[paramCount];
    for (int i = 0; i < paramTypes.length; i++) {
      String paramClassName = streamReader.readString();
      try {
        paramTypes[i] = getClassOrPrimitiveFromName(paramClassName);
      } catch (ClassNotFoundException e) {
        throw new SerializationException("Unknown parameter " + i + " type '"
            + paramClassName + "'", e);
      }
    }

    // For security, make sure the method is found in the service interface
    // and not just one that happens to be defined on this class.
    //
    Method serviceIntfMethod = findInterfaceMethod(serviceIntf, methodName,
        paramTypes, true);
}


于是参照RemoteServiceServlet重新写了一个在Spring中使用的Controller
GWTServiceController

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPOutputStream;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.context.ServletContextAware;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.impl.ServerSerializableTypeOracle;
import com.google.gwt.user.server.rpc.impl.ServerSerializableTypeOracleImpl;
import com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader;
import com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter;

public class GWTServiceController implements ServletContextAware, Controller {
	private ServletContext servletContext;

	/** Object we'll invoke methods on. Defaults to this. */
	private Object delegate;

	public void setServletContext(ServletContext servletContext) {
		this.servletContext = servletContext;
	}

	public ServletContext getServletContext() {
		return servletContext;
	}

	public Object getDelegate() {
		return delegate;
	}

	public void setDelegate(Object delegate) {
		this.delegate = delegate;
		registerImplementedRemoteServiceInterface(this.delegate);
	}

	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		doPost(request, response);
		return null;
	}

	/*
	 * These members are used to get and set the different HttpServletResponse and
	 * HttpServletRequest headers.
	 */
	private static final String ACCEPT_ENCODING = "Accept-Encoding";

	private static final String CHARSET_UTF8 = "UTF-8";

	private static final String CONTENT_ENCODING = "Content-Encoding";

	private static final String CONTENT_ENCODING_GZIP = "gzip";

	private static final String CONTENT_TYPE_TEXT_PLAIN_UTF8 = "text/plain; charset=utf-8";

	private static final String GENERIC_FAILURE_MSG = "The call failed on the server; see server log for details";

	private static final HashMap TYPE_NAMES;

	/**
	 * Controls the compression threshold at and below which no compression will
	 * take place.
	 */
	private static final int UNCOMPRESSED_BYTE_SIZE_LIMIT = 256;

	static {
		TYPE_NAMES = new HashMap();
		TYPE_NAMES.put("Z", boolean.class);
		TYPE_NAMES.put("B", byte.class);
		TYPE_NAMES.put("C", char.class);
		TYPE_NAMES.put("D", double.class);
		TYPE_NAMES.put("F", float.class);
		TYPE_NAMES.put("I", int.class);
		TYPE_NAMES.put("J", long.class);
		TYPE_NAMES.put("S", short.class);
	}

	/**
	 * Return true if the response object accepts Gzip encoding. This is done by
	 * checking that the accept-encoding header specifies gzip as a supported
	 * encoding.
	 */
	private static boolean acceptsGzipEncoding(HttpServletRequest request) {
		assert (request != null);

		String acceptEncoding = request.getHeader(ACCEPT_ENCODING);
		if (null == acceptEncoding) {
			return false;
		}

		return (acceptEncoding.indexOf(CONTENT_ENCODING_GZIP) != -1);
	}

	/**
	 * This method attempts to estimate the number of bytes that a string will
	 * consume when it is sent out as part of an HttpServletResponse. This really
	 * a hack since we are assuming that every character will consume two bytes
	 * upon transmission. This is definitely not true since some characters
	 * actually consume more than two bytes and some consume less. This is even
	 * less accurate if the string is converted to UTF8. However, it does save us
	 * from converting every string that we plan on sending back to UTF8 just to
	 * determine that we should not compress it.
	 */
	private static int estimateByteSize(final String buffer) {
		return (buffer.length() * 2);
	}

	/**
	 * Find the invoked method on either the specified interface or any super.
	 */
	private static Method findInterfaceMethod(Class intf, String methodName, Class[] paramTypes,
			boolean includeInherited) {
		try {
			return intf.getDeclaredMethod(methodName, paramTypes);
		} catch (NoSuchMethodException e) {
			if (includeInherited) {
				Class[] superintfs = intf.getInterfaces();
				for (int i = 0; i < superintfs.length; i++) {
					Method method = findInterfaceMethod(superintfs[i], methodName, paramTypes, true);
					if (method != null) {
						return method;
					}
				}
			}

			return null;
		}
	}

	private final ServerSerializableTypeOracle serializableTypeOracle;

	/**
	 * The default constructor.
	 */
	public GWTServiceController() {
		serializableTypeOracle = new ServerSerializableTypeOracleImpl(getPackagePaths());
		this.delegate = this;
		registerImplementedRemoteServiceInterface(this.delegate);
	}

	/**
	 * This is called internally.
	 */
	public final void doPost(HttpServletRequest request, HttpServletResponse response) {
		Throwable caught;
		try {

			// Read the request fully.
			//
			String requestPayload = readPayloadAsUtf8(request);

			// Invoke the core dispatching logic, which returns the serialized
			// result.
			//
			String responsePayload = processCall(requestPayload);

			// Write the response.
			//
			writeResponse(request, response, responsePayload);
			return;
		} catch (IOException e) {
			caught = e;
		} catch (ServletException e) {
			caught = e;
		} catch (SerializationException e) {
			caught = e;
		} catch (Throwable e) {
			caught = e;
		}

		respondWithFailure(response, caught);
	}

	/**
	 * This is public so that it can be unit tested easily without HTTP.
	 */
	public String processCall(String payload) throws SerializationException {

		// Let subclasses see the serialized request.
		//
		onBeforeRequestDeserialized(payload);

		// Create a stream to deserialize the request.
		//
		ServerSerializationStreamReader streamReader = new ServerSerializationStreamReader(serializableTypeOracle);
		streamReader.prepareToRead(payload);

		// Read the service interface
		//
		String serviceIntfName = streamReader.readString();

		// TODO(mmendez): need a way to check the type signature of the service intf
		// Verify that this very servlet implements the specified interface name.
		// 从delegate中获取serviceIntf
		Class serviceIntf = getImplementedRemoteServiceInterface(serviceIntfName);
		if (serviceIntf == null) {
			// Bad payload, possible hack attempt.
			//
			throw new SecurityException(
					"Blocked attempt to access interface '"
							+ serviceIntfName
							+ "', which is either not implemented by this servlet or which doesn't extend RemoteService; this is either misconfiguration or a hack attempt");
		}

		// Read the method name.
		//
		String methodName = streamReader.readString();

		// Read the number and names of the parameter classes from the stream.
		// We have to do this so that we can find the correct overload of the
		// method.
		//
		int paramCount = streamReader.readInt();
		Class[] paramTypes = new Class[paramCount];
		for (int i = 0; i < paramTypes.length; i++) {
			String paramClassName = streamReader.readString();
			try {
				paramTypes[i] = getClassOrPrimitiveFromName(paramClassName);
			} catch (ClassNotFoundException e) {
				throw new SerializationException("Unknown parameter " + i + " type '" + paramClassName + "'", e);
			}
		}

		// For security, make sure the method is found in the service interface
		// and not just one that happens to be defined on this class.
		//
		Method serviceIntfMethod = findInterfaceMethod(serviceIntf, methodName, paramTypes, true);

		// If it wasn't found, don't continue.
		//
		if (serviceIntfMethod == null) {
			// Bad payload, possible hack attempt.
			//
			throw new SecurityException("Method '" + methodName + "' (or a particular overload) on interface '"
					+ serviceIntfName + "' was not found, this is either misconfiguration or a hack attempt");
		}

		// Deserialize the parameters.
		//
		Object[] args = new Object[paramCount];
		for (int i = 0; i < args.length; i++) {
			args[i] = streamReader.deserializeValue(paramTypes[i]);
		}

		// Make the call via reflection.
		//
		String responsePayload = GENERIC_FAILURE_MSG;
		ServerSerializationStreamWriter streamWriter = new ServerSerializationStreamWriter(serializableTypeOracle);
		Throwable caught = null;
		try {
			Class returnType = serviceIntfMethod.getReturnType();
			Object returnVal = serviceIntfMethod.invoke(this.delegate, args);
			responsePayload = createResponse(streamWriter, returnType, returnVal, false);
		} catch (IllegalArgumentException e) {
			caught = e;
		} catch (IllegalAccessException e) {
			caught = e;
		} catch (InvocationTargetException e) {
			// Try to serialize the caught exception if the client is expecting it,
			// otherwise log the exception server-side.
			caught = e;
			Throwable cause = e.getCause();
			if (cause != null) {
				// Update the caught exception to the underlying cause
				caught = cause;
				// Serialize the exception back to the client if it's a declared
				// exception
				if (isExpectedException(serviceIntfMethod, cause)) {
					Class thrownClass = cause.getClass();
					responsePayload = createResponse(streamWriter, thrownClass, cause, true);
					// Don't log the exception on the server
					caught = null;
				}
			}
		}

		if (caught != null) {
			responsePayload = GENERIC_FAILURE_MSG;
			ServletContext servletContext = getServletContext();
			// servletContext may be null (for example, when unit testing)
			if (servletContext != null) {
				// Log the exception server side
				servletContext.log("Exception while dispatching incoming RPC call", caught);
			}
		}

		// Let subclasses see the serialized response.
		//
		onAfterResponseSerialized(responsePayload);

		return responsePayload;
	}

	/**
	 * Override this method to examine the serialized response that will be
	 * returned to the client. The default implementation does nothing and need
	 * not be called by subclasses.
	 */
	protected void onAfterResponseSerialized(String serializedResponse) {
	}

	/**
	 * Override this method to examine the serialized version of the request
	 * payload before it is deserialized into objects. The default implementation
	 * does nothing and need not be called by subclasses.
	 */
	protected void onBeforeRequestDeserialized(String serializedRequest) {
	}

	/**
	 * Determines whether the response to a given servlet request should or should
	 * not be GZIP compressed. This method is only called in cases where the
	 * requestor accepts GZIP encoding.
	 * <p>
	 * This implementation currently returns <code>true</code> if the response
	 * string's estimated byte length is longer than 256 bytes. Subclasses can
	 * override this logic.
	 * </p>
	 * 
	 * @param request the request being served
	 * @param response the response that will be written into
	 * @param responsePayload the payload that is about to be sent to the client
	 * @return <code>true</code> if responsePayload should be GZIP compressed,
	 *         otherwise <code>false</code>.
	 */
	protected boolean shouldCompressResponse(HttpServletRequest request, HttpServletResponse response,
			String responsePayload) {
		return estimateByteSize(responsePayload) > UNCOMPRESSED_BYTE_SIZE_LIMIT;
	}

	/**
	 * @param stream
	 * @param responseType
	 * @param responseObj
	 * @param isException
	 * @return response
	 */
	private String createResponse(ServerSerializationStreamWriter stream, Class responseType,
			Object responseObj, boolean isException) {
		stream.prepareToWrite();
		if (responseType != void.class) {
			try {
				stream.serializeValue(responseObj, responseType);
			} catch (SerializationException e) {
				responseObj = e;
				isException = true;
			}
		}

		String bufferStr = (isException ? "{EX}" : "{OK}") + stream.toString();
		return bufferStr;
	}

	/**
	 * Returns the {@link Class} instance for the named class.
	 * 
	 * @param name the name of a class or primitive type
	 * @return Class instance for the given type name
	 * @throws ClassNotFoundException if the named type was not found
	 */
	private Class getClassFromName(String name) throws ClassNotFoundException {
		return Class.forName(name, false, this.getClass().getClassLoader());
	}

	/**
	 * Returns the {@link Class} instance for the named class or primitive type.
	 * 
	 * @param name the name of a class or primitive type
	 * @return Class instance for the given type name
	 * @throws ClassNotFoundException if the named type was not found
	 */
	private Class getClassOrPrimitiveFromName(String name) throws ClassNotFoundException {
		Object value = TYPE_NAMES.get(name);
		if (value != null) {
			return (Class) value;
		}

		return getClassFromName(name);
	}

	/**
	 * Obtain the special package-prefixes we use to check for custom serializers
	 * that would like to live in a package that they cannot. For example,
	 * "java.util.ArrayList" is in a sealed package, so instead we use this prefix
	 * to check for a custom serializer in
	 * "com.google.gwt.user.client.rpc.core.java.util.ArrayList". Right now, it's
	 * hard-coded because we don't have a pressing need for this mechanism to be
	 * extensible, but it is imaginable, which is why it's implemented this way.
	 */
	private String[] getPackagePaths() {
		return new String[] { "com.google.gwt.user.client.rpc.core" };
	}

	/**
	 * Returns true if the {@link java.lang.reflect.Method Method} definition on
	 * the service is specified to throw the exception contained in the
	 * InvocationTargetException or false otherwise. NOTE we do not check that the
	 * type is serializable here. We assume that it must be otherwise the
	 * application would never have been allowed to run.
	 * 
	 * @param serviceIntfMethod
	 * @param e
	 * @return is expected exception
	 */
	private boolean isExpectedException(Method serviceIntfMethod, Throwable cause) {
		assert (serviceIntfMethod != null);
		assert (cause != null);

		Class[] exceptionsThrown = serviceIntfMethod.getExceptionTypes();
		if (exceptionsThrown.length <= 0) {
			// The method is not specified to throw any exceptions
			//
			return false;
		}

		Class causeType = cause.getClass();

		for (int index = 0; index < exceptionsThrown.length; ++index) {
			Class exceptionThrown = exceptionsThrown[index];
			assert (exceptionThrown != null);

			if (exceptionThrown.isAssignableFrom(causeType)) {
				return true;
			}
		}

		return false;
	}

	private final Map<String, Class> knownImplementedInterfacesMap = new HashMap<String, Class>();

	private void registerImplementedRemoteServiceInterface(Object delegate) {
		this.knownImplementedInterfacesMap.clear();
		if (delegate != null) {
			Class cls = delegate.getClass();
			if (cls.isInterface()) {
				addImplementedRemoteServiceInterfaceRecursive(cls);
			} else {
				while (cls != null) {
					Class[] intfs = cls.getInterfaces();
					for (int i = 0; i < intfs.length; i++) {
						addImplementedRemoteServiceInterfaceRecursive(intfs[i]);
					}

					// we look in the superclass
					cls = cls.getSuperclass();
				}
			}
		}
	}

	private void addImplementedRemoteServiceInterfaceRecursive(Class intfToCheck) {
		assert (intfToCheck.isInterface());

		if (RemoteService.class.equals(intfToCheck))
			return;

		if (RemoteService.class.isAssignableFrom(intfToCheck)) {
			this.knownImplementedInterfacesMap.put(intfToCheck.getName(), intfToCheck);
		}

		Class[] intfs = intfToCheck.getInterfaces();
		for (int i = 0; i < intfs.length; i++) {
			addImplementedRemoteServiceInterfaceRecursive(intfs[i]);
		}
	}

	private Class getImplementedRemoteServiceInterface(String intfName) {
		return this.knownImplementedInterfacesMap.get(intfName);
	}

	private String readPayloadAsUtf8(HttpServletRequest request) throws IOException, ServletException {
		int contentLength = request.getContentLength();
		if (contentLength == -1) {
			// Content length must be known.
			throw new ServletException("Content-Length must be specified");
		}

		String contentType = request.getContentType();
		boolean contentTypeIsOkay = false;
		// Content-Type must be specified.
		if (contentType != null) {
			// The type must be plain text.
			if (contentType.startsWith("text/plain")) {
				// And it must be UTF-8 encoded (or unspecified, in which case we assume
				// that it's either UTF-8 or ASCII).
				if (contentType.indexOf("charset=") == -1) {
					contentTypeIsOkay = true;
				} else if (contentType.indexOf("charset=utf-8") != -1) {
					contentTypeIsOkay = true;
				}
			}
		}
		if (!contentTypeIsOkay) {
			throw new ServletException(
					"Content-Type must be 'text/plain' with 'charset=utf-8' (or unspecified charset)");
		}
		InputStream in = request.getInputStream();
		try {
			byte[] payload = new byte[contentLength];
			int offset = 0;
			int len = contentLength;
			int byteCount;
			while (offset < contentLength) {
				byteCount = in.read(payload, offset, len);
				if (byteCount == -1) {
					throw new ServletException("Client did not send " + contentLength + " bytes as expected");
				}
				offset += byteCount;
				len -= byteCount;
			}
			return new String(payload, "UTF-8");
		} finally {
			if (in != null) {
				in.close();
			}
		}
	}

	/**
	 * Called when the machinery of this class itself has a problem, rather than
	 * the invoked third-party method. It writes a simple 500 message back to the
	 * client.
	 */
	private void respondWithFailure(HttpServletResponse response, Throwable caught) {
		ServletContext servletContext = getServletContext();
		servletContext.log("Exception while dispatching incoming RPC call", caught);
		try {
			response.setContentType("text/plain");
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			response.getWriter().write(GENERIC_FAILURE_MSG);
		} catch (IOException e) {
			servletContext.log("sendError() failed while sending the previous failure to the client", caught);
		}
	}

	private void writeResponse(HttpServletRequest request, HttpServletResponse response, String responsePayload)
			throws IOException {

		byte[] reply = responsePayload.getBytes(CHARSET_UTF8);
		String contentType = CONTENT_TYPE_TEXT_PLAIN_UTF8;

		if (acceptsGzipEncoding(request) && shouldCompressResponse(request, response, responsePayload)) {
			// Compress the reply and adjust headers.
			//
			ByteArrayOutputStream output = null;
			GZIPOutputStream gzipOutputStream = null;
			Throwable caught = null;
			try {
				output = new ByteArrayOutputStream(reply.length);
				gzipOutputStream = new GZIPOutputStream(output);
				gzipOutputStream.write(reply);
				gzipOutputStream.finish();
				gzipOutputStream.flush();
				response.setHeader(CONTENT_ENCODING, CONTENT_ENCODING_GZIP);
				reply = output.toByteArray();
			} catch (UnsupportedEncodingException e) {
				caught = e;
			} catch (IOException e) {
				caught = e;
			} finally {
				if (null != gzipOutputStream) {
					gzipOutputStream.close();
				}
				if (null != output) {
					output.close();
				}
			}

			if (caught != null) {
				getServletContext().log("Unable to compress response", caught);
				response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
				return;
			}
		}

		// Send the reply.
		//
		response.setContentLength(reply.length);
		response.setContentType(contentType);
		response.setStatus(HttpServletResponse.SC_OK);
		response.getOutputStream().write(reply);
	}

}


// delegate 用法参照 org.springframework.web.servlet.mvc.multiaction.MultiActionController





/*
  For GWT 1.4.60
*/
public class GwtRemoteServiceController extends RemoteServiceServlet implements
		Controller, ServletContextAware {
	private static final long serialVersionUID = 8175888785480720736L;

	private Object delegate;

	private ServletContext servletContext;

	@Override
	public void setServletContext(ServletContext servletContext) {
		this.servletContext = servletContext;
	}

	@Override
	public ServletContext getServletContext() {
		return servletContext;
	}

	@Override
	public ModelAndView handleRequest(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		super.doPost(request, response);
		return null;
	}

	@Override
	public String processCall(String payload) throws SerializationException {
		Object delegateToUse = this.delegate;
		if (delegateToUse == null) {
			return super.processCall(payload);
		} else {
			try {
				RPCRequest rpcRequest = RPC.decodeRequest(payload,
						delegateToUse.getClass(), this);
				return RPC.invokeAndEncodeResponse(delegateToUse, rpcRequest
						.getMethod(), rpcRequest.getParameters(), rpcRequest
						.getSerializationPolicy());
			} catch (IncompatibleRemoteServiceException ex) {
				getServletContext()
						.log(
								"An IncompatibleRemoteServiceException was thrown while processing this call.",
								ex);
				return RPC.encodeResponseForFailure(null, ex);
			}
		}
	}

	public Object getDelegate() {
		return delegate;
	}

	public void setDelegate(Object delegate) {
		this.delegate = delegate;
	}
}

开源真好:D
分享到:
评论
3 楼 ccj 2008-04-25  
使用Gwt-SL整合效果很好.
2 楼 gwbasic 2008-03-25  
有新版本了,请参照论坛中的<<gwt spring 完美整合>>
http://www.iteye.com/topic/143455

delegate 用法参照 org.springframework.web.servlet.mvc.multiaction.MultiActionController

public class GwtRemoteServiceController extends RemoteServiceServlet implements
		Controller, ServletContextAware {
	private static final long serialVersionUID = 8175888785480720736L;

	private Object delegate;

	private ServletContext servletContext;

	@Override
	public void setServletContext(ServletContext servletContext) {
		this.servletContext = servletContext;
	}

	@Override
	public ServletContext getServletContext() {
		return servletContext;
	}

	@Override
	public ModelAndView handleRequest(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		super.doPost(request, response);
		return null;
	}

	@Override
	public String processCall(String payload) throws SerializationException {
		Object delegateToUse = this.delegate;
		if (delegateToUse == null) {
			return super.processCall(payload);
		} else {
			try {
				RPCRequest rpcRequest = RPC.decodeRequest(payload,
						delegateToUse.getClass(), this);
				return RPC.invokeAndEncodeResponse(delegateToUse, rpcRequest
						.getMethod(), rpcRequest.getParameters(), rpcRequest
						.getSerializationPolicy());
			} catch (IncompatibleRemoteServiceException ex) {
				getServletContext()
						.log(
								"An IncompatibleRemoteServiceException was thrown while processing this call.",
								ex);
				return RPC.encodeResponseForFailure(null, ex);
			}
		}
	}

	public Object getDelegate() {
		return delegate;
	}

	public void setDelegate(Object delegate) {
		this.delegate = delegate;
	}
}
1 楼 li_tieyang 2008-03-19  
ServerSerializationStreamReader streamReader = new ServerSerializationStreamReader(
serializableTypeOracle);
你用的GWT是什么版本,我用1.4.6的这句代码过不去.

相关推荐

    GWT入门与经典实例解析

    此外,GWT还支持代码分割、模块化以及AOP(面向切面编程)等高级特性,极大地提升了开发效率和代码质量。 **GWT的主要特性:** 1. **Java编程**:GWT允许开发者使用Java编写前端代码,借助强大的Java生态系统,...

    gwt+spring+hibernate

    标题 "gwt+spring+hibernate" 涉及的是一个使用Google Web Toolkit (GWT)、Spring框架和Hibernate ORM技术的集成示例。这是一个常见的Web应用开发组合,用于构建高效、可扩展且功能丰富的Java web应用程序。下面将...

    smartgwt-1.3

    - 基于GWT的AOP(面向切面编程)特性,允许在运行时进行优化。 8. **社区支持和文档** - SmartGWT有一个活跃的社区,提供讨论、示例和解决方案。 - 官方文档详尽,包括API参考、教程和示例代码,帮助开发者快速...

    GWT与Spring整合经典文章

    3. 使用Spring的AOP和DI来管理服务实现类,包括依赖注入和服务的生命周期管理。 4. 在客户端,通过GWT的RPC机制调用服务器端服务,实现数据交换。 5. 使用Hibernate配置数据库连接和实体映射,处理数据持久化。 6. ...

    gwt 2.1.0 工具下载

    2. **编译过程**:GWT 2.1.0引入了先进的编译技术,通过AOP(面向切面编程)和JIT(即时编译)优化,将Java源代码转换为高性能的JavaScript代码。这一过程包括源码到字节码、字节码到JSIR(JavaScript Intermediate ...

    Ext-Gwt(GWT)开发实例(整合Spring +Hibernate)

    Spring 是一个全面的Java企业级应用开发框架,提供了依赖注入(DI)、面向切面编程(AOP)和声明式事务管理等核心功能。在本实例中,Spring 可能用于管理应用程序的bean,提供服务层的实现,以及负责与数据库的交互...

    最新GWT API

    9. **AOP(面向切面编程)**:GWT还引入了切面编程的概念,例如,你可以使用GWT的 Gin 框架进行依赖注入,或者使用 Errai 框架实现更复杂的AOP功能。 10. **兼容性和版本更新**:随着Web技术的发展,GWT也不断更新...

    spring集成gwt的办法

    在IT行业中,Spring框架是Java企业级应用开发的首选,而Google Web Toolkit (GWT) 则是一个用于构建和优化复杂Web应用程序的开源工具。本文将深入探讨如何将这两个强大的技术进行集成,以便利用Spring的强大功能来...

    smartgwt+mybatis+spring的整合

    它可以通过ApplicationContext来管理SmartGwt的视图和服务,同时通过Bean配置管理Mybatis的SqlSessionFactory和Mapper实例。Spring的AOP可以方便地实现日志记录、权限控制等功能。 整合步骤通常包括以下几个部分: ...

    smartgwt + spring + hibernate

    SmartGWT是基于GWT(Google Web Toolkit)的一个强大的UI库,提供丰富的用户界面组件和高性能的JavaScript客户端应用。Spring是一个开源的Java应用框架,它提供了依赖注入、AOP(面向切面编程)以及各种企业服务。...

    GWT 2.7 官方最新版本,eclipse4.5本地安装插件,极速下载

    4. **更好的AOP支持**:GWT 2.7增强了对Aspect-Oriented Programming (AOP)的支持,方便开发者进行代码组织和模块化。 5. **模块化改进**:模块化的改进让开发者能更好地管理大型项目,提高代码的可维护性和重用性。...

    Spring4GWT技术资料

    Spring4GWT是将Spring框架与Google Web Toolkit (GWT) 结合的一种技术,它旨在帮助开发者在GWT应用中更好地实现服务层管理和依赖注入,从而提升开发效率和代码的可维护性。以下是对Spring4GWT技术的详细说明: 1. *...

    smartGwt、spring、Mybatis整合

    Spring是一个全面的企业级应用开发框架,核心特性包括依赖注入(DI)和面向切面编程(AOP)。Spring还提供了对数据库访问的支持,如JDBC抽象层和ORM(对象关系映射)集成,包括Mybatis。在本项目中,Spring负责管理...

    前端开源库-mocha-gwt

    4. **AOP支持**:GWT 使用AOP(面向切面编程)实现事件处理、国际化和代码分离等功能。 5. **RPC通信**:GWT 提供了内置的远程过程调用(RPC)机制,使得客户端与服务器之间的数据交换简单易行。 ### Mocha GWT的...

    gwt(google web toolkit) 和 spring 在一起使用列子

    - **Spring-GWT-RPC**:GWT的Remote Procedure Call (RPC)机制可以与Spring的AOP和DI集成,实现服务端的Spring Bean作为GWT RPC的服务端点。这样,客户端可以直接调用服务端的业务逻辑,而无需关心服务的实现细节。...

    GWT通信机制初探

    而Spring框架则常用于后端服务,提供依赖注入、AOP(面向切面编程)等功能,便于构建可维护和可扩展的系统。将两者结合,可以构建出前后端分离、结构清晰的GWT应用。 总的来说,GWT的通信机制是通过RPC服务,利用...

    搭建简单的EXT-GWT(GXT)的开发环境(三)gxt结合spring和hibernate进行数据操作

    接下来,Spring框架是Java企业级应用中的核心组件,它提供依赖注入(DI)和面向切面编程(AOP)等特性,帮助开发者管理对象的生命周期和依赖关系。整合EXT-GWT与Spring,可以实现组件的灵活配置,使UI组件能够轻松...

    基于java的Spring4GWT.zip

    1. GWT-RPC与Spring:GWT-RPC是GWT内部的通信机制,Spring4可以通过AOP进行拦截,实现服务端的事务管理和权限控制。同时,Spring4的Service层可以作为GWT-RPC的服务端,提供远程调用的接口。 2. Spring Security与...

    gwt_spring-nolib.zip

    而Spring框架则是Java后端开发的核心框架,提供了依赖注入、AOP(面向切面编程)、事务管理等功能,极大地提高了开发效率和应用的可维护性。 在"gwt_spring-nolib.zip"这个压缩包中,我们可以看到一个实际的GWT和...

Global site tag (gtag.js) - Google Analytics