spring和gwt整合,让gwt直接调用spring bean的前端servlet

gwt和spring整合的关键是让gwt可以访问到spring的bean,先在提供一个前端servlet分发器,配置了这个servlet后,gwt的RemoteServiceServlet就不用在web.xml中一个一个的配置了。本文使用的gwt是2.5.1版本的,spring是3.2.4版本的。

1、服务层接口:要在client包或者子包下面,@RemoteServiceRelativePath标识这个servlet的相对路径,里面的值是spring bean的id

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

/**
 * The client side stub for the RPC service.
 */
@RemoteServiceRelativePath("greetingServiceImpl")
public interface GreetingService extends RemoteService {
  String greetServer(String name) throws IllegalArgumentException;
}

2、服务层异步接口,就是服务接口后加Async,和服务层接口在同一个包下面

import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * The async counterpart of <code>GreetingService</code>.
 */
public interface GreetingServiceAsync {
  void greetServer(String input, AsyncCallback<String> callback)
      throws IllegalArgumentException;
}
3、这个是gwt和spring整合的前端servlet总控制器,在inti方法中,设置该类可以自动装配。

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.RPC;
import com.google.gwt.user.server.rpc.RPCRequest;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class SpringGwtRemoteServiceServlet extends RemoteServiceServlet {
	private static final long serialVersionUID = 1L;
	private static final Logger LOG = LoggerFactory.getLogger(SpringGwtRemoteServiceServlet.class);

	public void init() throws ServletException {
		super.init();
		if (LOG.isDebugEnabled()) {
			LOG.debug("Spring GWT service exporter deployed");
		}
		WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
		AutowireCapableBeanFactory factory = context.getAutowireCapableBeanFactory();
		factory.autowireBean(this);
	}

	public String processCall(String payload) throws SerializationException {
		try {
			Object handler = getBean(getThreadLocalRequest());
			RPCRequest rpcRequest = RPC.decodeRequest(payload, handler.getClass(), this);
			onAfterRequestDeserialized(rpcRequest);
			if (LOG.isDebugEnabled()) {
				LOG.debug("Invoking " + handler.getClass().getName() + "." + rpcRequest.getMethod().getName());
			}
			return RPC.invokeAndEncodeResponse(handler, rpcRequest.getMethod(),
					rpcRequest.getParameters(),
					rpcRequest.getSerializationPolicy());
		} catch (IncompatibleRemoteServiceException ex) {
			log("An IncompatibleRemoteServiceException was thrown while processing this call.", ex);
			return RPC.encodeResponseForFailure(null, ex);
		}
	}

	protected Object getBean(HttpServletRequest request) {
		String service = getService(request);
		Object bean = getBean(service);
		if (!(bean instanceof RemoteService)) {
			throw new IllegalArgumentException(
					"Spring bean is not a GWT RemoteService: " + service + " (" + bean + ")");
		}
		if (LOG.isDebugEnabled()) {
			LOG.debug("Bean for service " + service + " is " + bean);
		}
		return bean;
	}

	protected String getService(HttpServletRequest request) {
		String url = request.getRequestURI();
		String service = url.substring(url.lastIndexOf("/") + 1);
		if (LOG.isDebugEnabled()) {
			LOG.debug("Service for URL " + url + " is " + service);
		}
		return service;
	}

	protected Object getBean(String name) {
		WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());

		if (applicationContext == null) {
			throw new IllegalStateException("No Spring web application context found");
		}
		if (!applicationContext.containsBean(name)) {
			throw new IllegalArgumentException("Spring bean not found: " + name);
		}
		return applicationContext.getBean(name);
	}
}

4、定义spring的bean,实现服务层接口。

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.inject.Inject;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import com.vteba.test.client.GreetingService;
import com.vteba.test.model.User;
import com.vteba.test.rpc.SpringGwtRemoteServiceServlet;
import com.vteba.test.shared.FieldVerifier;

/**
 * The server side implementation of the RPC service.
 */
@Service
public class GreetingServiceImpl implements GreetingService {
	private static final long serialVersionUID = 1L;
	
	@Inject
	private JdbcTemplate jdbcTemplate;

	public String greetServer(String input) throws IllegalArgumentException {
		// Verify that the input is valid.
		if (!FieldVerifier.isValidName(input)) {
			// If the input is not valid, throw an IllegalArgumentException back
			// to
			// the client.
			throw new IllegalArgumentException(
					"Name must be at least 4 characters long");
		}

		String sql = "select * from users";
		List<User> userList = jdbcTemplate.query(sql, new RowMapper<User>() {
			public User mapRow(ResultSet rs, int row) {
				User user = new User();
				try {
					user.setId(rs.getString("id"));
					user.setCompany(rs.getString("company"));
					user.setCreateDate(rs.getDate("create_date"));
					user.setMobilePhone(rs.getString("mobile_phone"));
					user.setState(rs.getInt("state"));
				} catch (SQLException e) {
					e.printStackTrace();
				}
				return user;
			}
		});
		
		System.out.println(userList);
		
		String serverInfo = "";//getServletContext().getServerInfo();
		String userAgent = "";//getThreadLocalRequest().getHeader("User-Agent");

		// Escape data from the client to avoid cross-site script
		// vulnerabilities.
		input = escapeHtml(input);
		userAgent = escapeHtml(userAgent);

		return "Hello, " + input + "!<br><br>I am running " + serverInfo
				+ ".<br><br>It looks like you are using:<br>" + userAgent;
	}

	/**
	 * Escape an html string. Escaping data received from the client helps to
	 * prevent cross-site script vulnerabilities.
	 * 
	 * @param html
	 *            the html string to escape
	 * @return the escaped string
	 */
	private String escapeHtml(String html) {
		if (html == null) {
			return null;
		}
		return html.replaceAll("&", "&").replaceAll("<", "<")
				.replaceAll(">", ">");
	}
}


5、然后在web.xml中配置第三步中定义的类即可,作为前端servlet总控制器,所有请求,都经过它来分发。

这样,gwt收到请求以后就直接委托给spring bean来处理了。

  <servlet>
  	<servlet-name>springGwtRemoteServiceServlet</servlet-name>
  	<servlet-class>com.vteba.test.rpc.SpringGwtRemoteServiceServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>springGwtRemoteServiceServlet</servlet-name>
  	<url-pattern>/testgwt/*</url-pattern>
  </servlet-mapping>


6、也可以,每个RemoteServiceServlet都定义,然后配置在web.xml中,下面提供一个servlet基类,继承它后,spring bean可自动注入进来

public class AutowiredRemoteServiceServlet extends RemoteServiceServlet {
	private static final long serialVersionUID = 1L;
	
	public void init() throws ServletException {
		super.init();
		WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
		AutowireCapableBeanFactory factory = context.getAutowireCapableBeanFactory();
		factory.autowireBean(this);
	}
	
}

也可以将继承的RemoteServiceServlet换成HttpServlet,那么普通的servlet环境中,servlet也可以注入spring bean了。


你可能感兴趣的:(spring和gwt整合,让gwt直接调用spring bean的前端servlet)