Статьи

Простой CRUD с использованием Servlet 3.0, Redis / Jedis и CDI — Часть 2

В этом посте мы сосредоточимся на CDI и Servlet 3.0. Вы можете увидеть часть 1 здесь .

Давайте начнем с CDI.

Когда я начал писать пост о происхождении этой серии, я не думал писать о CDI. Чтобы быть искренним, я никогда не использовал это раньше. Идея поста состояла в том, чтобы создать краду с использованием джедаев и сервлетов. Но когда я писал приложение, я просто ненавидел идею создавать бины. В своей повседневной работе я использую Spring для внедрения зависимостей и прочего, но для этого поста я не хотел бы добавлять его. Итак, я решил попробовать CDI, и я был очень удивлен, насколько просто добавить и использовать его в приложении.

Итак, что такое CDI?

CDI — это аббревиатура для внедрения контекста и зависимости, это спецификация javaee для адресации DI на платформе javaee. Поэтому, как только он активирован в вашем проекте, вы можете легко добавить зависимость, используя аннотацию @Inject . На CDI все является бобом,
и почти все классы могут быть введены.

Как активировать CDI?

Если мы запускаем наше приложение на сервере приложений Java EE, нам нужно только добавить пустой файл beans.xml в нашу папку META-INF. Но на таких серверах, как tomcat, нам нужно добавить еще несколько файлов и конфигураций:

  1. Добавьте weld-servlet.jar в папку lib. Вы можете получить его с сайта Weld;
  2. Создайте файл context.xml в разделе META-INF:
    1
    2
    3
    4
    5
    6
    7
    8
    <?xml version="1.0" encoding="UTF-8"?>
    <Context>
    <Manager pathname=""/> <!-- disables storage of sessions across restarts -->
    <Resource name="BeanManager"
    auth="Container"
    type="javax.enterprise.inject.spi.BeanManager"
    factory="org.jboss.weld.resources.ManagerObjectFactory"/>
    </Context>
  3. Добавьте некоторые конфигурации сварных швов в web.xml:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    <listener>
            <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
        </listener>
     
        <resource-env-ref>
            <resource-env-ref-name>BeanManager</resource-env-ref-name>
                <resource-env-ref-type>
                    javax.enterprise.inject.spi.BeanManager
                </resource-env-ref-type>
        </resource-env-ref>
  4. Тогда нам нужно только добавить пустой файл beans.xml в META-INF или WEB-INF.

После этого мы готовы начать кодирование с CDI.

В последнем посте мы создали класс UserDAO , в методах которого мы использовали экземпляр класса Jedis для выполнения команд Redis. Этот экземпляр был внедрен в объект UserDAO с помощью аннотации @Inject . Мы можем видеть это ниже:

1
2
3
4
5
public class UserDAO {
 
    @Inject Jedis jedis;
        //....
}

Как мы видим, внедрить экземпляр класса Jedis так просто. Если бы у класса Jedis был конструктор без аргумента, он был бы введен напрямую. Но это не так, поэтому мы использовали класс с методом, аннотированным @Produces . Это указывает на то, что это метод производителя. В нашем примере мы также использовали JedisPool, откуда мы получаем соединения Jedis. В этом случае у нас есть два производителя:

  1. Для джедаев
  2. Другое для джедаев .

У производителя Jedis есть экземпляр JedisPool, внедренный через @Inject , мы можем видеть их ниже:

JedisPoolFactory:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
public class JedisPoolFactory {
 
    private String host = "localhost";
    private JedisPool jedisPool;
    @Singleton
    public @Produces JedisPool getJedisPool(){
        jedisPool = new JedisPool(new JedisPoolConfig(), host);
        return jedisPool;
    }
 
    public void detroy(@Disposes JedisPool jedisPool){
        jedisPool.destroy();
    }
}

В коде мы видим, что метод getJedisPool аннотируется @Produces, говоря, что он является производителем экземпляров JedisPool. В этом коде мы видим также две другие аннотации.

  1. @Singleton — говоря, что возвращаемый экземпляр является одиночным, это означает, что будет только один экземпляр этого класса;
  2. @Disposesуказывает, какой метод следует вызывать при уничтожении экземпляра JedisPool;

Теперь мы можем увидеть JedisConnectionFactory :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
public class JedisConnectionFactory {
 
    @Inject
    private JedisPool jedisPool;
 
    @Produces
    public Jedis getJedis(){
        return jedisPool.getResource();
    }
 
    public void returnResource(@Disposes Jedis jedis){
        System.out.println("Returning jedis Connection");
        jedisPool.returnResource(jedis);
    }
 
}

Чтобы получить экземпляр Jedis, классу нужен экземпляр JedisPool . JedisPool внедряется через @Inject и создается методом продюсера, который мы видели в последнем коде. Он также имеет @Disposes, который просто возвращает соединение с пулом .

Таким образом, мы можем внедрить экземпляр Jedis в DAO. Затем в других классах мы просто используем @Inject , как мы видим в классе Service и Servlet:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
//UserService
@RequestScoped
public class UserService {
 
    @Inject
    UserDAO userDAO;
//...
}
 
//Servlet - UserController
public class UserController extends HttpServlet {
    private static final long serialVersionUID = 1L;
 
    @Inject UserService userService;
//...
}

В этом примере мы видим, как просто добавить и использовать CDI в приложении.

Сервлет 3.0

Основное отличие новых сервлетов в том, что нам не нужно объявлять их в web.xml , теперь мы можем просто установить параметры сервлета с помощью аннотаций. В сервлете, который мы создали в нашем примере, мы использовали аннотацию, чтобы установить отображение URL для нашего сервлета. Кто уже разработал сервлет раньше, знает, что это одна из конфигураций, которую мы должны добавить в web.xml. Мы можем видеть это в сервлете ниже:

01
02
03
04
05
06
07
08
09
10
11
@WebServlet("/UserController")
public class UserController extends HttpServlet {
    private static final long serialVersionUID = 1L;
 
    @Inject UserService userService;
//...
 
//.. doGet
//.. doPost
 
}

В приведенном выше коде мы говорим, что сервлет ответит на путь / UserController. С помощью этой аннотации мы можем добавить больше конфигураций, таких как:

1
@WebServlet(value="/UserController", name="userServlet")

В приведенном выше коде мы объявили отображение и имя сервлета. Существуют и другие аннотации для упрощения использования сервлетов api, такие как @WebInitParam, @WebListener, @WebFilter . Мы не будем говорить о них, но вы можете найти о них большие ресурсы. Также, начиная с сервлетов 3.0, поддерживается асинхронная обработка.

Вот и все на сегодня. Любые комментарии или предложения приветствуются.

  • Вы можете найти исходный код здесь .