Primero que nada, necesitamos crear nuestro fichero 
index.jsp o 
index.html que contendrá el formulario de ingreso. Éste fichero va dentro del folder 
webapp, WebContent o WebPages (de acuerdo al IDE):
- <%@page contentType="text/html" pageEncoding="UTF-8"%> 
- <!DOCTYPE html> 
- 	<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"> 
- 	<link rel="stylesheet" href="assets/css/login.css"/> 
- 	<div id="flogin" class="flogin"> 
-         <section class="left-side"> 
-             <section class="head"> 
-                 LOGIN 
-             </section> 
-             <section class="body"> 
-                 <section class="data"> 
-                     <section class="form-group"> 
-                         <section class="input-wrapper"> 
-                             <input type="text" id="txt-username" class="txt"/> 
-                             <i class="fa fa-user"></i> 
-                         </section> 
-                     </section> 
-                     <section class="form-group"> 
-                         <section class="input-wrapper"> 
-                             <input type="password" id="txt-password" class="txt"/> 
-                             <i class="fa fa-key"></i> 
-                         </section> 
-                     </section> 
-                 </section> 
-                 <section class="help"> 
-                     <a href="">- ¿Olvidaste tu usuario o contraseña? </a>
 
-                 </section> 
-             </section> 
-         </section> 
-         <section id="btn-login" class="right-side"> 
-             <i class="fa-4x fa fa-arrow-right"></i> 
-         </section> 
-   
- 	<!-- javascript files --> 
CSS:
- * { 
-     margin: 0px; 
-     padding: 0px; 
- } 
- body { 
-     align-items: center; 
-     background-color: #f9f9f9; 
-     display: flex; 
-     height: 100vh; 
-     justify-content: center; 
- } 
- .flogin { 
-     display: flex; 
-     justify-content: space-between; 
-     width: 400px; 
- } 
- .flogin > .left-side { 
-     background-color: #363636; 
-     border: 9px solid #dedede; 
-     border-right: none; 
-     border-radius: 20px 0px 0px 20px; 
-     width: 80%; 
- } 
- .flogin  > .right-side { 
-     align-items: center; 
-     background-color: #34B5D5; 
-     border: 9px solid #dedede; 
-     border-left: none; 
-     border-radius: 0px 20px 20px 0px; 
-     display: flex; 
-     flex-flow: column nowrap; 
-     justify-content: space-between; 
-     padding: 1.3rem .2rem; 
-     width: calc(20% - 2*.2rem - 9px); 
- } 
- .flogin > .right-side:hover { 
-     cursor: pointer; 
- } 
-   
- /********************* 
-       LEFT SIDE 
- *********************/ 
- .left-side > .head { 
-     border-bottom: 2px dashed #ddd; 
-     color: #eee; 
-     font-family: "segoe ui"; 
-     margin-bottom: 20px; 
-     padding: .75rem 1rem; 
- } 
- .left-side > .body { 
-     padding: .8rem 1.35rem; 
-     width: calc(100% * 2*1.35rem); 
- } 
- .body > .data { 
-     display: flex; 
-     justify-content: space-between; 
- } 
- .form-group { 
-     width: 45%; 
- } 
- .form-group > span { 
-     color: #ddd; 
-     display: block; 
-     font-family: "segoe ui"; 
-     font-size: 10pt; 
-     margin-bottom: 7px; 
- } 
- .form-group > .input-wrapper { 
-     align-items: center; 
-     background-color: white; 
-     border-radius: 5px; 
-     box-shadow: 0px 2px 5px 1px rgba(0,0,0,.4) inset, 
-         0px -1px 2px 1px rgba(0,0,0,.25) inset; 
-     display: flex; 
-     justify-content: space-between; 
- } 
- .input-wrapper > .txt { 
-     width: 80%; 
- } 
- .input-wrapper > i { 
-     color: gold; 
-     width: 20%; 
- } 
- .txt { 
-     background-color: transparent; 
-     border: none; 
-     border-radius: 5px; 
-     padding: .4rem .25rem; 
-     width: calc(80% - 2*.35rem - 2*1px); 
- } 
- .txt:focus { 
-     outline: none; 
- } 
- .help { 
-     display: flex; 
-     justify-content: flex-end; 
- } 
-   
- a { 
-     color: #ddd; 
-     display: block; 
-     font-family: "segoe ui"; 
-     font-size: 10pt; 
-     font-style: italic; 
-     margin-top: 20px; 
-     text-align: right; 
-     text-decoration: none; 
- } 
-   
- /***************** 
-     RIGHT SIDE 
- *****************/ 
- .right-side > i { 
-     color: #fff; 
-     display: block; 
- } 
- .right-side > span { 
-     color: #fff; 
-     display: block; 
-     font-family: "segoe ui"; 
-     font-size: 16pt; 
- } 
Como ven es código HTML simple, en el cual se construye un formulario. Ahora, escribamos el código javascript que nos permita hacer la llamada AJAX al futuro servlet. Éste fichero va dentro del folder assets/js:
- document.addEventListener("DOMContentLoaded", init, true); 
-   
- function init() { 
- 	document.querySelector("#btn-login").addEventListener("click", handleLogin, true); 
-   
- 	function handleLogin(e) { 
- 		e.preventDefault(); 
- 		var txtUsername = document.querySelector("#txt-username"); 
- 		var txtPassword = document.querySelector("#txt-password"); 
-   
- 		var userdata = '{"username":'+txtUsername.value+',"password":'+txtPassword.value+'}'; 
-   
- 		loginByAjax(userdata); 
- 		resetForm(); 
- 	} 
-   
- 	function loginByAjax(data) { 
- 		var request = new XMLHttpRequest(); 
- 		request.open("POST", "LoginController", true); 
- 		request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 
- 		request.onreadystatechange = function() { 
- 			// si la respuesta fue exitosa 
- 			if(request.readyState == 4 && request.status == 200) { 
- 				var message = request.responseText; 
- 				alert(message); 
- 			}  
- 			// si la respuesta trajo error 
- 			else if(request.readyState == 4 && request.status != 200){ 
- 				var message = request.responseText; 
- 				message = request.responseText; 
- 				alert(message); 
- 			} 
- 		}; 
- 		request.send("userdata="+data); 
- 	} 
-   
- 	function resetForm(form) { 
- 		var form = document.querySelector("#flogin"); 
- 		var controls = form.querySelectorAll("input, select"); 
-   
- 		for(var i=0; i<controls.length; i++) { 
- 			var control = controls[i]; 
- 			if(control.nodeName === "INPUT") 
- 				control.value = ""; 
- 			else if(control.nodeName === "SELECT") 
- 				control.selectedIndex = 0; 
- 		} 
- 		controls[0].focus(); 
- 	} 
-   
- } 
Como se puede observar, el código es muy sencillo. Escuchamos por evento 
submit del formulario y le decimos que se ejecutará la función 
handleLogin. Ésta función obtiene los valores ingresados en los textbox del formulario, crea un JSON en forma de texto y se lo envía al método 
loginByAjax(data) para que se envíe al servlet mediante AJAX.
El método 
loginByAjax tiene el siguiente código:
- function loginByAjax(data) { 
- 		var request = new XMLHttpRequest(); 
- 		request.open("POST", "LoginController", true); 
- 		request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 
- 		request.onreadystatechange = function() { 
- 			// si la respuesta fue exitosa 
- 			if(request.readyState == 4 && request.status == 200) { 
- 				var message = request.responseText; 
- 				alert(message); 
- 			}  
- 			// si la respuesta trajo error 
- 			else if(request.readyState == 4 && request.status != 200){ 
- 				var message = request.responseText; 
- 				message = request.responseText; 
- 				alert(message); 
- 			} 
- 		}; 
- 		request.send("userdata="+data); 
- 	} 
Como vemos, el código lo único que hace es hacer una llamada AJAX al servet 
LoginController enviándole el parámetro recibido 
data, que es el JSON en forma de texto:
- request.send("userdata="+data); 
Si la llamada AJAX funciona exitosamente, mostraremos la respuesta retornada desde el servlet en un alert:
- if(request.readyState == 4 && request.status == 200) { 
- 				var message = request.responseText; 
- 				alert(message); 
- 			}  
Caso contrario, se mostrará también el mensaje de error en un alert. Quizás te estés preguntando, porqué la condición:
- if(request.readyState == 4 && request.status == 200) 
La petición tiene 5 estados, que son:
-  0: Petición no inicializada
-  1: Conexión establecida con el servidor.
-  2: Petición recibida
-  3: Procesando petición
-  4: Petición finalizada y respuesta lista.
Así mismo, cada petición tiene muchos códigos de estado. El código 200 indica que la petición ha sido exitosa, 404 indica que el recurso no ha sido encontrado, 500, error del servidor, etc. Puedes ver la lista de códigos 
aquí.
Entonces, el código anterior se puede traducir a:
Si la petición ha finalizado y la respuesta está lista, y además la petición ha sido exitosa...
Por último, reseteamos el formulario para limpiar los campos y colocar el foco en el textbox del nombre de usuario.
Ahora, nos queda crear nuestro servlet. Nuestro servlet se llamará 
LoginController y tendrá el siguiente código:
- package com.company.controllers; 
-   
- import java.io.IOException; 
- import java.io.PrintWriter; 
- import java.util.logging.Logger; 
-   
- import javax.servlet.ServletException; 
- import javax.servlet.annotation.WebServlet; 
- import javax.servlet.http.HttpServlet; 
- import javax.servlet.http.HttpServletRequest; 
- import javax.servlet.http.HttpServletResponse; 
-   
- import org.json.JSONObject; 
-   
- @WebServlet(asyncSupported=true, urlPatterns={"/LoginController"}) 
- public class LoginController extends HttpServlet { 
- 	private static final long serialVersionUID = 1L; 
- 	private static final Logger logger = Logger.getLogger("LoginLogger"); 
-   
-     public LoginController() { 
-         super(); 
-     } 
-   
-     public void-  processRequest (- HttpServletRequest request, HttpServletResponse response ) throws-  ServletException,  IOException {
 
-     	response.setContentType("text/plain"); 
-     	String-  strJson  =-  request. getParameter("userdata"); // obtiene lo enviado por AJAX
 
-     	JSONObject json = new JSONObject(strJson); 
-   
-     	if(username.equals("Duke") && password.equals("Duke777")) { 
-     		writer.print("Usuario correctamente identificado"); 
-     	} else { 
-     		writer.print("Usuario o contraseña incorrectas"); 
-     	} 
-     	writer.flush(); 
-     	writer.close(); 
-     } 
-   
-     @Override 
- 	protected void doGet(HttpServletRequest request, HttpServletResponse response) { 
- 		try { 
- 			processRequest(request, response); 
- 			logger.warning(e.getLocalizedMessage()); 
- 		} 
- 	} 
-   
-     @Override 
- 	protected void-  doPost (- HttpServletRequest request, HttpServletResponse response ) throws-  ServletException,  IOException {
 
- 		try { 
-     		processRequest(request, response); 
-     		logger.warning(e.getLocalizedMessage()); 
-     	} 
- 	} 
-   
- } 
Nuestro servlet no es nada del otro mundo, es muy sencillo. Explicaré las siguientes lineas:
- String-  strJson  =-  request. getParameter("userdata"); // obtiene lo enviado por AJAX
 
