как отправить данные через ссылку в пределах одного и того же jsp без формы submit [duplicate]

Я создал свою собственную функцию для извлечения правил из деревьев решений, созданных sklearn:

import pandas as pd
import numpy as np
from sklearn.tree import DecisionTreeClassifier

# dummy data:
df = pd.DataFrame({'col1':[0,1,2,3],'col2':[3,4,5,6],'dv':[0,1,0,1]})

# create decision tree
dt = DecisionTreeClassifier(max_depth=5, min_samples_leaf=1)
dt.fit(df.ix[:,:2], df.dv)

Эта функция сначала начинается с узлов (идентифицированных -1 в дочерних массивах), а затем рекурсивно находит родителей. Я называю это «родословной» узла. Попутно я получаю значения, которые мне нужно создать, если / then / else логика SAS:

def get_lineage(tree, feature_names):
     left      = tree.tree_.children_left
     right     = tree.tree_.children_right
     threshold = tree.tree_.threshold
     features  = [feature_names[i] for i in tree.tree_.feature]

     # get ids of child nodes
     idx = np.argwhere(left == -1)[:,0]     

     def recurse(left, right, child, lineage=None):          
          if lineage is None:
               lineage = [child]
          if child in left:
               parent = np.where(left == child)[0].item()
               split = 'l'
          else:
               parent = np.where(right == child)[0].item()
               split = 'r'

          lineage.append((parent, split, threshold[parent], features[parent]))

          if parent == 0:
               lineage.reverse()
               return lineage
          else:
               return recurse(left, right, parent, lineage)

     for child in idx:
          for node in recurse(left, right, child):
               print node

Наборы кортежей ниже содержат все, что мне нужно для создания SAS, если / then / else. Мне не нравится использование блоков do в SAS, поэтому я создаю логику, описывающую весь путь узла. Единственное целое после кортежей - это идентификатор конечного узла в пути. Все предыдущие кортежи объединяются для создания этого узла.

In [1]: get_lineage(dt, df.columns)
(0, 'l', 0.5, 'col1')
1
(0, 'r', 0.5, 'col1')
(2, 'l', 4.5, 'col2')
3
(0, 'r', 0.5, 'col1')
(2, 'r', 4.5, 'col2')
(4, 'l', 2.5, 'col1')
5
(0, 'r', 0.5, 'col1')
(2, 'r', 4.5, 'col2')
(4, 'r', 2.5, 'col1')
6

GraphViz output of example tree [/g0]

3
задан BalusC 30 November 2015 в 10:31
поделиться

1 ответ

Простейший способ: просто укажите ссылку на страницу JSP и передайте идентификатор строки в качестве параметра:

<a href="delete.jsp?id=1">delete</a>

И в delete.jsp (я оставляю очевидную проверку параметров запроса / валидация в сторону) :

<% dao.delete(Long.valueOf(request.getParameter("id"))); %>

Это, однако, довольно плохая практика (это все еще было преуменьшением) и по двум причинам:

  1. Запросы HTTP, которые изменяют данные на стороне сервера, не должны выполняться с помощью GET , а через POST . Ссылки - это неявное GET. Представьте, что произойдет, если веб-искатель, такой как googlebot, попытается выполнить все ссылки удаления. Вы должны использовать <form method="post"> и <button type="submit"> для действия удаления. Однако вы можете использовать CSS, чтобы стиль кнопки выглядел как ссылка. Редактировать ссылки, которые предварительно загружают элемент, чтобы предварительно заполнить форму редактирования, могут безопасно быть GET.
  2. Помещение бизнес-логики (функции , как вы ее называете) в JSP с использованием scriptlets (те <% %> вещи) обескуражены. Вы должны использовать сервлет сервлета для контроля, препроцесса и постпроцессов HTTP-запросов.

Поскольку вы не сообщили ни слова о сервлете в своем вопросе, я подозреваю, что вы уже используете сценарии для загрузки данных из БД и отображения их в таблице. Это также должно быть сделано сервлетом.

