Руководство по веб-аннотациям Java EE

1. обзор

Аннотации Java EE упрощают жизнь разработчиков, позволяя им указать, как компоненты приложения должны вести себя в контейнере. Это современные альтернативы для XML-дескрипторов и, в основном, позволяют избежать шаблонного кода.

В этой статье мы сосредоточимся на аннотациях, представленных в Servlet API 3.1 в Java EE 7. Мы рассмотрим их назначение и посмотрим на их использование.

2. Веб-аннотации

Servlet API 3.1 представил новый набор типов аннотаций, которые можно использовать в классахServlet:

  • @WebServlet

  • @WebInitParam

  • @WebFilter

  • @WebListener

  • @ServletSecurity

  • @HttpConstraint

  • @HttpMethodConstraint

  • @MultipartConfig

Мы рассмотрим их подробно в следующих разделах.

3. @WebServletс

Проще говоря, эта аннотация позволяет нам объявлять классы Java как сервлеты:

@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. Использование атрибутов аннотации@WebServlet

@WebServlet имеет набор атрибутов, которые позволяют нам настраивать сервлет:

  • name

  • описание

  • urlPatterns

  • initParams

Мы можем использовать их, как показано в примере ниже:

@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 {
        // ...
    }
}

Атрибутname заменяет имя сервлета по умолчанию, которое по умолчанию является полным именем класса. Если мы хотим предоставить описание того, что делает сервлет, мы можем использовать атрибутdescription.

АтрибутurlPatterns используется для указания URL-адресов, по которым доступен сервлет (этому атрибуту может быть предоставлено несколько значений, как показано в примере кода).

4. @WebInitParamс

Эта аннотация используется с атрибутомinitParams аннотации@WebServlet и параметрами инициализации сервлета.

В этом примере мы устанавливаем параметр инициализации сервлетаtype на значение «экономии»:

@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с

Если мы хотим изменить запрос и ответ сервлета, не затрагивая его внутреннюю логику, мы можем использовать аннотациюWebFilter. Мы можем связать фильтры с сервлетом или с группой сервлетов и статическим содержимым, указав шаблон URL.

В приведенном ниже примере мы используем аннотацию@WebFilter для перенаправления любого неавторизованного доступа к странице входа:

@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с

Если нам нужно знать или контролировать, как и когда сервлет и его запросы инициализируются или изменяются, мы можем использовать аннотацию@WebListener.

Чтобы написать веб-прослушиватель, нам нужно расширить один или несколько из следующих интерфейсов:

  • УведомленияServletContextListener – for о жизненном циклеServletContext

  • УведомленияServletContextAttributeListener – for при изменении атрибутаServletContext

  • УведомленияServletRequestListener – for при каждом запросе ресурса

  • УведомленияServletRequestAttributeListener – for при добавлении, удалении или изменении атрибута вServletRequest

  • УведомленияHttpSessionListener – for при создании и уничтожении нового сеанса

  • УведомленияHttpSessionAttributeListener – for, когда новый атрибут добавляется или удаляется из сеанса

Ниже приведен пример того, как мы можем использоватьServletContextListener для настройки веб-приложения:

@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с

Когда мы хотим указать модель безопасности для нашего сервлета, включая роли, требования к управлению доступом и аутентификации, мы используем аннотацию@ServletSecurity.

В этом примере мы ограничим доступ к нашемуAccountServlet с помощью аннотации@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();
    }
}

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

Мы можем использовать аннотации@HttpConstraint и@HttpMethodConstraint, чтобы указать значения для атрибутовvalue иhttpMethodConstraints, аннотации@ServletSecurity.

Аннотация@HttpConstraint применяется ко всем методам HTTP. Другими словами, он определяет ограничение безопасности по умолчанию.

@HttpConstraint имеет три атрибута:

  • значение

  • роли

  • транспортГарантия

Из этих атрибутов наиболее часто используется атрибутrolesAllowed. В приведенном выше примере фрагмента кода пользователям, принадлежащим к ролиMember, разрешено вызывать все методы HTTP.

Аннотация@HttpMethodConstraint позволяет нам указать ограничения безопасности для конкретного метода HTTP.

@HttpMethodConstraint имеет следующие атрибуты:

  • значение

  • emptyRoleSemantic

  • роли

  • транспортГарантия

В приведенном выше примере фрагмента кода показано, как методdoPost ограничен только для пользователей, принадлежащих к ролиAdmin, позволяя выполнять функцию депозита только пользователюAdmin.

8. @MultipartConfigс

Эта аннотация используется, когда нам нужно аннотировать сервлет для обработки запросовmultipart/form-data (обычно используется для сервлета загрузки файла).

Это откроет методыgetParts() иgetPart(name) изHttpServletRequest, которые можно использовать для доступа ко всем частям, а также к отдельной части.

Загруженный файл можно записать на диск, вызвавwrite(fileName) объекта Part.

Теперь мы рассмотрим пример сервлетаUploadCustomerDocumentsServlet, демонстрирующий его использование:

@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 имеет четыре атрибута:

  • fileSizeThreshold - это порог размера при временном сохранении загруженного файла. Если размер загруженного файла превышает этот порог, он будет сохранен на диске. В противном случае файл сохраняется в памяти (размер в байтах)

  • maxFileSize - это максимальный размер загружаемого файла (размер в байтах)

  • maxRequestSize - это наибольший размер запроса, включая как загруженные файлы, так и другие данные формы (размер в байтах)

  • location - это каталог, в котором хранятся загруженные файлы

9. Заключение

В этой статье мы рассмотрели некоторые аннотации Java EE, представленные в Servlet API 3.1, их назначение и использование.

Исходный код, относящийся к этой статье, можно найтиover on GitHub.