重构Java Servlet - 寻找一个好的命名方案

时间:2011-08-01 11:23:51

标签: java design-patterns servlets refactoring

我正在重构现有的(Ajax)Java Web应用程序,该应用程序目前在servlet中直接拥有大量逻辑。 (servlet甚至互相打电话,使用一些讨厌的技巧......)

重构本身很痛苦,但非常简单(现在重构一切以使用Dependency Injection)。

我的问题是,我真的无法想出完美的命名方案:

重构的Servlet现在只占用最少量的逻辑(只是它们处理ServletRequest和ServletResponse,发送HTTP错误代码等),然后它们调用我当前称为处理器的内容(好/坏名字?!?),可以被几个Servlet,Test类重用,......处理器执行动作所需的逻辑,类似于Session Bean在我们使用时会做的事情的EJB。

我从没想过,“Session Bean”无论如何都会是一个好名字。而且我也不太热衷于定义一个单片的“Facade”。我主要是寻找一个比“处理器”更好的名称,或者可能是一些想法如何构建你的Servlet处理代码。

实施例

这是一个简化的例子(真正的应用程序使用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 个答案:

答案 0 :(得分:4)

以下是基于之前讨论的示例:

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 :(得分:1)

为什么不给他们称呼他们:Servlet s?

如:

com.mycompany.app.admin.user.SaveServlet.java
com.mycompany.app.admin.user.ListServlet.java