[問題] spring, 與架構問題
主要問題:
如何禁止從 Controller 直接呼叫 Repository
問題描述:
我使用 spring 來開發 webapp
採用三層式架構
Controller -> Service -> Repository
// Repository 是 Spring Data 使用的術語,可以想像成 DAO
原本打算把 jta, auditing log 加在 Service layer 上
所以我不希望其他開發人員從 Controller 這裡直接呼叫 Repository
但是其他開發人員不可能被我控制
他們可以隨意的在 controller 裡面任意 autowired repository
接下來就隨便他們搞了
後來我加了一個 AOP 來限制 repository 的呼叫
如果是從 service package 呼叫的就放行,否則拋出例外
@Aspect
public class ModelAdvice {
private Pattern pattern = Pattern.compile("^demo\\.services\\..*");
@Before("execution(* demo.repositories..*Repository.*(..))")
public void protectRepositories(JoinPoint joinPoint) {
StackTraceElement[] stElements =
Thread.currentThread().getStackTrace();
for (StackTraceElement element : stElements) {
Matcher matcher = pattern.matcher(element.getClassName());
if (matcher.matches()) {
return;
}
}
throw new RuntimeException("security violation!");
}
}
雖然可以動,但是覺得不太漂亮,而且可能會很慢
後來有人說把 service 跟 repository 放在同一個 package
然後 repository 定義成 default 這樣子的話
controller 完全無法定義 repository 型別的變數
看起來似乎很有道理,但是很快又被破解了
@Autowired
private ApplicationContext context;
private JpaRepository getRepoBean(String name) {
try {
Class<?> formTypeClazz = Class.forName(name);
Object bean = context.getBean(formTypeClazz);
JpaRepository repo = (JpaRepository)bean;
return repo;
}
catch (BeansException e) {
throw new RuntimeException();
}
catch (ClassNotFoundException e) {
throw new RuntimeException();
}
}
只要把想要用的 repository qualified class name 傳進來就能拿到
雖然是 JpaRepository 但是基本功能都有
而且前面的 AOP 似乎攔不到
請問各位先進,是否有更好的方法?
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 122.116.187.182
※ 文章網址: http://www.ptt.cc/bbs/java/M.1399259076.A.B9E.html
→
05/05 13:32, , 1F
05/05 13:32, 1F
→
05/05 14:14, , 2F
05/05 14:14, 2F
→
05/05 14:38, , 3F
05/05 14:38, 3F
→
05/05 14:48, , 4F
05/05 14:48, 4F
→
05/05 14:50, , 5F
05/05 14:50, 5F
→
05/05 14:50, , 6F
05/05 14:50, 6F
※ 編輯: ghchen (122.116.187.182), 05/05/2014 14:51:33
→
05/05 14:54, , 7F
05/05 14:54, 7F
討論串 (同標題文章)
以下文章回應了本文:
完整討論串 (本文為第 1 之 2 篇):