博客首页 » Java GWT with JSON
发布于 23 Dec 2014 15:45
标签 blog
GWT是一个优秀的Toolkit,一方面支持Client的Java->Javascript的编译优化,另一方面支持Client与Server间的RPC。只是这个RPC协议是Google专有的,并不通用。我们用JSON重新实现一遍这个RPC的功能。
Demo的基本结构
首先,使用GWT的Eclipse插件生成一个Demo。
它有两部分,一部分是client,一部分是server,还有一个共享shared部分。
- shared部分有一些公用的代码,可以被client和server调用到
- client有一个EntryPoint的Java程序以及GreetingService、GreetingServiceAsync的接口。
- EntryPoint的Java程序,表达界面操作,用GWT的Java-Javascript编译,生成一个画面,有user的name输入框和一个提交按钮。
- GreetingService与GreetingServiceAsync是一对一一对应的表达服务的接口
- 当按钮被按下时,把user的name用GreetingServiceAsync发送出去。
- server是一个实现了GreetingService接口的Servlet
- 当收到GreetingService接口的调用时, 就会返回相应的结果
- 从client的GreetingServiceAsync的调用,到server的GreetingService的调用,其间的数据封装和转化就被GWT封装了
我们的修改,就是基于这个基础。所以我们需要:
- client发送信息时
- 重写一个GreetingServiceAsync的实现
- 用gwt json来组合json成为String。
- 用RequestBuilder来发送request。
- 用String来接受结果
- 用JsonParser来解析结果String
- 调用新的GreetingServiceAsync(因为接口略有不同)
- 重写一个GreetingServiceAsync的实现
- server上接受GreeringService的调用
- 用org.json解析String
- 用org.json封装返回的String
GreetingServiceAsync
我们重用所有的接口,这样GWT清晰的结构以及与GWT的兼容性都不受影响。
我们可以看到GWT.create(GreetingService.class)的简洁代码被我们替换成了手动合成json,使用RequestBuilder发送的这两部分代码。
这里为了阐释原理,这里使用两种方法实现,一种是json的这个包。稍后我们还要继续讲解AutoBean。
/** * Create a remote service proxy to talk to the server-side Greeting service. */ private final GreetingServiceAsync greetingService = new GreetingServiceAsync() { @Override public void greetServer(String name, final AsyncCallback<String> callback) throws IllegalArgumentException { JSONObject inputs = new JSONObject(); inputs.put("name", new JSONString(name)); RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, GWT.getModuleBaseURL()+ "greetJson" ); try { builder.sendRequest(inputs.toString(), new RequestCallback(){ @Override public void onResponseReceived(Request request, Response response) { JSONValue rst = JSONParser.parseStrict(response.getText()); callback.onSuccess(response.getText()); } @Override public void onError(Request request, Throwable exception) { callback.onFailure(exception); }}); } catch (RequestException exception) { callback.onFailure(exception); } }}; /* private final GreetingServiceAsync greetingService = GWT .create(GreetingService.class); */
直接发送请求的方法实现
JSONObject inputs = new JSONObject(); inputs.put("name", new JSONString(nameField.getText())); RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, GWT.getModuleBaseURL()+ "greetJson" //"http://localhost/alts/gwtest/php/gwtest.ajax.php" );
try { builder.sendRequest(inputs.toString(), new RequestCallback(){ @Override public void onResponseReceived(Request request, Response response) { dialogBox.setText("Remote Procedure Call"); serverResponseLabel .removeStyleName("serverResponseLabelError"); //serverResponseLabel.setHTML(result); JSONValue result = JSONParser.parseStrict(response.getText()); JSONValue resultVal = result.isObject().get("result"); String name = resultVal.isString().stringValue(); serverResponseLabel.setHTML(name); dialogBox.center(); closeButton.setFocus(true); } @Override public void onError(Request request, Throwable exception) { serverResponseLabel.setHTML(exception.toString()); }}); serverResponseLabel.addStyleName("serverResponseLabelError"); serverResponseLabel.setHTML("request sent"); } catch (RequestException e) { serverResponseLabel.setHTML(e.toString()); throw new RuntimeException(e); }
使用与GWT相同的interface发送请求
原来的代码
greetingService.greetServer(textToServer, new AsyncCallback<String>() { public void onFailure(Throwable caught) { // Show the RPC error message to the user dialogBox .setText("Remote Procedure Call - Failure"); serverResponseLabel .addStyleName("serverResponseLabelError"); serverResponseLabel.setHTML(SERVER_ERROR); dialogBox.center(); closeButton.setFocus(true); } public void onSuccess(String result) { dialogBox.setText("Remote Procedure Call"); serverResponseLabel .removeStyleName("serverResponseLabelError"); serverResponseLabel.setHTML(result); dialogBox.center(); closeButton.setFocus(true); } });
修改后的代码
greetingService.greetServer(textToServer, new AsyncCallback<String>() { public void onFailure(Throwable caught) { // Show the RPC error message to the user dialogBox .setText("Remote Procedure Call - Failure"); serverResponseLabel .addStyleName("serverResponseLabelError"); serverResponseLabel.setHTML(SERVER_ERROR); dialogBox.center(); closeButton.setFocus(true); } public void onSuccess(String result) { dialogBox.setText("Remote Procedure Call"); serverResponseLabel .removeStyleName("serverResponseLabelError"); JSONValue resultParse = JSONParser.parseStrict(result); JSONValue resultVal = resultParse.isObject().get("result"); String name = resultVal.isString().stringValue(); serverResponseLabel.setHTML(name); dialogBox.center(); closeButton.setFocus(true); } });
可以看到,我们增加了JSON解析的部分。
server端
接着是server端
package com.fj.gwtest.server; import java.io.IOException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; import org.json.*; import com.fj.gwtest.client.GreetingService; public class GreetingJsonServiceImpl extends HttpServlet implements GreetingService { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) { try { resp.getWriter().print(greetServer(req.getQueryString())); } catch (IOException e) { throw new RuntimeException(e); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) { try { resp.getWriter().print(greetServer(IOUtils.toString(req.getReader()))); } catch (IOException e) { throw new RuntimeException(e); } } @Override public String greetServer(String inputStr) throws IllegalArgumentException { try { System.out.println("Received payLoad"); JSONObject inputs = (JSONObject)new JSONTokener(inputStr).nextValue(); String name = inputs.getString("name"); String result = "{\"result\":\"" + escapeJsonHtml(name) + "\"}"; //" + escapeJson(name) + " return result; } catch (JSONException e) { throw new RuntimeException(e); } } /** * 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 escapeJsonHtml(String html) { if (html == null) { return null; } return html.replaceAll("&", "&").replaceAll("<", "<") .replaceAll(">", ">") .replaceAll("\"", """); } private String escapeJson(String str) { if (str == null) { return null; } return str.replaceAll("\"", "\\\""); } }
后话
我们还有几个可以改进的地方
- 可以用json对于object, method进行封装,以完成更加类似与rpc的行为,并且传递复杂对象。
- 可以用autobean封装/解析对象,完成自动化
- 可以用JSONP代替JSON,实现跨域的访问
- 可以用JSP+Component代替Servlet,实现动态开发测试
本页面的文字允许在知识共享 署名-相同方式共享 3.0协议和GNU自由文档许可证下修改和再使用,仅有一个特殊要求,请用链接方式注明文章引用出处及作者。请协助维护作者合法权益。
系列文章
文章列表
- Java GWT with JSON
这篇文章对你有帮助吗,投个票吧?
留下你的评论