我正在构建一个使用服务 API 的 UI 客户端,该 API 在后台使用 Web 服务。其中一项 API 服务如下所示:
interface UserService {
List<User> findUsers(User loggedInUser, UserSearchParameters searchParameters, PagingParameters pagingParameters) throws AuthenticationFault, InvalidIndexFault;
void removeUser(User loggedInUser, User userToRemove) throws AutheticationFault;
void addUser(User loggedInUser, User newUser) throws AuthenticationFault;
}
loggedInUser 是代表调用该方法的用户。 AuthenticationFault 是一个已检查的异常。这样的服务接口(interface)大约有 20 个。我想要做的是实现一个隐藏loggedInUser参数和AuthenticationFault异常的外观。外观实现将使用当前登录客户端的用户调用这些方法。
我还想对其他已检查的异常进行一些清理。正如您所看到的,当客户端尝试检索页面 -1 时会引发 InvalidIndexFault 异常,但这是程序员错误,我不想将其作为检查异常。
目前,我所做的总是为我不喜欢的异常重新抛出 RuntimeException,但如果我后来改变主意,以后需要做很多工作来改变它。这也感觉像是代码重复。其他程序员刚刚吞下了异常并记录了它们,这是非常可怕的。大多数时候,如果出现异常,我希望将其冒泡到显示错误的 ui 中的错误处理程序。
我想到了一些解决方案:
- Java动态代理
- 代码生成
我还没有抽出时间尝试这些解决方案,所以我想我不妨先在这里问一下。你建议我如何实现这个?环境是 Java 6,构建工具是 Maven 3(如果有帮助的话)。
PS。如果您回答这个问题,请说的不仅仅是“选择 2”:) 欢迎提供任何提示和其他实现细节。澄清一下,检索当前登录的用户不是问题,因此您不必帮助我。我目前将其隐藏在接口(interface)后面并使用 IoC 将其注入(inject)。它在幕后使用 ThreadLocals
最佳答案
我想这将是完美的用例
- Java 动态代理
- 线程局部变量
说明一下:
首先,创建您的外观界面:
interface UserServiceFacede { List findUsers(UserSearchParameters searchParameters, PagingParameters pagingParameters) throws AuthenticationFault, InvalidIndexFault; void removeUser(User userToRemove) throws AutheticationFault; void addUser(User newUser) throws AuthenticationFault; }
接下来你实现你的 InvocableHandler :
public class UserHandler implements InvocationHandler{ private final UserService service; public UserHandler(UserService service) { this.service = service; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { .... // Based on the method argument, call the appropriate function on the actual service // object .... } }
然后您可以像这样创建代理对象:
UserServiceFacade uProxy = (UserServiceFacade)Proxy.newProxyInstance(UserHandler.class.getClassLoader(), new Class[] { UserServiceFacade.class}, new UserHandler(userService));
第一个参数是类加载器,第二个参数是代理必须确认的接口(interface)列表,第三个参数是处理程序对象
现在的问题是如何获取登录用户的句柄。这就是ThreadLocal进来。
创建一个 ThreadLocal 静态变量来保存登录用户。然后在调用代理之前将当前用户设置到ThreadLocal中
private static final ThreadLocal loggedinUser = ...; ... ... loggedinUser.set(currentUser); // Create a user Proxy object as mentioned above.. uProxy.findUser(searchParams, ..); ...
从处理程序的调用函数内的 ThreadLocal 检索用户。现在在处理程序内部,您可以访问loggedinUser(使用loggedinUser.get()
)以及用户服务对象(您已将服务对象传递到处理程序的构造函数中)
就如何处理异常而言,我通常会继续抛出 RuntimeExceptions 的子类。然后在应用程序的外围层捕获这些。我所说的外围层是指应用程序/库的入口点。如果您正在开发 webbApp,这将是您的 Servlet。
关于java - 用于隐藏 Java Web 服务的身份验证详细信息的外观,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6889948/