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.