Рефакторинг Java-сервлетов - Ищем хорошую схему именования - PullRequest
4 голосов
/ 01 августа 2011

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

Рефакторинг сам по себе болезнен, но довольно прост (рефакторинг всего, чтобы использовать Dependency Injection сейчас).

Моя проблема в том, что я действительно не могу придумать идеальную схему именования:

Реорганизованные сервлеты теперь содержат лишь минимальное количество логики (настолько, что они обрабатываютServletRequest и ServletResponse, отправляют код ошибки HTTP и т. Д.), Затем они называют то, что я в настоящее время называю Процессоры (хорошее / плохое имя?!?), Которые могут быть повторно использованы несколькими сервлетами, тестовыми классами, ... Процессоры выполняют логику, необходимую для действия, аналогично тому, что делал бы Session Bean, если бы мы использовали EJB.

Я никогда не думал, что Session Bean в любом случае будет хорошим именем.И я тоже не очень заинтересован в определении монолитного «Фасада».В первую очередь я ищу лучшее имя, чем «Процессор», или, может быть, есть идеи, как вы структурируете свой код обработки сервлета.

Пример

Это упрощенный пример(настоящее приложение использует GWT с Gilead, ... но это не так важно):

public class UserRegistrationServlet extends HttpServlet {

@Inject
UserRegistrationProcessor userRegistrationProcessor;

@Override
protected void doPost(final HttpServletRequest req, 
        final HttpServletResponse resp)
        throws ServletException, IOException {

    RegistrationRequest registrationRequest = parseRegistrationRequest(req);

    RegistrationResult registrationResult = 
                userRegistrationProcessor.process(registrationRequest);

    pw.print(toJson(registrationResult));

    ...
}
}

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

Ответы [ 2 ]

4 голосов
/ 01 августа 2011

Вот мой пример, основанный на предыдущем обсуждении:

public class UserRegistrationServlet extends HttpServlet {

    @Inject
    private UserRequestExtractor userRequestExtractor;

    @Inject
    private UserRegistrationService userRegistrationService;

    @Override
    protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
        PrintWriter pw = response.getWriter();
        pw.print(createResponse(userRequestExtractor.extract(request)));
    }

    protected String createResponse(User newUser) {
        if (newUser == null) {
            return "{'message' : 'the user parameters are not valid'}";
        }
        else {
            UserRegistrationResult result = userRegistrationService.register(newUser);
            switch (result) {
                case SUCCESS:
                    return "{'message' : 'hurray'}";
                case EMAIL_IN_USE:
                    return String.format("{'message' : 'the email address %s is already in use'}", newUser.email);
                case USERNAME_IN_USE:
                    return String.format("{'message' : 'the user name %s is already in use'}", newUser.username);
                default:
                    return "{'message' : 'an error occurred'}";
            }
        }
    }
}

public class User {
    private String username;
    private String email;

    public boolean isValid() {
        return username != null && email != null;
    }
}

/**
 * Extractor which instantiates an object of type T from a request
 * 
 * @param <T>
 */
public interface RequestExtractor<T> {
    public T extract(HttpServletRequest request);
}

public class UserRequestExtractor implements RequestExtractor<User> {
    public User extract(HttpServletRequest request) {
        User user = new User();
        user.username = request.getParameter("username");
        user.email = request.getParameter("email");
        // validation could also be a responsibility of the RequestExtractor
        if (!user.isValid()) {
            return null;
        }
        return user;
    }
}

public interface UserRegistrationService {
    public UserRegistrationResult register(User user);
}

// implementation of UserRegistrationService omitted

public enum UserRegistrationResult {
    SUCCESS, EMAIL_IN_USE, USERNAME_IN_USE;
}

/**
 * Unit test
 */
public class UserRegistrationServletTest {

    @Test
    public void test() {
        UserRegistrationServlet cut = new UserRegistrationServlet();
        User user = new User();
        user.username = null;
        user.email = "test@test.test";

        String response = cut.createResponse(user);

        Assert.assertEquals("{'message' : 'the user parameters are not valid'}", response);
    }
}

Надеюсь, это поможет.

1 голос
/ 01 августа 2011

Почему бы не назвать их такими, какие они есть: Servlet s?

Как в:

com.mycompany.app.admin.user.SaveServlet.java
com.mycompany.app.admin.user.ListServlet.java
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...