Tämän laittaminen on jonkin verran viivästynyt, mutta olen laatinut arkkityypiksi kelpaavan verkkoprojektiesimerkin. Se on saatavissa tästä linkistä:
Sitä voi kokeilla avaamalla paketin:
$ unzip -d warproject warproject.zip $ cd warproject $ mvn clean install $ mvn jetty:run
ja täyttämällä lomakkeen osoitteessa http://localhost:8080/lomake
Painamalla nappia ”Lähetä”, ladataan uusi sivu, jossa toistetaan täytetyt tiedot ja painamalla nappia ”Lähetä AJAX”, muodostetaan AJAX-pyyntö, jonka perusteella vastaus tuotetaan Javascriptillä selaimen ruudulle. Seuraavassa selitetään tarkemmin sovelluksen eri osia ja mitä on muuttunut ”jarproject”-Maven-projektiin nähden.
Laitetaan seuraavaksi kokonaisuudessaan Maven-projektin selitystiedosto pom.xml
:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>fi.mikkonummelin</groupId> <artifactId>warproject</artifactId> <packaging>war</packaging> <version>0.1-SNAPSHOT</version> <name>${project.artifactId}</name> <url>http://www.mikkonummelin.fi</url> <!-- EXAMPLE! For release plugin. <scm> <developerConnection>scm:git:file:///home/mnummeli/Asiakirjat/java/jarproject</developerConnection> <tag>HEAD</tag> </scm> --> <properties> <commons-logging.version>1.1.3</commons-logging.version> <junit.version>4.11</junit.version> <log4j.version>1.2.17</log4j.version> <servlet-api.version>3.1.0</servlet-api.version> <jsp-api.version>2.3.1</jsp-api.version> <jstl.version>1.2</jstl.version> <jackson-databind.version>2.3.0</jackson-databind.version> </properties> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet-api.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>${jsp-api.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson-databind.version}</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>${commons-logging.version}</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.7</source> <target>1.7</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>2.6</version> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.4</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.1.1.v20140108</version> </plugin> </plugins> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> <!-- EXAMPLE! For release plugin. <distributionManagement> <repository> <id>Local Releases</id> <name>My Local Releases Repository</name> <url>file:///home/mnummeli/maven-releases</url> </repository> </distributionManagement> --> </project>
Uusina liitännäisinä tässä ovat maven-war-plugin ja jetty-maven-plugin. Ensinmainittu määrittelee, että projekti käännetään Java-sovelluspalvelimelle, kuten Tomcatille, Jettylle, JBossille tm. kelpaavaksi verkkosovellukseksi ja jälkimmäisenä mainittu taas määrittelee, että lähtökohtaisesti käytetään sisäänrakennettua Jettyä.
Mistä sitten tulivat sovelluksen verkkosivut ja niiden toiminnallisuus? Lomake on määritelty seuraavasti:
<%@page contentType="text/html" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <link rel="stylesheet" type="text/css" href="/css/style.css" /> <title>Lomake</title> <script src="/js/jquery-1.11.0.min.js"></script> <script src="/js/lomake.js"></script> </head> <body> <div class="m1"> <h1>Täytä lomake</h1> <hr/> <form action="lomake/vastaus"> <p style="float: left;">Nimi:</p><input type="text" id="nimi" name="nimi"/><div style="clear: both;"></div> <p style="float: left;">Osoite:</p><input type="text" id="osoite" name="osoite"/><div style="clear: both;"></div> <input type="submit" value="Lähetä"/> <button id="laheta_ajax" type="button">Lähetä AJAX-viesti</button> </form> <p id="ajaxvastauksentulos"> </p> </div> </body> </html>
ja vastaussivu samaan tapaan, tosin yksinkertaisempana. Kun selaimeen kirjoitti:
http://localhost:8080/lomake
tunnisti sovelluspalvelin ilmaisun ”/lomake” sovelman nimeksi ja kykeni ratkaisemaan sen huomioimalla tiedostosta LomakeServlet.java, annotaation WebServlet:
package fi.mikkonummelin.warproject; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.*; import javax.servlet.*; import javax.servlet.annotation.*; import javax.servlet.http.*; import org.apache.commons.logging.*; @WebServlet("/lomake/*") public class LomakeServlet extends HttpServlet { private static final Log LOG = LogFactory.getLog(LomakeServlet.class); private void defaultAction(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.getRequestDispatcher("/WEB-INF/lomake.jsp").forward(req, resp); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String pathName = req.getPathInfo(); LOG.info("Pathname: " + pathName); if (pathName == null) { defaultAction(req, resp); return; } switch (pathName) { case "/vastaus": { String nimi = req.getParameter("nimi"); String osoite = req.getParameter("osoite"); req.setAttribute("nimi", nimi); req.setAttribute("osoite", osoite); req.getRequestDispatcher("/WEB-INF/vastaus.jsp").forward(req, resp); break; } case "/ajaxvastaus": { LOG.info("AJAX:ia kysytty!"); String nimi = req.getParameter("nimi"); String osoite = req.getParameter("osoite"); resp.setContentType("application/json"); LOG.info("nimi="+nimi+", osoite="+osoite); NimiJaOsoite njo = new NimiJaOsoite(nimi, osoite); ObjectMapper mapper; mapper = new ObjectMapper(); mapper.writeValue(resp.getOutputStream(), njo); break; } default: { defaultAction(req, resp); } } } }
ja vastaavasti vastaus tai AJAX-vastaus on prosessoitu omissa vaihtoehdoissaan tarkemman polkunimen perusteella. AJAX-vastaus vaatii lisäksi sen, että lomakkeessa mainittu nappi laheta_ajax on liitetty JQuery-JavaScript-kirjaston avulla seuraavanlaiseen JavaScript-ohjelmanpätkään:
$(document).ready(function() { $('#laheta_ajax').click(function() { $.ajax({ url: '/lomake/ajaxvastaus', data: { nimi: $('#nimi').val(), osoite: $('#osoite').val() }, type: 'GET', dataType: 'json', success: function(json) { $('#ajaxvastauksentulos').html('Hei ' + json.nimi + "! Annoit osoitteeksesi " + json.osoite + "."); } }); }); });
Mainittu JavaScript-pätkä myös muokkaa sivua sopivasti.