Um guia para anotações relacionadas à Web do Java EE
1. Visão geral
As anotações do Java EE facilitam a vida dos desenvolvedores, permitindo que eles especifiquem como os componentes do aplicativo devem se comportar em um contêiner. Essas são alternativas modernas para descritores XML e, basicamente, tornam possível evitar o código padrão.
Neste artigo, vamos nos concentrar nas anotações introduzidas com Servlet API 3.1 no Java EE 7. Examinaremos seu objetivo e examinaremos seu uso.
2. Web Annotations
Servlet API 3.1 introduziu um novo conjunto de tipos de anotação que podem ser usados nas classesServlet:
-
@WebServlet
-
@WebInitParam
-
@WebFilter
-
@WebListener
-
@ServletSecurity
-
@HttpConstraint
-
@HttpMethodConstraint
-
@MultipartConfig
Vamos examiná-los em detalhes nas próximas seções.
3. @WebServlet
Simplificando, essa anotação nos permite declarar classes Java como servlets:
@WebServlet("/account")
public class AccountServlet extends javax.servlet.http.HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// ...
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// ...
}
}
3.1. Usando atributos de anotação de@WebServlet
@WebServlet tem um conjunto de atributos que nos permitem personalizar o servlet:
-
name
-
descrição
-
urlPatterns
-
initParams
Podemos usá-los como mostrado no exemplo abaixo:
@WebServlet(
name = "BankAccountServlet",
description = "Represents a Bank Account and it's transactions",
urlPatterns = {"/account", "/bankAccount" },
initParams = { @WebInitParam(name = "type", value = "savings")})
public class AccountServlet extends javax.servlet.http.HttpServlet {
String accountType = null;
public void init(ServletConfig config) throws ServletException {
// ...
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// ...
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// ...
}
}
O atributoname substitui o nome do servlet padrão, que é o nome de classe totalmente qualificado por padrão. Se quisermos fornecer uma descrição do que o servlet faz, podemos usar o atributodescription.
O atributourlPatterns é usado para especificar a (s) URL (s) na (s) qual (is) o servlet está disponível (vários valores podem ser fornecidos para este atributo conforme mostrado no exemplo de código).
4. @WebInitParam
Esta anotação é usada com o atributoinitParams da anotação@WebServlet e os parâmetros de inicialização do servlet.
Neste exemplo, definimos um parâmetro de inicialização do servlettype, para o valor de ‘economia’:
@WebServlet(
name = "BankAccountServlet",
description = "Represents a Bank Account and it's transactions",
urlPatterns = {"/account", "/bankAccount" },
initParams = { @WebInitParam(name = "type", value = "savings")})
public class AccountServlet extends javax.servlet.http.HttpServlet {
String accountType = null;
public void init(ServletConfig config) throws ServletException {
accountType = config.getInitParameter("type");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// ...
}
}
5. @WebFilter
Se quisermos alterar a solicitação e a resposta de um servlet sem tocar em sua lógica interna, podemos usar a anotaçãoWebFilter. Podemos associar filtros a um servlet ou a um grupo de servlets e conteúdo estático, especificando um padrão de URL.
No exemplo abaixo, estamos usando a anotação@WebFilter para redirecionar qualquer acesso não autorizado à página de login:
@WebFilter(
urlPatterns = "/account/*",
filterName = "LoggingFilter",
description = "Filter all account transaction URLs")
public class LogInFilter implements javax.servlet.Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(
ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
res.sendRedirect(req.getContextPath() + "/login.jsp");
chain.doFilter(request, response);
}
public void destroy() {
}
}
6. @WebListener
Se desejarmos conhecimento ou controle sobre como e quando um servlet e seus pedidos são inicializados ou alterados, podemos usar a anotação@WebListener.
Para escrever um ouvinte da web, precisamos estender uma ou mais das seguintes interfaces:
-
ServletContextListener – for notificações sobre o ciclo de vida deServletContext
-
ServletContextAttributeListener – for notificações quando um atributoServletContext é alterado
-
ServletRequestListener – for notificações sempre que uma solicitação de um recurso é feita
-
ServletRequestAttributeListener – for notificações quando um atributo é adicionado, removido ou alterado em umServletRequest
-
HttpSessionListener – for notificações quando uma nova sessão é criada e destruída
-
HttpSessionAttributeListener – for notificações quando um novo atributo está sendo adicionado ou removido de uma sessão
Abaixo está um exemplo de como podemos usar umServletContextListener para configurar um aplicativo da web:
@WebListener
public class BankAppServletContextListener
implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
sce.getServletContext().setAttribute("ATTR_DEFAULT_LANGUAGE", "english");
}
public void contextDestroyed(ServletContextEvent sce) {
// ...
}
}
7. @ServletSecurity
Quando queremos especificar o modelo de segurança para nosso servlet, incluindo funções, controle de acesso e requisitos de autenticação, usamos a anotação@ServletSecurity.
Neste exemplo, iremos restringir o acesso ao nossoAccountServlet usando a anotação@ServletSecurity:
@WebServlet(
name = "BankAccountServlet",
description = "Represents a Bank Account and it's transactions",
urlPatterns = {"/account", "/bankAccount" },
initParams = { @WebInitParam(name = "type", value = "savings")})
@ServletSecurity(
value = @HttpConstraint(rolesAllowed = {"Member"}),
httpMethodConstraints = {@HttpMethodConstraint(value = "POST", rolesAllowed = {"Admin"})})
public class AccountServlet extends javax.servlet.http.HttpServlet {
String accountType = null;
public void init(ServletConfig config) throws ServletException {
// ...
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// ...
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
double accountBalance = 1000d;
String paramDepositAmt = request.getParameter("dep");
double depositAmt = Double.parseDouble(paramDepositAmt);
accountBalance = accountBalance + depositAmt;
PrintWriter writer = response.getWriter();
writer.println(" Balance of " + accountType + " account is: " + accountBalance
+ "");
writer.flush();
}
}
Nesse caso, ao invocarAccountServlet,, o navegador exibe uma tela de login para o usuário inserir um nome de usuário e uma senha válidos.
Podemos usar as anotações@HttpConstrainte@HttpMethodConstraint para especificar valores para os atributosvalueehttpMethodConstraints, da anotação@ServletSecurity.
A anotação@HttpConstraint se aplica a todos os métodos HTTP. Em outras palavras, especifica a restrição de segurança padrão.
@HttpConstraint tem três atributos:
-
valor
-
rolesAllowed
-
transportGuarantee
Destes atributos, o atributo mais comumente usado érolesAllowed. No fragmento de código de exemplo acima, os usuários que pertencem à funçãoMember têm permissão para invocar todos os métodos HTTP.
A anotação@HttpMethodConstraint nos permite especificar as restrições de segurança de um método HTTP particular.
@HttpMethodConstraint tem os seguintes atributos:
-
valor
-
emptyRoleSemantic
-
rolesAllowed
-
transportGuarantee
No exemplo de trecho de código acima, ele mostra como o métododoPost é restrito apenas para usuários que pertencem à funçãoAdmin, permitindo que a função de depósito seja feita apenas por um usuárioAdmin.
8. @MultipartConfig
Esta anotação é usada quando precisamos anotar um servlet para lidar com solicitaçõesmultipart/form-data (normalmente usado para um servlet de upload de arquivo).
Isso irá expor os métodosgetParts()egetPart(name) deHttpServletRequest podem ser usados para acessar todas as partes, bem como uma parte individual.
O arquivo carregado pode ser gravado no disco chamandowrite(fileName) do objeto Parte.
Agora veremos um exemplo de servletUploadCustomerDocumentsServlet que demonstra seu uso:
@WebServlet(urlPatterns = { "/uploadCustDocs" })
@MultipartConfig(
fileSizeThreshold = 1024 * 1024 * 20,
maxFileSize = 1024 * 1024 * 20,
maxRequestSize = 1024 * 1024 * 25,
location = "./custDocs")
public class UploadCustomerDocumentsServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
for (Part part : request.getParts()) {
part.write("myFile");
}
}
}
@MultipartConfig tem quatro atributos:
-
fileSizeThreshold - Este é o limite de tamanho ao salvar o arquivo carregado temporariamente. Se o tamanho do arquivo enviado for maior que esse limite, ele será armazenado no disco. Caso contrário, o arquivo é armazenado na memória (tamanho em bytes)
-
maxFileSize - Este é o tamanho máximo do arquivo enviado (tamanho em bytes)
-
maxRequestSize - este é o maior tamanho da solicitação, incluindo arquivos carregados e outros dados de formulário (tamanho em bytes)
-
location - é o diretório onde os arquivos carregados são armazenados
9. Conclusão
Neste artigo, vimos algumas anotações do Java EE introduzidas com a API do Servlet 3.1 e seus propósitos e uso.
O código-fonte relacionado a este artigo pode ser encontradoover on GitHub.