как реализовать сервисный уровень в приложении сервлета - PullRequest
0 голосов
/ 30 июля 2011

Предположим, я хочу создать сервисный слой для своего веб-приложения, в котором используются сервлеты. Как мне поступить? (Я не использую фреймворк веб-приложения ... Так что, пожалуйста, потерпите меня). Должен ли я реализовать его какслушатель? Служба предназначена для доступа к базе данных. То есть я должен иметь возможность звонить из моего сервлета

class MyServlet{
...
    doPost(...){
    ...
        MyEntity entity = dbAccessService.getMyEntity(someId);
        ...
    }
}

Где dbAccessService должен иметь дело с сеансом гибернации, транзакциями и т. д. Ранее я делал этовсе это внутри методов дао, но мне советовали, что это не очень хорошая идея.

Любые предложения приветствуются

спасибо

mark

Пример кода:приведено ниже

    class DBAccessServiceImpl{
    ...
        private MyEntity getMyEntity(Long id){
                Transaction tx = null;
                MyEntity me = null;
                Session session = HibernateUtil.getCurrentSession();
                try{
                    tx = session.beginTransaction();
                    return entitydao.findEntityById(id);
                }catch(RuntimeException e){
                    logger.info("problem occurred while calling findEntityById()");
                    throw e;
                }
            }
    ...
}

Затем создайте прослушиватель для создания экземпляра DBAccessService

class MyAppListener implements ServletContextListener {

    @Override

    public void contextInitialized(ServletContextEvent ctxEvent) {

        ServletContext sc = ctxEvent.getServletContext();
        DBAccessService dbservice = new DBAccessServiceImpl();
        sc.setAttribute("dbAccessService",dbservice);

    }
}

В web.xml добавьте прослушиватель

...
<listener>

    <listener-class>myapp.listeners.MyAppListener</listener-class>

 </listener>
...

Ответы [ 2 ]

4 голосов
/ 30 июля 2011

Предполагая, что вы не хотите внедрять фреймворк, два варианта имеют смысл (на мой взгляд):

  1. определите ваш сервисный уровень, используя сессионные компоненты EJB без сохранения состояния. Вам нужен контейнер EJB.
  2. сделайте это как всегда на языках ОО, создайте интерфейс и соответствующую реализацию:

Определить интерфейс

public interface BusinessService {
    abstract public BusinessObject performSomeOperation(SomeInput input);
}

И реализация

public class BusinessServiceImpl implements BusinessService {
    public BusinessObject performSomeOperation(SomeInput input) {
        // some logic here...
    }
}

У вас есть несколько вариантов создания службы. Если вы начинаете с нуля с небольшого приложения, может быть достаточно просто создать экземпляр службы внутри вашего веб-приложения:

BusinessService service = new BusinessServiceImpl();
service.performSomeOperation(...);

Кстати: Позже вы можете захотеть провести рефакторинг и реализовать некоторые абстракции, связанные с созданием экземпляра Сервиса (шаблон Factory, внедрение зависимостей и т. Д.). Кроме того, в больших системах существует вероятность того, что вам потребуется разместить уровень сервиса в собственной инфраструктуре для масштабируемости, чтобы ваше веб-приложение связывалось с уровнем сервиса через открытый протокол, будь то RESTful или веб-сервисы.

Однако будущее выглядит так, что благодаря четко определенному интерфейсу, определяющему ваши бизнес-функции, вы сможете «легко» двигаться вперед в случае роста приложения.

Ответ на ваше обновление: Я бы не реализовывал сам сервис в качестве слушателя, это не имеет смысла. Тем не менее, ваш пример кода кажется разумным, но вы должны различать Service (в данном случае DBAccessService) и способ его создания / извлечения (слушатель). Реализованный вами слушатель играет роль ServiceLocator , который способен находить определенные сервисы. Если вы храните экземпляр вашей службы в контексте сервлета, вы должны напомнить, что реализация службы должна быть поточно-ориентированной.

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

public final class ServiceFactory {

    public static DBAccessService getDBAccessService() {
        DBAccessService service = new DBAccessServiceImpl();
        return service;
    }
}

Для реализации ServiceFactory доступны сложные альтернативы, и в настоящее время некоторые называют это анти-паттерном. Но до тех пор, пока вы не хотите начинать с внедрения зависимостей (и т. Д.), Это по-прежнему верное решение. Реализация сервиса DBAccessServiceImpl доступна только в одном месте (на заводе). Как я упоминал ранее - следите за многопоточностью ... надеюсь, это поможет!

2 голосов
/ 30 июля 2011

То, что вы предлагаете, на самом деле ничем не отличается от выполнения сеанса и обработки транзакций в DAO.В конце концов, ваш класс обслуживания вызывает DAO;к клиентскому коду нет никакой разницы.

Скорее, я подозреваю, что тот, кто сказал вам не включать обработку сеансов в DAO, думал, что вместо этого следует использовать Открыть сеанс в представлении шаблон.Очень просто, в его обычной форме, это включает в себя написание Filter , который открывает сеанс и запускает транзакцию перед передачей запроса по цепочке, а затем фиксирует транзакцию (или откатывает ее при необходимости) и закрываетсеанс после завершения запроса.Это означает, что в рамках любого одного запроса весь доступ к постоянным объектам происходит в одной транзакции и в одном сеансе, что обычно является правильным способом сделать это (это, безусловно, самый быстрый способ сделать это).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...