Эффективное создание HTML-таблицы CSS с использованием Java

Я пытаюсь создать таблицу HTML с помощью Java. У меня есть объект, который я выполняю для создания таблицы HTML.

StringBuilder sb = new StringBuilder();
sb.append("<html>");
sb.append("<head>");
sb.append("</head>");
sb.append("<table>");
sb.append("<th style = \"background: #333; color: white; font-weight: bold; padding: 6px; border: 1px solid #ccc; text-align: left;\"> ClientName");
sb.append("</th>");
sb.append("<th style = \"background: #333; color: white; font-weight: bold; padding: 6px; border: 1px solid #ccc; text-align: left;\"> SyncCount");
sb.append("</th>");
sb.append("<th style = \"background: #333; color: white; font-weight: bold; padding: 6px; border: 1px solid #ccc; text-align: left;\"> SyncPercentile");
sb.append("</th>");
sb.append("<th style = \"background: #333; color: white; font-weight: bold; padding: 6px; border: 1px solid #ccc; text-align: left;\"> SyncAvg");
sb.append("</th>");
sb.append("<th style = \"background: #333; color: white; font-weight: bold; padding: 6px; border: 1px solid #ccc; text-align: left;\"> SyncMax");
sb.append("</th>");
sb.append("<th style = \"background: #333; color: white; font-weight: bold; padding: 6px; border: 1px solid #ccc; text-align: left;\"> AsyncCount");
sb.append("</th>");
sb.append("<th style = \"background: #333; color: white; font-weight: bold; padding: 6px; border: 1px solid #ccc; text-align: left;\"> AsyncPercentile");
sb.append("</th>");
sb.append("<th style = \"background: #333; color: white; font-weight: bold; padding: 6px; border: 1px solid #ccc; text-align: left;\"> AsyncAvg");
sb.append("</th>");

for (DataMetrics metrics : dataMetricsList) {
    sb.append("<tr>");
    sb.append("<td style = \"padding: 6px; border: 1px solid #ccc; text-align: left;\"> " + metrics.getName());
    sb.append("</td>");
    sb.append("<td style = \"padding: 6px; border: 1px solid #ccc; text-align: left;\"> " + metrics.getSyncCall());
    sb.append("</td>");
    sb.append("<td style = \"padding: 6px; border: 1px solid #ccc; text-align: left;\"> " + metrics.getSyncPercent());
    sb.append("</td>");
    sb.append("<td style = \"padding: 6px; border: 1px solid #ccc; text-align: left;\"> " + metrics.getSyncAvg());
    sb.append("</td>");
    sb.append("<td style = \"padding: 6px; border: 1px solid #ccc; text-align: left;\"> " + metrics.getSyncMax());
    sb.append("</td>");
    sb.append("<td style = \"padding: 6px; border: 1px solid #ccc; text-align: left;\"> " + metrics.getAsyncCall());
    sb.append("</td>");
    sb.append("<td style = \"padding: 6px; border: 1px solid #ccc; text-align: left;\"> " + metrics.getAsyncPercent());
    sb.append("</td>");
    sb.append("<td style = \"padding: 6px; border: 1px solid #ccc; text-align: left;\"> " + metrics.getAsyncAvg());
    sb.append("</td>");
    sb.append("</tr>");
}
sb.append("</table>");
sb.append("</body>");
sb.append("</html>");

System.out.println(sb.toString());

Как-то код выглядит довольно уродливо для меня тем, как HTML и CSS используются в StringBuilder. Я выбираю обзор кода, чтобы узнать, можем ли мы что-нибудь улучшить здесь. Есть ли лучший способ написать этот код?

11 голосов | спросил arsenal 19 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 19 Sep 2014 10:11:22 +0400 2014, 10:11:22

5 ответов


20
  1. Как насчет выделения style="" s в head

    sb.append("<style>" +
    "td { padding: 6px; border: 1px solid #ccc; text-align: left; }" + 
    "th { background: #333; color: white; font-weight: bold; padding: 6px; border: 1px solid #ccc; text-align: left;}" +
    "</style>");
    
  2. Вы должны написать вспомогательные методы, которые делают для вас «тяжелый подъем»:

    void appendTag(StringBuilder sb, String tag, String contents) {
        sb.append('<').append(tag).append('>');
        sb.append(contents);
        sb.append("</").append(tag).append('>');
    }
    void appendDataCell(StringBuilder sb, String contents) {
        appendTag(sb, "td", contents);
    }
    void appendHeaderCell(StringBuilder sb, String contents) {
        appendTag(sb, "th", contents);
    }
    

Обратите внимание, что если вы используете StringBuilder, вы не должны конкатенировать строки с помощью +. Вы хотите избавиться от конкатенации строк, а не делать это.


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

Предлагаем усы :

Если вы используете усы, вы можете написать такой шаблон:

