Как передать текущий элемент методу Java, нажав гиперссылку или кнопку на странице JSP?

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

Как вызвать функцию JSP на странице, когда пользователь нажимает на каждую из этих гиперссылок или кнопку удаления, чтобы я мог удалить эту запись строки из базы данных? В чем именно тег <a> или <button> должен вызывать функцию JSP?

Обратите внимание, что мне нужно вызвать JSP-функцию, а не функцию JavaScript.

Ответ 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 для стилизации кнопки, чтобы она выглядела как ссылка. Редактировать ссылки, которые просто предварительно загружают элемент, чтобы заполнить форму редактирования, можно смело.

  2. Вводить бизнес-логику (функции, как вы ее называете) в JSP с помощью скриптлетов (эти вещи <% %> %% <% %>) не рекомендуется. Вы должны использовать сервлет для контроля, предварительной обработки и пост-обработки 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>

Обратите внимание на разницу в подходе: ссылка редактирования запускает запрос GET с уникальным идентификатором элемента в качестве параметра запроса. Однако кнопка удаления запускает запрос POST, в результате чего уникальный идентификатор элемента передается как значение самой кнопки.

Сохраните его как 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 "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.

Смотрите также: