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;     }      // ... } 

see also:


Comments

Popular posts from this blog

unity3d - Rotate an object to face an opposite direction -

angular - Is it possible to get native element for formControl? -

javascript - Why jQuery Select box change event is now working? -