java - How to use Servlets and Ajax? -
i'm new web apps , servlets , have following question:
whenever print inside servlet , call webbrowser, returns new page containing text. there way print text in current page using ajax?
indeed, keyword "ajax": asynchronous javascript , xml. however, last years it's more asynchronous javascript , json. basically, let js execute asynchronous http request , update html dom tree based on response data.
since it's pretty tedious work make work across browsers (especially internet explorer versus others), there plenty of javascript libraries out simplifies in single functions , covers many possible browser-specific bugs/quirks under hoods, such jquery, prototype, mootools. since jquery popular these days, i'll use in below examples.
kickoff example returning string
plain text
create /some.jsp
below (note: code doesn't expect jsp file being placed in subfolder, if so, alter servlet url accordingly):
<!doctype html> <html lang="en"> <head> <title>so question 4112686</title> <script src="http://code.jquery.com/jquery-latest.min.js"></script> <script> $(document).on("click", "#somebutton", function() { // when html dom "click" event invoked on element id "somebutton", execute following function... $.get("someservlet", function(responsetext) { // execute ajax request on url of "someservlet" , execute following function ajax response text... $("#somediv").text(responsetext); // locate html dom element id "somediv" , set text content response text. }); }); </script> </head> <body> <button id="somebutton">press here</button> <div id="somediv"></div> </body> </html>
create servlet doget()
method this:
@override protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { string text = "some text"; response.setcontenttype("text/plain"); // set content type of response jquery knows can expect. response.setcharacterencoding("utf-8"); // want world domination, huh? response.getwriter().write(text); // write response body. }
map servlet on url pattern of /someservlet
or /someservlet/*
below (obviously, url pattern free choice, you'd need alter someservlet
url in js code examples on place accordingly):
@webservlet("/someservlet/*") public class someservlet extends httpservlet { // ... }
or, when you're not on servlet 3.0 compatible container yet (tomcat 7, glassfish 3, jboss 6, etc or newer), map in web.xml
old fashioned way (see our servlets wiki page):
<servlet> <servlet-name>someservlet</servlet-name> <servlet-class>com.example.someservlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>someservlet</servlet-name> <url-pattern>/someservlet/*</url-pattern> </servlet-mapping>
now open http://localhost:8080/context/test.jsp in browser , press button. you'll see content of div updated servlet response.
returning list<string>
json
with json instead of plaintext response format can steps further. allows more dynamics. first, you'd have tool convert between java objects , json strings. there plenty of them (see bottom of this page overview). personal favourite google gson. download , put jar file in /web-inf/lib
folder of webapplication.
here's example displays list<string>
<ul><li>
. servlet:
@override protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { list<string> list = new arraylist<>(); list.add("item1"); list.add("item2"); list.add("item3"); string json = new gson().tojson(list); response.setcontenttype("application/json"); response.setcharacterencoding("utf-8"); response.getwriter().write(json); }
the js code:
$(document).on("click", "#somebutton", function() { // when html dom "click" event invoked on element id "somebutton", execute following function... $.get("someservlet", function(responsejson) { // execute ajax request on url of "someservlet" , execute following function ajax response json... var $ul = $("<ul>").appendto($("#somediv")); // create html <ul> element , append html dom element id "somediv". $.each(responsejson, function(index, item) { // iterate on json array. $("<li>").text(item).appendto($ul); // create html <li> element, set text content iterated item , append <ul>. }); }); });
do note jquery automatically parses response json , gives directly json object (responsejson
) function argument when set response content type application/json
. if forget set or rely on default of text/plain
or text/html
, responsejson
argument wouldn't give json object, plain vanilla string , you'd need manually fiddle around json.parse()
afterwards, totally unnecessary if set content type right in first place.
returning map<string, string>
json
here's example displays map<string, string>
<option>
:
@override protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { map<string, string> options = new linkedhashmap<>(); options.put("value1", "label1"); options.put("value2", "label2"); options.put("value3", "label3"); string json = new gson().tojson(options); response.setcontenttype("application/json"); response.setcharacterencoding("utf-8"); response.getwriter().write(json); }
and jsp:
$(document).on("click", "#somebutton", function() { // when html dom "click" event invoked on element id "somebutton", execute following function... $.get("someservlet", function(responsejson) { // execute ajax request on url of "someservlet" , execute following function ajax response json... var $select = $("#someselect"); // locate html dom element id "someselect". $select.find("option").remove(); // find child elements tag name "option" , remove them (just prevent duplicate options when button pressed again). $.each(responsejson, function(key, value) { // iterate on json object. $("<option>").val(key).text(value).appendto($select); // create html <option> element, set value iterated key , text content iterated item , append <select>. }); }); });
with
<select id="someselect"></select>
returning list<entity>
json
here's example displays list<product>
in <table>
product
class has properties long id
, string name
, bigdecimal price
. servlet:
@override protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { list<product> products = someproductservice.list(); string json = new gson().tojson(products); response.setcontenttype("application/json"); response.setcharacterencoding("utf-8"); response.getwriter().write(json); }
the js code:
$(document).on("click", "#somebutton", function() { // when html dom "click" event invoked on element id "somebutton", execute following function... $.get("someservlet", function(responsejson) { // execute ajax request on url of "someservlet" , execute following function ajax response json... var $table = $("<table>").appendto($("#somediv")); // create html <table> element , append html dom element id "somediv". $.each(responsejson, function(index, product) { // iterate on json array. $("<tr>").appendto($table) // create html <tr> element, set text content iterated item , append <table>. .append($("<td>").text(product.id)) // create html <td> element, set text content id of iterated product , append <tr>. .append($("<td>").text(product.name)) // create html <td> element, set text content name of iterated product , append <tr>. .append($("<td>").text(product.price)); // create html <td> element, set text content price of iterated product , append <tr>. }); }); });
returning list<entity>
xml
here's example same previous example, xml instead of json. when using jsp xml output generator you'll see it's less tedious code table , all. jstl way more helpful can use iterate on results , perform server side data formatting. servlet:
@override protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { list<product> products = someproductservice.list(); request.setattribute("products", products); request.getrequestdispatcher("/web-inf/xml/products.jsp").forward(request, response); }
the jsp code (note: if put <table>
in <jsp:include>
, may reusable elsewhere in non-ajax response):
<?xml version="1.0" encoding="utf-8"?> <%@page contenttype="application/xml" pageencoding="utf-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <data> <table> <c:foreach items="${products}" var="product"> <tr> <td>${product.id}</td> <td><c:out value="${product.name}" /></td> <td><fmt:formatnumber value="${product.price}" type="currency" currencycode="usd" /></td> </tr> </c:foreach> </table> </data>
the js code:
$(document).on("click", "#somebutton", function() { // when html dom "click" event invoked on element id "somebutton", execute following function... $.get("someservlet", function(responsexml) { // execute ajax request on url of "someservlet" , execute following function ajax response xml... $("#somediv").html($(responsexml).find("data").html()); // parse xml, find <data> element , append html html dom element id "somediv". }); });
you'll realize why xml more powerful json particular purpose of updating html document using ajax. json funny, after useful so-called "public web services". mvc frameworks jsf use xml under covers ajax magic.
ajaxifying existing form
you can use jquery $.serialize()
ajaxify existing post forms without fiddling around collecting , passing individual form input parameters. assuming existing form works fine without javascript/jquery (and degrades gracefully when enduser has javascript disabled):
<form id="someform" action="someservlet" method="post"> <input type="text" name="foo" /> <input type="text" name="bar" /> <input type="text" name="baz" /> <input type="submit" name="submit" value="submit" /> </form>
you can progressively enhance ajax below:
$(document).on("submit", "#someform", function(event) { var $form = $(this); $.post($form.attr("action"), $form.serialize(), function(response) { // ... }); event.preventdefault(); // important! prevents submitting form. });
you can in servlet distinguish between normal requests , ajax requests below:
@override protected void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { string foo = request.getparameter("foo"); string bar = request.getparameter("bar"); string baz = request.getparameter("baz"); boolean ajax = "xmlhttprequest".equals(request.getheader("x-requested-with")); // ... if (ajax) { // handle ajax (json or xml) response. } else { // handle regular (jsp) response. } }
the jquery form plugin less or more same above jquery example, has additional transparent support multipart/form-data
forms required file uploads.
manually sending request parameters servlet
if don't have form @ all, wanted interact servlet "in background" whereby you'd post data, can use jquery $.param()
convert json object url-encoded query string.
var params = { foo: "foovalue", bar: "barvalue", baz: "bazvalue" }; $.post("someservlet", $.param(params), function(response) { // ... });
the same dopost()
method shown here above can reused. note above syntax works $.get()
in jquery , doget()
in servlet.
manually sending json object servlet
if intend send json object whole instead of individual request parameters reason, you'd need serialize string using json.stringify()
(not part of jquery) , instruct jquery set request content type application/json
instead of (default) application/x-www-form-urlencoded
. can't done via $.post()
convenience function, needs done via $.ajax()
below.
var data = { foo: "foovalue", bar: "barvalue", baz: "bazvalue" }; $.ajax({ type: "post", url: "someservlet", contenttype: "application/json", // not datatype! data: json.stringify(data), success: function(response) { // ... } });
do note lot of starters mix contenttype
datatype
. contenttype
represents type of request body. datatype
represents (expected) type of response body, unnecessary jquery autodetects based on response's content-type
header.
then, in order process json object in servlet isn't being sent individual request parameters whole json string above way, need manually parse request body using json tool instead of using getparameter()
usual way. namely, servlets don't support application/json
formatted requests, application/x-www-form-urlencoded
or multipart/form-data
formatted requests. gson supports parsing json string json object.
jsonobject data = new gson().fromjson(request.getreader(), jsonobject.class); string foo = data.get("foo").getasstring(); string bar = data.get("bar").getasstring(); string baz = data.get("baz").getasstring(); // ...
do note more clumsy using $.param()
. normally, want use json.stringify()
if target service e.g. jax-rs (restful) service reason capable of consuming json strings , not regular request parameters.
sending redirect servlet
important realize , understand sendredirect()
, forward()
call servlet on ajax request forward or redirect the ajax request itself , not main document/window ajax request originated. javascript/jquery in such case retrieve redirected/forwarded response responsetext
variable in callback function. if represents whole html page , not ajax-specific xml or json response, replace current document it.
document.open(); document.write(responsetext); document.close();
note doesn't change url enduser sees in browser's address bar. there issues bookmarkability. therefore, it's better return "instruction" javascript/jquery perform redirect instead of returning whole content of redirected page. e.g. returning boolean, or url.
string redirecturl = "http://example.com"; map<string, string> data = new hashmap<>(); data.put("redirect", redirecturl); string json = new gson().tojson(data); response.setcontenttype("application/json"); response.setcharacterencoding("utf-8"); response.getwriter().write(json);
function(responsejson) { if (responsejson.redirect) { window.location = responsejson.redirect; return; } // ... }
Comments
Post a Comment