«1. Обзор

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

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

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

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

    @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 имеет набор атрибутов, которые позволяют нам настраивать сервлет:

    имя описание 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 и параметрами инициализации сервлета.

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

@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 — для уведомлений о жизненном цикле ServletContext ServletContextAttributeListener — для уведомлений об изменении атрибута ServletContext ServletRequestListener — для уведомления при каждом запросе ресурса ServletRequestAttributeListener — для уведомлений о добавлении, удалении или изменении атрибута в ServletRequest HttpSessionListener — для уведомлений при создании и уничтожении нового сеанса HttpSessionAttributeListener — для уведомлений при появлении нового атрибут добавляется или удаляется из сеанса

Ниже приведен пример того, как мы можем использовать 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("<html> Balance of " + accountType + " account is: " + accountBalance 
        + "</html>");
        writer.flush();
    }
}

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

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

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

value rolesAllowed transportGuarantee

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

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

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

value emptyRoleSemantic rolesAllowed transportGuarantee

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

8. @MultipartConfig

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

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

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

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

@MultipartConfig имеет четыре атрибута:

@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");
        }
    }

}

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

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

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

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

«