Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Как лучше получить в сервлете на выходе XML? / 10 сообщений из 10, страница 1 из 1
23.09.2004, 16:46
    #32709007
sanitar
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как лучше получить в сервлете на выходе XML?
Код тестовый, учебный можно сказать. В общем есть сервлет, коннект к базе, результат запроса. Как лучше его вывести с использованием XSLT. В коде ниже результат запроса я передаю в строку, но чувствую что это не совсем хорошо.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
package nonbr;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import DBConnection.*;
import java.sql.*;
import java.util.*;
import xmlUtils.*;
import java.io.PrintWriter;
import java.io.OutputStream;

public class TransformServlet extends HttpServlet {

    public void doGet(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {

        String path=this.getServletContext().getRealPath("/");

        Result result = new StreamResult(res.getOutputStream());

        DBConnection DBC = new DBConnection("sa","sqladmin");

        String sXML="";

        if (DBC.ok)  {
          Connection c = DBC.getConn();
          Statement stmt = null;
             try {
               stmt = c.createStatement();
               ResultSet rst = null;
               rst = stmt.executeQuery("select id, name from sysobjects for xml auto, elements");
               while (rst.next()) {
                 String s = rst.getString(1);
                 sXML = sXML + s;
               }
               rst.close();
               sXML="<xmlroot>"+sXML+"</xmlroot>";
               System.out.println(sXML);

             }
             catch (SQLException ex) {
                   ex.printStackTrace();
             }
          try {  // Это преобразование XML строки с помощью XSL файла 
              StringBufferInputStream strXML = new StringBufferInputStream(sXML);
              Source xmlSource = new StreamSource(strXML);
              Source xsltSource = new StreamSource(path+"sysobjects.xsl");

             res.setContentType("text/html");
               // get the factory 
              TransformerFactory transFact = TransformerFactory.newInstance();

               // get a transformer for this particular stylesheet 
              Transformer trans = transFact.newTransformer(xsltSource);
              trans.setOutputProperty(OutputKeys.ENCODING,"WINDOWS-1251");
               // do the transformation 
              trans.transform(xmlSource, result);

          } catch (Exception ex) {
              throw new ServletException(ex);
          }

        }
        else {
          System.out.println("Login or password incorrect or SQL server is unavailable");
          System.exit(1);
        }
    }
}
...
Рейтинг: 0 / 0
23.09.2004, 17:52
    #32709187
NotGonnaGetUs
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как лучше получить в сервлете на выходе XML?
А чем тебе этот вариант не нравится (кроме того что sXml должен быть CтрингБуффер)? Всё как у людей :)

Если скучно, можно разнести разные действия (коннект, выполнение запроса, трансформация результата) в разные методы, если не классы, что бы это не обросло потом геморроем.
Можно обдумать процесс автоматизации поиска нужной xsl для заданного xml
(по запросу к базе, по root-тагу xml, etc).
Тогда ничто не помешает в будущем сделать кеш/пул для xsl трансформов, что бы не перезагружать их постоянно.

У нас как ни как ООП, поэтому выносить определения переменных в начало метода не зачем (result, path). Где надо, там и используем. А вот, что res.setContentType("text/html"); делает в коде выполняющем преобразование xsl не ясно :)

Если совсем не нравится обращение к rst.getString(), можно накидать полученные rst в класс наследник от StreamSource() и брать напрямую из bytes, благо доступ к Stream последовательный :)
...
Рейтинг: 0 / 0
23.09.2004, 19:52
    #32709352
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как лучше получить в сервлете на выходе XML?
XSLT трансформацию можно делать как на сервере так и на клиенте. С сервером правда будет надежнее т.к. не все клиенты на сегодняшний день поддерживают XSL трансформацию. IE - первый браузер который реально поддержал XML-XSLT технологию
...
Рейтинг: 0 / 0
24.09.2004, 12:11
    #32710105
wessen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как лучше получить в сервлете на выходе XML?
Я бы еще посоветовал формировать XML используя API, а то если xml будет сложным, то замучеешься ты совсем со всеми вложенными елементами и аттребутами.. :)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
package jmobilshop.actions;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.sql.*;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

import actions.ActionBase;
import actions.ActionRouter;
import jmobilshop.beans.*;

