javax.*).Se usar Tomcat 10/10.1, troquejavax.*porjakarta.*(nota no final).
Produto) e DAO (acesso a dados).war (se preferir, use o zip pronto acima).pom.xml (principais trechos):<packaging>war</packaging>
<dependencies>
<!-- Tomcat 9 / javax.* -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
src/main/java/com/exemplo/mvc/
model/Produto.java
dao/ProdutoDAO.java
dao/ProdutoDAOEmMemoria.java
controller/ProdutoController.java
src/main/webapp/
index.jsp
WEB-INF/web.xml
WEB-INF/views/
lista.jsp
form.jsp
Produto.java (id, nome, preco; getters/setters).ProdutoDAO (listar, buscarPorId, salvar, atualizar, excluir).ProdutoDAOEmMemoria (usa Map<Long, Produto>).Mantém o foco no padrão MVC antes de banco real.
@WebServlet("/produtos").doGet: trata action=list|form|edit|delete.doPost: lê campos, cria/atualiza e faz redirect para list.lista.jsp: tabela com produtos + links de Novo, Editar, Excluir (usa JSTL: <c:forEach>).form.jsp: formulário com nome e preco.RequestDispatcher para /WEB-INF/views/....mvn clean package
# gera target/mvc-aula8.war
webapps).http://localhost:8080/mvc-aula8/produtos?action=list.Produto (id, nome, preco).list, form, edit, delete e POST para salvar/atualizar.lista.jsp (tabela) e form.jsp (formulário).ProdutoController.java(Servlet)
@WebServlet(name = "ProdutoController", urlPatterns = {"/produtos"})
public class ProdutoController extends HttpServlet {
private ProdutoDAO dao = new ProdutoDAOEmMemoria();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String action = req.getParameter("action");
if (action == null) action = "list";
switch (action) {
case "form":
req.setAttribute("produto", new Produto());
req.getRequestDispatcher("/WEB-INF/views/form.jsp").forward(req, resp);
break;
case "edit":
try {
Long id = Long.valueOf(req.getParameter("id"));
Produto p = dao.buscarPorId(id).orElseThrow();
req.setAttribute("produto", p);
req.getRequestDispatcher("/WEB-INF/views/form.jsp").forward(req, resp);
} catch (Exception e) {
resp.sendRedirect(req.getContextPath() + "/produtos?action=list");
}
break;
case "delete":
try {
Long idDel = Long.valueOf(req.getParameter("id"));
dao.excluirPorId(idDel);
} catch (Exception ignored) {}
resp.sendRedirect(req.getContextPath() + "/produtos?action=list");
break;
case "list":
default:
req.setAttribute("produtos", dao.listarTodos());
req.getRequestDispatcher("/WEB-INF/views/lista.jsp").forward(req, resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
String idStr = req.getParameter("id");
String nome = req.getParameter("nome");
String precoStr = req.getParameter("preco");
try {
Double preco = Double.valueOf(precoStr);
if (idStr == null || idStr.isBlank()) {
dao.salvar(new Produto(null, nome, preco));
} else {
Long id = Long.valueOf(idStr);
Produto p = dao.buscarPorId(id).orElseThrow();
p.setNome(nome); p.setPreco(preco);
dao.atualizar(p);
}
resp.sendRedirect(req.getContextPath() + "/produtos?action=list");
} catch (Exception e) {
req.setAttribute("erro", e.getMessage());
req.getRequestDispatcher("/WEB-INF/views/form.jsp").forward(req, resp);
}
}
}
lista.jsp<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<h2>Produtos</h2>
<p><a href="<c:url value='/produtos?action=form'/>">Novo Produto</a></p>
<c:choose>
<c:when test="${empty produtos}">
<p>Nenhum produto cadastrado.</p>
</c:when>
<c:otherwise>
<table>
<thead><tr><th>ID</th><th>Nome</th><th>Preço</th><th>Ações</th></tr></thead>
<tbody>
<c:forEach items="${produtos}" var="p">
<tr>
<td>${p.id}</td><td>${p.nome}</td><td>R$ ${p.preco}</td>
<td>
<a href="<c:url value='/produtos?action=edit&id=${p.id}'/>">Editar</a>
<a href="<c:url value='/produtos?action=delete&id=${p.id}'/>"
onclick="return confirm('Excluir este produto?');">Excluir</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</c:otherwise>
</c:choose>
form.jsp<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<h2>${empty produto.id ? 'Novo' : 'Editar'} Produto</h2>
<form method="post" action="<c:url value='/produtos'/>">
<input type="hidden" name="id" value="${produto.id}"/>
<label>Nome: <input type="text" name="nome" value="${produto.nome}" required/></label>
<label>Preço: <input type="number" step="0.01" name="preco" value="${produto.preco}" required/></label>
<button type="submit">Salvar</button>
<a href="<c:url value='/produtos?action=list'/>">Cancelar</a>
</form>
pom.xml, troque:javax.servlet:javax.servlet-api:4.0.1 → jakarta.servlet:jakarta.servlet-api:6.0.0 (scope provided).javax.servlet.* → jakarta.servlet.*.jakarta.tags.core nas JSPs.

public class Task {
private Long id;
private String titulo;
private boolean concluida;
// Construtor sem argumentos
public Task() {}
// Getters e Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
// Demais getters e setters...
}
// JavaBean
public class Task {
private Long id;
private String titulo;
private boolean concluida;
// Getters e setters...
}
// DAO
public class TaskDao {
public void save(Task task) {
// Código para persistir no banco
}
public List findAll() {
// Retorna todas as tarefas
}
public void delete(Long id) {
// Remove uma tarefa
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>Lista de Tarefas</title>
</head>
<body>
<h1>Minhas Tarefas</h1>
<ul>
<c:forEach items="${tarefas}" var="tarefa">
<li>
${tarefa.titulo}
<c:if test="${tarefa.concluida}">
(Concluída)
</c:if>
</li>
</c:forEach>
</ul>
</body>
</html>

@WebServlet("/tarefas")
public class TarefaController extends HttpServlet {
private TaskDao taskDao = new TaskDao();
@Override
protected void doGet(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException {
// Obtém dados do Model
List tarefas = taskDao.findAll();
// Disponibiliza para a View
req.setAttribute("tarefas", tarefas);
// Encaminha para a View
req.getRequestDispatcher("/WEB-INF/views/tarefas.jsp")
.forward(req, resp);
}
}

public class Produto implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String nome;
private String descricao;
private BigDecimal preco;
private Integer estoque;
// Construtor padrão
public Produto() {
}
// Construtor completo
public Produto(Long id, String nome,
String descricao,
BigDecimal preco,
Integer estoque) {
this.id = id;
this.nome = nome;
this.descricao = descricao;
this.preco = preco;
this.estoque = estoque;
}
// Getters e setters...
}
@WebServlet("/produtos")
public class ProdutoController extends HttpServlet {
private ProdutoDAO dao = new ProdutoDAO();
@Override
protected void doGet(
HttpServletRequest req,
HttpServletResponse resp
) throws ServletException, IOException {
String acao = req.getParameter("acao");
if ("novo".equals(acao)) {
// Exibir formulário
req.getRequestDispatcher(
"/WEB-INF/views/produto-form.jsp"
).forward(req, resp);
} else {
// Listar produtos
List produtos = dao.listarTodos();
req.setAttribute("produtos", produtos);
req.getRequestDispatcher(
"/WEB-INF/views/produtos.jsp"
).forward(req, resp);
}
}
@Override
protected void doPost(
HttpServletRequest req,
HttpServletResponse resp
) throws ServletException, IOException {
// Processar formulário
// ...
}
}

Logger logger = Logger.getLogger(ProdutoController.class.getName());
logger.info("Requisição recebida: " + acao);
@Test
public void testProdutoPrecoNegativo() {
Produto p = new Produto();
assertThrows(IllegalArgumentException.class,
() -> p.setPreco(new BigDecimal(-10)));
}
@Before
public void setUp() {
// Configura banco de teste e insere dados
}
public class ProdutoDAO {
private Connection getConnection() throws SQLException {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
return DriverManager.getConnection(
"jdbc:mysql://localhost:3306/loja",
"usuario", "senha");
} catch (ClassNotFoundException e) {
throw new SQLException("Driver não encontrado", e);
}
}
public void inserir(Produto p) throws SQLException {
String sql = "INSERT INTO produtos (nome, descricao, preco, estoque) VALUES (?, ?, ?, ?)";
try (Connection conn = getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, p.getNome());
stmt.setString(2, p.getDescricao());
stmt.setBigDecimal(3, p.getPreco());
stmt.setInt(4, p.getEstoque());
stmt.executeUpdate();
}
}
}
