powered by simpleCommunicator - 2.0.58     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Как лучше получить в сервлете на выходе XML?
10 сообщений из 10, страница 1 из 1
Как лучше получить в сервлете на выходе XML?
    #32709007
sanitar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код тестовый, учебный можно сказать. В общем есть сервлет, коннект к базе, результат запроса. Как лучше его вывести с использованием 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
Как лучше получить в сервлете на выходе XML?
    #32709187
NotGonnaGetUs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А чем тебе этот вариант не нравится (кроме того что sXml должен быть CтрингБуффер)? Всё как у людей :)

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

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

Если совсем не нравится обращение к rst.getString(), можно накидать полученные rst в класс наследник от StreamSource() и брать напрямую из bytes, благо доступ к Stream последовательный :)
...
Рейтинг: 0 / 0
Как лучше получить в сервлете на выходе XML?
    #32709352
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
XSLT трансформацию можно делать как на сервере так и на клиенте. С сервером правда будет надежнее т.к. не все клиенты на сегодняшний день поддерживают XSL трансформацию. IE - первый браузер который реально поддержал XML-XSLT технологию
...
Рейтинг: 0 / 0
Как лучше получить в сервлете на выходе XML?
    #32710105
wessen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я бы еще посоветовал формировать 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
Как лучше получить в сервлете на выходе XML?
    #32710135
wessen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NotGonnaGetUs Тогда ничто не помешает в будущем сделать кеш/пул для xsl трансформов, что бы не перезагружать их постоянно.


Можно поподробнее про кеш/пул для xsl трансформов. Может есть примерчик, а то я сейчас пишу веб-приложение, весь вывод у меня через xml/xsl преобразования, ложу в определенную область видимости объект(Node например, как в пред. посте) а затем кастом таг достает этот объект, загружает XSLT процессор и делает свое дело, и этот таг, делает это при каждом обращении, вот я сейчас и думаю над тем, как бы загрузить трансформатор один раз и юзать его потом со всех потоков, в плотную я этим еще не занимался, но думаю, что будет проблема с синхронизацией.
...
Рейтинг: 0 / 0
Как лучше получить в сервлете на выходе XML?
    #32711387
NotGonnaGetUs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Как лучше получить в сервлете на выходе XML?
    #32712619
wessen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2NotGonnaGetUs
Ооо, это все для меня ?:)
Спасибо, буду разбираться.
вот еще нарыл
...
Рейтинг: 0 / 0
Как лучше получить в сервлете на выходе XML?
    #32713958
NotGonnaGetUs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wessen
вот еще нарыл
Мне тоже не нравилась идея с free & busy хранилищами :)
...
Рейтинг: 0 / 0
Как лучше получить в сервлете на выходе XML?
    #32713994
NotGonnaGetUs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
NotGonnaGetUs wessen
вот еще нарыл
Мне тоже не нравилась идея с free & busy хранилищами :)
Правда в статье предлагают хешить только фактори, а сами трансформеры создаются каждый раз заново.
Вполне возможно, что из-за полного лока на чтение из пула (как у меня), быстрее будет создавать трансформеры заново, чем ждать своей очереди.
Но для этого читающих потоков должно быть действительно много :)
Кроме того, процедура апдейта кешированных значений упрощается если нет пула...
...
Рейтинг: 0 / 0
Как лучше получить в сервлете на выходе XML?
    #32714021
NotGonnaGetUs
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
^^^ вот это меня колбсит :)
templates, а не фактори. А поскольку там компиленные xsl'ки, то пул и не упёрся никуда по крупному счёту.
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Как лучше получить в сервлете на выходе XML?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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