Электронный магазин на Java и XML

       

Код сервлета управления опросом


В листинге 7.4 показаны инструкции импорта, объявления классов и метод init для сервлета QuestionnaireServ. Статическая переменная homedir, значение которой может быть получено из ServletConfig, используется в методе init для считывания файла свойств. С помощью этого файла задается путь к исходному файлу XML для данной анкеты. Также файл свойств может потребоваться для того, чтобы задать значение переменной handler типа Srting. Это значение равно URL- адресу, который используется web-сервером для данного сервлета.

Листинг 7.4. Начало кода сервлета QuestionnaireServ (QuestionnaireServ.java)

package com.XmlEcomBook.Chap07;

import com.XmlEcomBook.DOMlibrary ; import org.w3c.dom.* ; import java.io.*; import java.util.* ; import javax.servlet.*; import javax.servlet.http.*;

public class QuestionnaireServ extends HttpServlet { static String brcrlf = "<br>\r\n" ; static String homedir = "e:\\scripts\\questionnaire" ; static String handler = "http://www.lanw.com/servlet/Questionnaire" ; static String version = "v1.0"; Properties qProp ;

public void init(ServletConfig config) throws ServletException { super.init(config); String tmp = config.getInitParameter("homedir"); if( tmp != null ) homedir = tmp ; System.out.println("Start QuestionnaireServ using " + homedir ); File f = new File( homedir, "questionnaire.properties"); try { qProp = new Properties(); qProp.load( new FileInputStream(f) ); tmp = qProp.getProperty("handler"); if( tmp != null ) handler = tmp ; System.out.println ("Loaded properties for Questionnaire handler: " + handler ); }catch(IOException e){ System.out.println("Error loading " + e ); } }

Сервлет QuestionnaireServ отслеживает взаимодействие с каждым пользователем, отвечающим на вопросы анкеты, в сеансах. Предполагается, что исходный запрос — это запрос методом GET с HTML-страницы, на которой имеется простая форма для определения значения переменной qname, идентифицирующей требуемую анкету. Приспосабливая этот сервлет для своего приложения, вы на этом этапе можете также записать идентификатор пользователя.


Метод doGet, показанный в листинге 7.5, отыскивает объект document, соответствующий значению переменной qname, используя путь, указанный в файле свойств, и служебную библиотеку DOMlibrary. Если ему удается найти этот объект, далее он получает объект HttpSession и присоединяет к сеансу новый объект Interpreter, в котором хранится документ. Новый объект Recorder также инициализируется и присоединяется к сеансу. Для обработки любой ошибки и создания соответствующего сообщения используется метод errorMsg (см. листинг 7.7).

Объект Interpreter отвечает за создание форм HTML, с помощью которых будет осуществляться опрос, а объект Recorder отвечает за запись ответов пользователя. Эти классы обсуждаются в разделах «Класс Interpreter» и «Класс Recorder».

Результатом вызова метода doGet является страница с текстом, содержащимся в теге Intro документа XML. Для отображения этого текста на странице используется метод dolntro объекта Interpreter; также на странице располагается форма с кнопкой, при щелчке на которой появляется первый вопрос анкеты.





Листинг 7.5. Код метода doGet (QuestionnaireServ.java)

public void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); PrintWriter out = new PrintWriter(resp.getOutputStream()); String qname = req.getParameter("qname") ; // System.out.println("Start doGet"); if( qname == null || qname.length() == 0 ){ errorMsg( out, "Bad QNAME data", null); return; } // MUST have qname = name of xml file String src = qProp.getProperty( qname ); if( src == null ) { errorMsg( out, "Bad QNAME lookup", null ); return ; } String userid = "unknown" ; // customer or student id or unknown String tmp = req.getParameter("userid"); if( tmp != null ) userid = tmp; String usertype = "unknown" ; // "student" "customer" etc etc tmp = req.getParameter("usertype"); if(tmp != null ) usertype = tmp ; DOMlibrary lib = DOMlibrary.getLibrary(); System.out.println("DOMlibrary initialized, try for " + src ); Document doc = lib.getDOM( src ); if( doc == null ){ errorMsg( out, "DOM doc failed - unable to continue", null ); return ; } HttpSession session = req.getSession( true ); // if not new must be re-entering - could recover here Interpreter terpret = new Interpreter( doc, handler ); session.putValue( "xmldocument", terpret ); // session.setAttribute("xmldocument",terpret ); // the putValue method was used in the 2.1 API but is now // a deprecated method, // Recorder rb = new Recorder(userid, usertype, session.getId(), src ); rb.setMethods( doc ); session.putValue("recorder", rb ); //session.setAttribute("recorder", rb ); try { // terpret.doIntro( out ); // includes head and Form footer( out ); }catch(Exception e){ errorMsg( out, "doGet ", e ); }



После введения в анкету, как видно из листинга 7.6, все запросы и ответы проходят через метод doPost. После извлечения из объекта HttpSession объектов Interpreter и Recorder данные запроса собираются и с помощью объектов Interpreter и Recorder генерируется ответ.



Листинг 7.6. Метод doPost класса QuestionnaireServ (QuestionnaireServ.java)

public void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); PrintWriter out = new PrintWriter(resp.getOutputStream()); //System.out.println("Start doPost"); HttpSession session = req.getSession(false); try { if( session == null ){ errorMsg(out, "No Session ", null ); return ; } Interpreter terpret = (Interpreter)session.getValue("xmldocument"); //deprecated //in 2.2 API we use this // (Interpreter)session.getAttribute("xmldocument"); Recorder rb = (Recorder) session.getValue("recorder"); // (Recorder) session.getValue("recorder"); if( terpret == null || rb == null ){ errorMsg( out, "Data not recovered from Session", null ); return; } terpret.doPostQ( out, req, rb ); footer( out ); }catch(Exception e ){ errorMsg( out, "doPost ", e ); } }

В листинге 7.7 показаны некоторые полезные вспомогательные методы класса QuestionnaireServ. Используя метод footer для размещения закрывающих те- гов на каждой странице, можно внизу указывать версию сервлета. Это очень удобно на этапе разработки, а впоследствии из финальной версии сервлета эти теги можно легко удалить.

Отладка сервлетов может оказаться очень непростым делом, особенно если ошибки проявляются лишь время от времени. Отладка особенно затрудняется в том случае, если пользователи не могут четко и однозначно выразить свои проблемы. Для сообщения об ошибках мы предпочитаем использовать метод erroMsg. Если ошибка связана с каким-либо исключением, то на HTML-странице появится сообщение с содержимым стека. Там же указывается и электронный адрес, по которому пользователь может послать сообщение об ошибке и, мы надеемся, копию содержимого стека. Разумеется, вам следует заменить приведенный ниже электронный адрес на свой.





Листинг 7.7. Вспомогательные методы сервлета QuestionnaireServ (QuestionnaireServ.java)

public void footer( PrintWriter out ){ out.println("<hr> Servlet version: " + version + "<br>"); out.println("</body>"); out.println("</html>"); out.close(); }

// assumes response has been set to text/html private void errorMsg ( PrintWriter out, String msg, Exception ex ){ out.println("<html>"); out.println("<head> <title>QuestionnaireServ Output</title></head>"); out.println("<body>"); out.println("<h2>Error: " ); out.println( msg ); out.println("</h2><br>"); if( ex != null ){ ex.printStackTrace( out ); } out.println("<br>"); out.println("<a href=\"mailto:wbrogden@bga.com\"> Please mail me the error message.</a><br>"); footer( out ); }

public String getServletInfo() { return "Administers a questionnaire"; }

}






Содержание раздела