Перейти к основному содержимому

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

· 6 мин. чтения

1. Обзор

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

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

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

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

  • @WebServlet
  • @WebInitParam
  • @Веб-фильтр
  • @WebListener
  • @ServletSecurity
  • @HttpConstraint
  • @HttpMethodConstraint
  • @MultipartConfig

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

3. @Веб-сервер

Проще говоря, эта аннотация позволяет нам объявлять классы 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 . Мы можем связать фильтры с сервлетом или с группой сервлетов и статическим содержимым, указав шаблон 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();
}
}

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

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

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

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

  • ценность
  • роли разрешены
  • транспортГарантия

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

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

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

  • ценность
  • emptyRoleSemantic
  • роли разрешены
  • транспортГарантия

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

8. @MultipartConfig

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

Это позволит использовать методы 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, их назначение и использование.

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