<html>
  <head>
    <title>Table</title>
    <style>...</style>
  </head>
  <body>
    <table>
     <tr><th>....</th></tr>
    {{#metrics}}
      <tr>
        <td>{{getName}}</td>
        ...
      </tr>
    {{/metrics}}
  </body>
</html>

, а затем визуализируйте его, например,

public static void main(String[] args) throws IOException {
    HashMap<String, Object> scopes = new HashMap<String, Object>();
    scopes.put("metrics", dataMetricsList);

    Writer writer = new OutputStreamWriter(System.out);
    MustacheFactory mf = new DefaultMustacheFactory();
    Mustache mustache = mf.compile(new StringReader(getTemplateCodeFromAbove()), "example");
    mustache.execute(writer, scopes);
    writer.flush();
}

Это зависит от вашего варианта использования, конечно. Если все, что вам когда-либо понадобится, - это сделать одну таблицу, вы в порядке с StringBuilder. Но если вы повторите это, получите для него внешнюю библиотеку.

ответил thriqon 19 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 19 Sep 2014 10:23:06 +0400 2014, 10:23:06
4

Ответ thriqon's хороший, вы должны переместить код стиля где-нибудь, но заголовки таблиц не слишком далеко, вы должны переместить весь свой стиль в файл CSS, который будет выглядеть следующим образом:

th {
    background: #333; 
    color: white; 
    font-weight: bold; 
    padding: 6px; 
    border: 1px solid #ccc; 
    text-align: left;
}

td {
    padding: 6px; 
    border: 1px solid #ccc; 
    text-align: left;
}

Если у вас более одной таблицы, вы должны искать либо создание идентификатора для каждой таблицы, либо классов для таблиц, имеющих один и тот же стиль.

Сделав это, вы можете изменить тему страницы без необходимости проходить через код, просто измените таблицу стилей.


После того, как CSS (стилизация) будет разобрана, вы можете немного изменить свой код, очистив его, полностью удалив строки кода.

StringBuilder sb = new StringBuilder();
sb.append("<html>");
sb.append("<head>");
sb.append("</head>");
sb.append("<table>");
sb.append("<th> ClientName </th>");
sb.append("<th> SyncCount </th>");
sb.append("<th> SyncPercentile </th>");
sb.append("<th> SyncAvg </th>");
sb.append("<th> SyncMax </th>");
sb.append("<th> AsyncCount </th>");
sb.append("<th> AsyncPercentile </th>");
sb.append("<th> AsyncAvg </th>");

for (DataMetrics metrics : dataMetricsList) {
    sb.append("<tr>");
    sb.append("<td> " + metrics.getName() + " </td>");
    sb.append("<td> " + metrics.getSyncCall() + " </td>");
    sb.append("<td> " + metrics.getSyncPercent() + " </td>");
    sb.append("<td> " + metrics.getSyncAvg() + " </td>");
    sb.append("<td> " + metrics.getSyncMax() + " </td>");
    sb.append("<td> " + metrics.getAsyncCall() + " </td>");
    sb.append("<td> " + metrics.getAsyncPercent() + " </td>");
    sb.append("<td> " + metrics.getAsyncAvg() + " </td>");
    sb.append("</tr>");
}
sb.append("</table>");
sb.append("</body>");
sb.append("</html>");

System.out.println(sb.toString());

Вам действительно не нужно иметь строку только для концевых тегов (th и td), которые они могут использовать.

Это выглядит намного более чистым.

Я согласен с тем, что помощник тега был бы действительно хорош, и Шаблон Engine выглядит действительно приятным способом.

ответил Malachi 23 +04002014-10-23T18:37:15+04:00312014bEurope/MoscowThu, 23 Oct 2014 18:37:15 +0400 2014, 18:37:15
3

Я уже чувствовал необходимость в прошлом, и я в конечном итоге разработал java-библиотеку - HtmlFlow (развернуто в Центральном репозитории Maven ) - это простой API для написания HTML в свободном стиле. Проверьте это здесь: https://github.com/fmcarvalho/HtmlFlow .

Вы можете использовать HtmlFlow с привязкой данных или без нее, но здесь я представляю пример привязки свойств объекта Task в HTML-элементы. Рассмотрим класс Java Task с тремя свойствами: Title, Description и Priority и то мы можем создать HTML-документ для объекта Task следующим образом:

import htmlflow.HtmlView;

import model.Priority;
import model.Task;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;

public class App {

    private static HtmlView<Task> taskDetailsView(){
        HtmlView<Task> taskView = new HtmlView<>();
        taskView
                .head()
                .title("Task Details")
                .linkCss("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css");
        taskView
                .body().classAttr("container")
                .heading(1, "Task Details")
                .hr()
                .div()
                .text("Title: ").text(Task::getTitle)
                .br()
                .text("Description: ").text(Task::getDescription)
                .br()
                .text("Priority: ").text(Task::getPriority);
        return taskView;
    }

    public static void main(String [] args) throws IOException{
        HtmlView<Task> taskView = taskDetailsView();
        Task task =  new Task("Special dinner", "Have dinner with someone!", Priority.Normal);

        try(PrintStream out = new PrintStream(new FileOutputStream("Task.html"))){
            taskView.setPrintStream(out).write(task);
            Runtime.getRuntime().exec("explorer Task.html");
        }
    }
}
ответил Miguel Gamboa 1 FebruaryEurope/MoscowbMon, 01 Feb 2016 20:17:41 +0300000000pmMon, 01 Feb 2016 20:17:41 +030016 2016, 20:17:41
1

Я решил эту проблему, создав несколько тривиальных вспомогательных классов TableData, TableRow и TableCell. Затем я использую их для построения таблицы с объектами Java. Эти объекты имеют javax. xml.bind.annotation.XmlValue и такие аннотации в них, чтобы таблица легко могла быть сериализована в XML с использованием JAXB . Этот XML затем может быть далее обработан в любом виде HTML с помощью XSLT-преобразования , что на удивление просто сделать на Java.

У меня есть проект с открытым исходным кодом в Bitbucket, который использует этот метод. HtmlFormatter класс принимает TableData ​​a > и выводит строку HTML после описанного выше процесса (используя xmlToHtml.xsl XSL-файл).

ответил ZeroOne 19 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 19 Sep 2014 15:37:35 +0400 2014, 15:37:35
1

Вы можете условно генерировать html и css, используя структуру wffweb . Это позволяет писать сильно типизированный код в отношении объектов, а не подверженных ошибкам жестко закодированных строк. Это дает лучшую читаемость кода и возможность повторного использования. А также сгенерированный html будет в уменьшенной форме, так что это оптимизация на уровне веб-страницы , вы можете увидеть, что источник google.com также уменьшен.

Например, этот код:

public static void main(String[] args) {

    final int totalRows = 10;

    Html html = new Html(null) {
        Body body = new Body(this) {

            Table table = new Table(this) {

                {
                    Style column1Style = new Style(AlignContent.CENTER);
                    Style column2Style = new Style(AlignItems.CENTER,
                            new BackgroundColor(CssColorName.AQUA.getColorName()));

                    for (int i = 0; i < totalRows; i++) {

                        final String cellContent = "td1Id" + i;

                        new Tr(this) {

                            {
                                Td td1 = new Td(this, column1Style) {
                                    {
                                        new NoTag(this, cellContent);
                                    }
                                };

                                Td td2 = new Td(this, column2Style) {
                                    {
                                        new NoTag(this, cellContent);
                                    }
                                };

                                Td td3 = new Td(this) {
                                    {
                                        new NoTag(this, cellContent);
                                    }
                                };
                            }
                        };
                    }
                }

            };
        };
    };

    // html.setPrependDocType(true);
    System.out.println(html.toHtmlString());

}

напечатает ниже html (без форматирования)

<html>
   <body>
      <table>
         <tr>
            <td style="align-content:center;">td1Id0</td>
            <td style="align-items:center;background-color:Aqua;">td1Id0</td>
            <td>td1Id0</td>
         </tr>
         <tr>
            <td style="align-content:center;">td1Id1</td>
            <td style="align-items:center;background-color:Aqua;">td1Id1</td>
            <td>td1Id1</td>
         </tr>
         <tr>
            <td style="align-content:center;">td1Id2</td>
            <td style="align-items:center;background-color:Aqua;">td1Id2</td>
            <td>td1Id2</td>
         </tr>
         <tr>
            <td style="align-content:center;">td1Id3</td>
            <td style="align-items:center;background-color:Aqua;">td1Id3</td>
            <td>td1Id3</td>
         </tr>
         <tr>
            <td style="align-content:center;">td1Id4</td>
            <td style="align-items:center;background-color:Aqua;">td1Id4</td>
            <td>td1Id4</td>
         </tr>
         <tr>
            <td style="align-content:center;">td1Id5</td>
            <td style="align-items:center;background-color:Aqua;">td1Id5</td>
            <td>td1Id5</td>
         </tr>
         <tr>
            <td style="align-content:center;">td1Id6</td>
            <td style="align-items:center;background-color:Aqua;">td1Id6</td>
            <td>td1Id6</td>
         </tr>
         <tr>
            <td style="align-content:center;">td1Id7</td>
            <td style="align-items:center;background-color:Aqua;">td1Id7</td>
            <td>td1Id7</td>
         </tr>
         <tr>
            <td style="align-content:center;">td1Id8</td>
            <td style="align-items:center;background-color:Aqua;">td1Id8</td>
            <td>td1Id8</td>
         </tr>
         <tr>
            <td style="align-content:center;">td1Id9</td>
            <td style="align-items:center;background-color:Aqua;">td1Id9</td>
            <td>td1Id9</td>
         </tr>
      </table>
   </body>
</html>
ответил ANSGAR ANTON 14 J000000Thursday16 2016, 08:21:23

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132