[問題] spring, 與架構問題

作者: ghchen (Seele)   2014-05-05 11:04:34
主要問題:
如何禁止從 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 似乎攔不到
請問各位先進,是否有更好的方法?
作者: cyclone350 (老子我最神)   2014-05-05 13:32:00
口頭告知就好...開發人員有那麼不聽話嗎?
作者: ghchen (Seele)   2014-05-05 14:14:00
不聽話 orz
作者: cyclone350 (老子我最神)   2014-05-05 14:38:00
我的話就會寫一隻程式檢查另外檢查source code...
作者: ghchen (Seele)   2014-05-05 14:48:00
我知道 checkstyle 在程式檢核這塊很有用
作者: cyclone350 (老子我最神)   2014-05-05 14:50:00
例如不能有 "import *Repository*;"字串...
作者: ghchen (Seele)   2014-05-05 14:50:00
但是我這邊不一定能接觸到程式碼個模組大多都是交jar上來的

Links booklink

Contact Us: admin [ a t ] ucptt.com