Вот пример основного примера, как это сделать. Я не знаю, что представляют данные таблицы, поэтому давайте возьмем Product в качестве примера.

public class Product {
    private Long id;
    private String name;
    private String description;
    private BigDecimal price;
    // Add/generate public getters and setters.
}

И затем JSP-файл, который использует JSTL (просто снимите jstl-1.2.jar в /WEB-INF/lib, чтобы установить его), чтобы отобразить продукты в таблице с ссылкой на редактирование и кнопкой удаления в каждой строке:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
...
<form action="products" method="post">
    <table>
        <c:forEach items="${products}" var="product">
            <tr>
                <td><c:out value="${fn:escapeXml(product.name)}" /></td>
                <td><c:out value="${product.description}" /></td>
                <td><fmt:formatNumber value="${product.price}" type="currency" currencyCode="USD" /></td>
                <td><a href="${pageContext.request.contextPath}/product?edit=${product.id}">edit</a></td>
                <td><button type="submit" name="delete" value="${product.id}">delete</button></td>
            </tr>
        </c:forEach>
    </table>
    <a href="${pageContext.request.contextPath}/product">add</a>
</form>
]

Назовите его products.jsp и поместите его в папку /WEB-INF, чтобы он не был напрямую доступен по URL-адресу (так, чтобы конечный пользователь был вынужден вызвать сервлет для этого).

Вот как сервлет примерно похож на (валидация опущена для краткости):

@WebServlet("/products")
public class ProductsServlet extends HttpServlet {

    private ProductDAO productDAO; // EJB, plain DAO, etc.

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Product> products = productDAO.list();
        request.setAttribute("products", products); // Will be available as ${products} in JSP.
        request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String delete = request.getParameter("delete");

        if (delete != null) { // Is the delete button pressed?
            productDAO.delete(Long.valueOf(delete));
        }

        response.sendRedirect(request.getContextPath() + "/products"); // Refresh page with table.
    }

}

Вот как может выглядеть форма добавления / редактирования в /WEB-INF/product.jsp:

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
...
<form action="product" method="post">
    <label for="name">Name</label>
    <input id="name" name="name" value="${fn:escapeXml(product.name)}" />
    <br/>
    <label for="description">Description</label>
    <input id="description" name="description" value="${fn:escapeXml(product.description)}" />
    <br/>
    <label for="price">Price</label>
    <input id="price" name="price" value="${fn:escapeXml(product.price)}" />
    <br/>
    <button type="submit" name="save" value="${product.id}">save</button>
</form>

fn:escapeXml() как раз там, чтобы предотвратить атаки XSS при повторном просмотре данных редактирования, он делает то же самое, что и <c:out>, только лучше подходит для использования в атрибутах.

Вот как product сервлет может выглядеть следующим образом (опять-таки, для краткости для сокращения):

@WebServlet("/product")
public class ProductServlet extends HttpServlet {

    private ProductDAO productDAO; // EJB, plain DAO, etc.

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String edit = request.getParameter("edit");

        if (edit != null) { // Is the edit link clicked?
            Product product = productDAO.find(Long.valueOf(delete));
            request.setAttribute("product", product); // Will be available as ${product} in JSP.
        }

        request.getRequestDispatcher("/WEB-INF/product.jsp").forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String save = request.getParameter("save");

        if (save != null) { // Is the save button pressed? (note: if empty then no product ID was supplied, which means that it's "add product".
            Product product = (save.isEmpty()) ? new Product() : productDAO.find(Long.valueOf(save));
            product.setName(request.getParameter("name"));
            product.setDescription(request.getParameter("description"));
            product.setPrice(new BigDecimal(request.getParameter("price")));
            productDAO.save(product);
        }

        response.sendRedirect(request.getContextPath() + "/products"); // Go to page with table.
    }

}

Разверните и запустите его. Вы можете открыть таблицу http://example.com/contextname/products .

См. Также:

7
ответ дан Community 24 August 2018 в 06:33
поделиться
Другие вопросы по тегам:

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