开发者

Refactoring Java Servlets - Looking for a good naming scheme

开发者 https://www.devze.com 2023-03-25 13:50 出处:网络
I\'m refactoring an existing (Ajax) Java Web application, which currently holds lots of its logic directly in the servlets. (The servlets even call each other, using a few nasty tricks ...)

I'm refactoring an existing (Ajax) Java Web application, which currently holds lots of its logic directly in the servlets. (The servlets even call each other, using a few nasty tricks ...)

The refactoring itself is painful, but pretty much straightforward (refactoring everything to use Dependency Injection now).

My problem is, that I really can't come up with the perfect naming scheme:

The refactored Servlets are now holding just a minimum amount of logic (just so much that they process the ServletRequest and ServletResponse, send an HTTP error code, etc.), then they call what I currently refer to as Processors (good/bad name?!?), which can be reused by several Servlets, Test classes, ... The processors perform the logic required for the action, similar to what a Session Bean would do if we were using EJBs.

I never thought, that "Session Bean" would be a good name anyway. And I'm also not very keen on defining a monolithic "Facade". I'm looking primarily for a better name than "Processor", or maybe some ideas how you structure your Servlet processing code.

Example

开发者_JAVA百科

This is a simplified example (the real application uses GWT with Gilead, ... but that's not so important):

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));

    ...
}
}

As the example suggests, I prefer to have specialized processors, which are responsible for one task only (or maybe a few very strongly related tasks) - opposed to a big class that handles lots of different actions.


Here is my example based on previous discussion:

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);
    }
}

Hope this helps.


Why not call them what they are: Servlets?

As in:

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

精彩评论

暂无评论...
验证码 换一张
取 消