-     	JSONObject json = new JSONObject(strJson); 
¿Recuerdas que en el código AJAX enviamos el JSON con el nombre de usuario y contraseña en formato texto? Bien, y tenía como identificador 
userdata.
Como ves, esa 
variable userdata con el valor del JSON enviado desde AJAX, lo podemos obtener en nuestro Servlet mediante el método 
getParameter, el cual obtiene un valor pasado por parámetro mediante su identificador.
En éste momento, 
strJson es equivalente al JSON en forma de texto enviado desde AJAX:
- var userdata = '{"username":'+txtUsername.value+',"password":'+txtPassword.value+'}'; 
Una vez que tenemos el valor enviado en nuestro servlet, lo que vamos a hacer es convertirlo a JSONObject:
- JSONObject json = new JSONObject(strJson); 
JSONObject hace uso de un objeto tipo Map para poder trabajar fácilmente con pares "llave - valor". Por lo que, por medio de la llave podemos obtener su valor. Las llaves son 
username y 
password, entonces, solo obtenemos sus valores:
Y por último, evaluamos si el usuario es 
Duke y si la contraseña es 
Duke777. Si es correcto enviaremos el mensaje 
Usuario correctamente identificado o 
Usuario o contraseña incorrecta de vuelta a la llamada AJAX.
Una vez que la respuesta ha sido devuelta a la llamada AJAX, solo la mostramos en un alert:
- if(request.readyState == 4 && request.status == 200) { 
- 				var message = request.responseText; 
- 				alert(message); 
- 			}  
- 			// si la respuesta trajo error 
- 			else if(request.readyState == 4 && request.status != 200){ 
- 				var message = request.responseText; 
- 				message = request.responseText; 
- 				alert(message); 
- 			} 
CONCLUSIÓN
Como el lector se ha dado cuenta, comunicar servlets con AJAX es realmente muy sencillo, tan sencillo como en otros lenguajes 

¡Hasta la próxima!