public class ShowPhoneListAction
    extends ActionBase {
  private Document doc;
  private PreparedStatement phoneFirmList;  // 
  private PreparedStatement firmName; // 
  private Connection conn;
  private DBBean dbBean;
  private String firmId;

  public ShowPhoneListAction() {
    try {
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder = factory.newDocumentBuilder();
      doc = builder.newDocument();
    }
    catch (ParserConfigurationException ex) {
      ex.printStackTrace(System.out);
    }
  }

  public ActionRouter perform(HttpServlet servlet,
                              HttpServletRequest req,
                              HttpServletResponse res) throws ServletException,
      SQLException {
    if (dbBean == null) {
      dbBean = (DBBean) servlet.getServletContext().getAttribute("dbBean");
      conn = dbBean.getConnection();
      phoneFirmList = conn.prepareStatement("select * from phones where firm_id=?");
      firmName=conn.prepareStatement("select name from phone_firms where id=?");
    }
    try {
       // 
      firmName.setString(1,req.getParameter("id"));
      ResultSet rs=firmName.executeQuery();
      rs.next();
      firmId=rs.getString("name");
       // 
      phoneFirmList.setString(1, req.getParameter("id"));
      rs = phoneFirmList.executeQuery();

       //test(getPhoneListXML(rs)); 
       //ложим в request объек Node  
      req.setAttribute("phoneList", getPhoneListXML(rs));

    }
    catch (SQLException ex) {
    }
    return new ActionRouter("show_phone_list_page");
  }

   //создаем XML(объек Node)для телефонов выбраной фирмы 
  Node getPhoneListXML(ResultSet rs) throws SQLException {
    Element phoneList = doc.createElement("phoneList");
    phoneList.setAttribute("firm",firmId);
    while (rs.next()) {
      Element phone = doc.createElement("phone");
      phone.setAttribute("id",String.valueOf(rs.getInt("id")));

      Element temp = doc.createElement("model");
      temp.appendChild(doc.createTextNode(rs.getString("model")));
      phone.appendChild(temp);

      temp = doc.createElement("img");
      temp.appendChild(doc.createTextNode(rs.getString("image_hreff")));
      phone.appendChild(temp);

      temp = doc.createElement("price");
      temp.appendChild(doc.createTextNode(rs.getString("price")));
      phone.appendChild(temp);

      temp = doc.createElement("priceConn");
      temp.appendChild(doc.createTextNode(rs.getString("price_conn")));
      phone.appendChild(temp);

      temp = doc.createElement("status");
      temp.appendChild(doc.createTextNode(rs.getString("stat")));
      phone.appendChild(temp);

      temp = doc.createElement("standart");
      temp.appendChild(doc.createTextNode(rs.getString("standart")));
      phone.appendChild(temp);

      phoneList.appendChild(phone);
    }
    return phoneList;
  }
 //вывод получившегося XML в консоль(для отладки) 
  void test(Node n) {
    TransformerFactory factory = TransformerFactory.newInstance();
    Source domSource = new DOMSource(n);
    try {
      Transformer trans = factory.newTransformer();
      trans.setOutputProperty(OutputKeys.ENCODING, "Cp1251");
      trans.transform(domSource, new StreamResult(System.out));
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

}
...
Рейтинг: 0 / 0
24.09.2004, 12:22
    #32710135
wessen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как лучше получить в сервлете на выходе XML?
NotGonnaGetUs Тогда ничто не помешает в будущем сделать кеш/пул для xsl трансформов, что бы не перезагружать их постоянно.


Можно поподробнее про кеш/пул для xsl трансформов. Может есть примерчик, а то я сейчас пишу веб-приложение, весь вывод у меня через xml/xsl преобразования, ложу в определенную область видимости объект(Node например, как в пред. посте) а затем кастом таг достает этот объект, загружает XSLT процессор и делает свое дело, и этот таг, делает это при каждом обращении, вот я сейчас и думаю над тем, как бы загрузить трансформатор один раз и юзать его потом со всех потоков, в плотную я этим еще не занимался, но думаю, что будет проблема с синхронизацией.
...
Рейтинг: 0 / 0
25.09.2004, 02:22
    #32711387
NotGonnaGetUs
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как лучше получить в сервлете на выходе XML?
wessenМожно поподробнее про кеш/пул для xsl трансформов. Может есть примерчик,
...
но думаю, что будет проблема с синхронизацией.

Конечно будет. Transformer не синхранизирован. Поэтому каждому потоку нужно давать свой трансформер и поэтому нужен не столько кеш, сколько пул.

В первом приближении это можно изобразить в виде ниже приведённого кода. Я его не тестировал, так что может где описался. В конце концов это просто иллюстрация идеи написанная в полвторого ночи :)
Если какие вопросы возникнут - милости прошу :)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
import org.w3c.dom.Node;

import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.OutputStream;
import java.util.*;

public class XslCache {
    private static Cache poolCache = new Cache();

    private XslCache() {};

    public static void transform(Node xmlNode, OutputStream output, String xslName) throws TransformerException {
        Pool pool = poolCache.getPoolFor(xslName);
        Transformer transformer = pool.getTransformer();
        try {
            Source xmlSource = new DOMSource(xmlNode);
            Result result = new StreamResult(output);
            transformer.transform(xmlSource, result);
        } catch (TransformerException e) {
            throw e;
        } finally {
            pool.releaseTransformer(transformer);
        }
    }

    public static void clear() {
        poolCache.clear();
    }
}

class Cache {
    private static final int MAX_SIZE = 100;
    private LinkedHashMap poolCache = new LinkedHashMap();
    private RWLock lock;

