思考一下,如果要在Java Web项目中完成两个功能:
1、打印每个请求从开始到结束的耗时
2、校验某些请求的当前用户是否登录
按照常规思路,解决办法就是
1、在每个请求的 controller 代码的开始和结尾都记录时间,最后打印一下这个时间差
2、在每个需要校验的请求代码中,加上校验当前用户是否登录的代码
这样:
- 修改了原来的代码逻辑
- 每个涉及的点都需要改动,改动量很大
有没有办法就处理这种统一的需求,而不改动原来代码,让原来的代码仍然只关心最核心的业务逻辑?
有,使用代理模式。让代理者去处理统一的需求,被代理者只需实现最核心的业务逻辑。
模拟原始的业务代码:
package constxiong.cxproxy.chapter1;
import constxiong.cxproxy.chapter1.service.Service;
import constxiong.cxproxy.chapter1.service.ServiceImpl;
/**
* 测试类
* @author ConstXiong
* @date 2019-05-29 11:01:30
*/
public class Test {
public static void main(String[] args) {
Service service = new ServiceImpl();
service.login("ConstXiong", "123456");
service.getUserInfo("ConstXiong");
}
}
package constxiong.cxproxy.chapter1.service;
import java.util.Map;
/**
* 服务接口
* @author ConstXiong
* @date 2019-05-29 11:02:02
*/
public interface Service {
boolean login(String username, String password);
Map<String, Object> getUserInfo(String username);
}
package constxiong.cxproxy.chapter1.service;
import java.util.HashMap;
import java.util.Map;
/**
* 服务接口实现
* @author ConstXiong
* @date 2019-05-29 11:02:15
*/
public class ServiceImpl implements Service {
@Override
public boolean login(String username, String password) {
simulateDaOperation(100);
System.out.println("用户名:" + username + ", 密码:" + password + " 登录成功");
return true;
}
@Override
public Map<String, Object> getUserInfo(String username) {
Map<String, Object> userInfo = new HashMap<String, Object>();
simulateDaOperation(100);
userInfo.put("username", username);
userInfo.put("sex", "男");
userInfo.put("age", 18);
System.out.println("用户名:" + username + ", 获取用户信息:" + userInfo);
return userInfo;
}
/**
* 模拟数据库操作,休眠
* @param millis 毫秒数
*/
private void simulateDaOperation(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试类执行结果:
用户名:ConstXiong, 密码:123456 登录成功
用户名:ConstXiong, 获取用户信息:{sex=男, age=18, username=ConstXiong}
完整源码:https://github.com/ConstXiong/xtools cxproxy项目 chapter1
下面我们不使用代理,完成功能。
【Java面试题与答案】整理推荐