web-dev-qa-db-fra.com

Afficher le jeu de résultats JDBC en HTML dans la page JSP à l'aide du modèle MVC et DAO

J'implémente MVC en utilisant JSP et JDBC. J'ai importé un fichier de classe de base de données dans mon fichier JSP et je voudrais afficher les données d'une table DB. Je ne sais pas comment renvoyer le ResultSet de la classe Java à la page JSP et l'intégrer au format HTML.

Comment puis-je atteindre cet objectif?

51
Ashwani Sharma

Dans une approche MVC bien conçue, le fichier JSP ne doit contenir aucune ligne de code Java et la classe de servlet ne doit contenir aucune ligne de code JDBC.

En supposant que vous souhaitez afficher une liste de produits dans une boutique en ligne, le code suivant doit être créé.

  • Une classe Product représentant une entité réelle d'un produit, elle devrait être juste Javabean .

    public class Product {
    
        private Long id; 
        private String name;
        private String description;
        private BigDecimal price;
    
        // Add/generate getters/setters/c'tors/equals/hashcode boilerplate.
    }
    
  • Une classe DAO qui fait tout le méchant travail JDBC et renvoie un joli List<Product>.

    public class ProductDAO {
    
        private DataSource dataSource;
    
        public ProductDAO(DataSource dataSource) {
            this.dataSource = dataSource;
        }
    
        public List<Product> list() throws SQLException {
            List<Product> products = new ArrayList<Product>();
    
            try (
                Connection connection = dataSource.getConnection();
                PreparedStatement statement = connection.prepareStatement("SELECT id, name, description, price FROM product");
                ResultSet resultSet = statement.executeQuery();
            ) {
                while (resultSet.next()) {
                    Product product = new Product();
                    product.setId(resultSet.getLong("id"));
                    product.setName(resultSet.getString("name"));
                    product.setDescription(resultSet.getString("description"));
                    product.setPrice(resultSet.getBigDecimal("price"));
                    products.add(product);
                }
            }
    
            return products;
        }
    
    }
    
  • Une classe servlet qui obtient la liste et la place dans la portée de la requête.

    @WebServlet("/products")
    public class ProductsServlet extends HttpServlet {
    
        @Resource(name="jdbc/YourDB") // For Tomcat, define as <Resource> in context.xml and declare as <resource-ref> in web.xml.
        private DataSource dataSource;
        private ProductDAO productDAO;
    
        @Override
        public void init() {
            productDAO = new ProductDAO(dataSource);
        }
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            try {
                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);
            } catch (SQLException e) {
                throw new ServletException("Cannot obtain products from DB", e);
            }
        }
    
    }
    
  • Enfin un fichier JSP dans /WEB-INF/products.jsp Qui utilise JSTL <c:forEach> Pour itérer sur List<Product> Qui est disponible dans EL par ${products}, Et utilise JSTL <c:out> Pour échapper aux propriétés des chaînes afin d'éviter les trous XSS lorsqu'il s'agit d'une entrée contrôlée par l'utilisateur.

    <%@ taglib uri="http://Java.Sun.com/jsp/jstl/core" prefix="c" %>
    <%@ taglib uri="http://Java.Sun.com/jsp/jstl/format" prefix="fmt" %>
    ...
    <table>
        <c:forEach items="${products}" var="product">
            <tr>
                <td>${product.id}</td>
                <td><c:out value="${product.name}" /></td>
                <td><c:out value="${product.description}" /></td>
                <td><fmt:formatNumber value="${product.price}" type="currency" currencyCode="USD" /></td>
            </tr>
        </c:forEach>
    </table>
    

Pour le faire fonctionner, il suffit d'appeler le servlet par son URL. À condition que le servlet soit annoté @WebServlet("/products") ou mappé dans web.xml Avec <url-pattern>/products</url-pattern>, Vous pouvez l'appeler par http://example.com/contextname/products

Voir également:

118
BalusC

MVC, dans un contexte d'application web, ne consiste pas à utiliser une classe à partir d'une JSP. Il consiste à utiliser le modèle suivant:

  1. le navigateur envoie une demande à un serveur Web
  2. le serveur web est configuré pour que la requête soit traitée par un servlet ou un filtre (le contrôleur: Java, pas code JSP)
  3. Le servlet/filtre envoie généralement la demande à une classe spécifique (appelée Action, la partie spécifique du contrôleur), en fonction de la configuration/des annotations
  4. L'action exécute la logique métier (c'est-à-dire récupérer les données de la base de données dans votre exemple: le modèle)
  5. L'action transmet la demande à un JSP. Le rôle du JSP est uniquement de générer du code HTML (c'est-à-dire d'afficher vos données: la vue)

Étant donné que le JSP utilise généralement des balises JSP (le JSTL, par exemple) et le langage d'expression JSP, et puisque les balises JSP et l'EL sont conçues pour obtenir des informations à partir de JavaBeans, vous feriez mieux d'avoir vos données disponibles sous la forme de JavaBeans ou de collections de JavaBeans.

Le rôle du contrôleur (la classe d'action) est donc de récupérer les données, de créer des instances JavaBean contenant les données, dans un format approprié pour le JSP, de les mettre dans des attributs de requête, puis de les envoyer au JSP. Le JSP va ensuite parcourir les instances JavaBean et afficher ce qu'elles contiennent.

Vous ne devez pas implémenter le framework MVC vous-même. Utilisez ceux existants (Stripes, Struts, etc.)

11
JB Nizet

Je ne sais pas comment retourner le ResultSet du fichier de classe à la page JSP

Eh bien non.

Le point de MVC est de séparer votre modèle (le M DB info dans ce cas) de votre vue ( V a jsp, dans ce cas) de telle manière que vous pouvez changer la vue sans freiner l'application.

Pour ce faire, vous pouvez utiliser un objet intermédiaire pour représenter vos données (généralement appelé DTO - après Data Transfer Object -, je ne sais pas comment ils l'appellent de nos jours), et un autre objet pour le récupérer (généralement un DAO).

Donc, fondamentalement, vous avez votre fichier JSP, obtenez les paramètres de demande, puis appelez une méthode à partir du DAO. Le dao, en interne, a les moyens de se connecter à la base de données et de récupérer les données et construit une collection de DTO qui sont retournés au JSP pour le rendu.

Quelque chose comme ce code extrêmement simplifié (et non sécurisé):

Employee.Java

class Employee {
   String name;
   int emplid;
}

EmployeeDAO.Java

class EmployeeDAO { 
   ... method to connect 
   etc. 
   List<Employee> getAllNamed( String name ) { 
       String query = "SELECT name, emplid FROM employee where name like ?";
       ResultSet rs = preparedStatement.executeQuery etc etc.
       List<Employee> results = ....
       while( rs.hasNext() ) { 
          results.add( new Employee( rs.getString("name"), rs.getInt("emplid")));
       }
       // close resources etc 
       return results;
    }
}

employee.jsp

<%
   request.setAttribute("employees", dao.getAllNamed( request.getParameter("name") );
%>
<table>
<c:forEach items="${employees}" var="employee">
<tr><td>${employee.emplid}</td><td>${employee.name}</td></tr>
</c:forEach>
</table>

J'espère que cela vous donnera une meilleure idée.

5
OscarRyz