    Cache() {
        lock = new RWLock(poolCache);
    }

    public Pool getPoolFor(String xslName) throws TransformerException {
        lock.getReadLock();
        if (!poolCache.containsKey(xslName)) {
            lock.releaseLock();
            addNewPoolFor(xslName);
            lock.getReadLock();
        }
        Pool result = (Pool) poolCache.get(xslName);
        lock.releaseLock();
        return result;
    }

    public void clear() {
        lock.getWriteLock();
        Iterator iterator = poolCache.keySet().iterator();
        while (iterator.hasNext()) {
            Pool pool = (Pool) iterator.next();
            pool.clear();
        }
        poolCache.clear();
        lock.releaseLock();
    }

    private void addNewPoolFor(String xslName) throws TransformerException {
        lock.getWriteLock();
        if (!poolCache.containsKey(xslName)) {
            poolCache.put(xslName, new Pool(xslName));
        }
        checkOverflow();
        lock.releaseLock();
    }

    private void checkOverflow() {
        if (poolCache.size() > MAX_SIZE) {
            Object firstAddedPool = poolCache.keySet().iterator().next();
            poolCache.remove(firstAddedPool);
        }
    }
}

class Pool {
    private final static int MAX_SIZE = 10;
    private final String xslName;
    private LinkedList free = new LinkedList();
    private LinkedList buzy = new LinkedList();

    public Pool(String xslName) throws TransformerException {
        this.xslName = xslName;
    }

    public Transformer getTransformer() throws TransformerException {
        synchronized (this) {
            if (free.isEmpty()) {
                if (buzy.size() < MAX_SIZE) {
                    free.addLast(createNewTransformer());
                } else {
                    return createNewTransformer();
                }
            }
            Transformer transformer = (Transformer) free.removeLast();
            buzy.addLast(transformer);
            return transformer;
        }
    }

    public void releaseTransformer(Transformer trans) {
        synchronized (this) {
            if (buzy.remove(trans)) {
                free.addLast(trans);
            }
        }
    }

    public void clear() {
        synchronized (this) {
            free.clear();
            buzy.clear();
        }
    }

    private Transformer createNewTransformer() throws TransformerException {
        TransformerFactory transFact = TransformerFactory.newInstance();
        Source xsltSource = new StreamSource(xslName);
        return transFact.newTransformer(xsltSource);
    }
}

class RWLock {
    private int waitingRead;
    private int waitingWrite;
    private int hasReadLock;
    private boolean isWriteLock;
    private Object lockedObject;

    RWLock(Object locked) {
        lockedObject = locked;
    }

    void getReadLock() {
        synchronized (lockedObject) {
            waitingRead++;
            while (waitingWrite != 0 || isWriteLock) {
                try {
                    lockedObject.wait();
                } catch (InterruptedException e) {
                }
            }
            waitingRead--;
            hasReadLock++;
        }
    }

    void getWriteLock() {
        synchronized (lockedObject) {
            waitingWrite++;
            while (hasReadLock != 0) {
                try {
                    lockedObject.wait();
                } catch (InterruptedException e) {
                }
            }
            waitingWrite--;
            isWriteLock = true;
        }
    }

    void releaseLock() {
        synchronized (lockedObject) {
            if (isWriteLock) {
                isWriteLock = false;
            } else {
                hasReadLock--;
            }
            lockedObject.notifyAll();
        }
    }
}
...
Рейтинг: 0 / 0
27.09.2004, 13:20
    #32712619
wessen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как лучше получить в сервлете на выходе XML?
2NotGonnaGetUs
Ооо, это все для меня ?:)
Спасибо, буду разбираться.
вот еще нарыл
...
Рейтинг: 0 / 0
28.09.2004, 09:30
    #32713958
NotGonnaGetUs
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как лучше получить в сервлете на выходе XML?
wessen
вот еще нарыл
Мне тоже не нравилась идея с free & busy хранилищами :)
...
Рейтинг: 0 / 0
28.09.2004, 09:46
    #32713994
NotGonnaGetUs
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как лучше получить в сервлете на выходе XML?
NotGonnaGetUs wessen
вот еще нарыл
Мне тоже не нравилась идея с free & busy хранилищами :)
Правда в статье предлагают хешить только фактори, а сами трансформеры создаются каждый раз заново.
Вполне возможно, что из-за полного лока на чтение из пула (как у меня), быстрее будет создавать трансформеры заново, чем ждать своей очереди.
Но для этого читающих потоков должно быть действительно много :)
Кроме того, процедура апдейта кешированных значений упрощается если нет пула...
...
Рейтинг: 0 / 0
28.09.2004, 09:58
    #32714021
NotGonnaGetUs
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как лучше получить в сервлете на выходе XML?
^^^ вот это меня колбсит :)
templates, а не фактори. А поскольку там компиленные xsl'ки, то пул и не упёрся никуда по крупному счёту.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Как лучше получить в сервлете на выходе XML? / 10 сообщений из 10, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]