控制層 -> 服務層 -> 持久層java
模塊劃分git
分離功能性需求和非功能性需求spring
下載地址:點擊前往編程
package cn.test.demo.base_demo.entity; /** * @author 王楊帥 * @create 2018-04-29 17:11 * @desc 商品實體類 **/ public class Product { private Integer id; private String name; public Product() { } public Product(Integer id, String name) { this.id = id; this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Product{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
該類主要用來設定用戶和獲取用戶緩存
package cn.test.demo.base_demo.security; /** * @author 王楊帥 * @create 2018-04-29 17:15 * @desc 模擬用戶登陸,該類能夠設定用戶和獲取用戶 **/ public class CurrentSetHolder { private final static ThreadLocal<String> holder = new ThreadLocal<>(); /** * 獲取用戶 * @return */ public static String get() { return holder.get() == null ? "unknown" : holder.get(); } /** * 設定用戶 * @param user */ public static void set(String user) { holder.set(user); } }
該類主要用於判斷當前用戶是不是「admin」用戶編程語言
package cn.test.demo.base_demo.service; import cn.test.demo.base_demo.security.CurrentSetHolder; import org.springframework.stereotype.Component; /** * @author 王楊帥 * @create 2018-04-29 17:19 * @desc 權限校驗服務類 **/ @Component public class AuthService { /** * 權限檢查,若是用戶不是 「admin" 就會報錯 */ public void checkAccess() { String user = CurrentSetHolder.get(); if (!"admin".equals(user)) { throw new RuntimeException("operation not allow."); } } }
該類主要實現對Product的一些操做分佈式
package cn.test.demo.base_demo.service; import cn.test.demo.base_demo.entity.Product; import cn.test.demo.base_demo.security.AdminOnly; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @author 王楊帥 * @create 2018-04-29 17:14 * @desc 商品服務層 **/ @Service @Slf4j public class ProductService { private final String className = getClass().getName(); /** * 依賴注入權限校驗服務 */ @Autowired private AuthService authService; public void insert(Product product) { authService.checkAccess(); // 利用權限校驗對象進行權限校驗,不是 」admin" 就會報錯 log.info("===/" + className + "/insert===新增數據"); } @AdminOnly public void delete(Integer id) { // authService.checkAccess(); // 利用權限校驗對象進行權限校驗 log.info("===/" + className + "/delete===刪除數據"); } }
在調用ProductService的insert方法前對用戶進行設定ide
package cn.test.demo.base_demo.service; import cn.test.demo.base_demo.entity.Product; import cn.test.demo.base_demo.security.CurrentSetHolder; import org.junit.Test; import org.junit.runner.RunWith; import org.omg.CORBA.Current; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import static org.junit.Assert.*; @RunWith(SpringRunner.class) @SpringBootTest public class ProductServiceTest { /** * 依賴注入權限 */ @Autowired private ProductService productService; /** * productService.insert(product) 方法中有權限驗證,若是不是「admin"用戶就會報錯 */ @Test public void annonInsert() { CurrentSetHolder.set("bob"); // 設置用戶 Product product = new Product(); productService.insert(product); } /** * productService.insert(product) 方法中有權限驗證,若是不是「admin"用戶就會報錯 */ @Test public void adminInsert() { CurrentSetHolder.set("admin"); // 設置用戶 Product product = new Product(); productService.insert(product); } @Test public void delete() throws Exception { } }
下載地址:點擊前往函數式編程
package cn.test.demo.base_demo.entity; /** * @author 王楊帥 * @create 2018-04-29 17:11 * @desc 商品實體類 **/ public class Product { private Integer id; private String name; public Product() { } public Product(Integer id, String name) { this.id = id; this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Product{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
package cn.test.demo.base_demo.security; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface AdminOnly { }
該類主要用來設置用戶和獲取用戶函數
package cn.test.demo.base_demo.security; /** * @author 王楊帥 * @create 2018-04-29 17:15 * @desc 模擬用戶登陸,該類能夠設定用戶和獲取用戶 **/ public class CurrentSetHolder { private final static ThreadLocal<String> holder = new ThreadLocal<>(); /** * 獲取用戶 * @return */ public static String get() { return holder.get() == null ? "unknown" : holder.get(); } /** * 設定用戶 * @param user */ public static void set(String user) { holder.set(user); } }
該類主要對全部使用了@AdminOnly註解的方法進行權限校驗
package cn.test.demo.base_demo.security; import cn.test.demo.base_demo.service.AuthService; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * @author 王楊帥 * @create 2018-04-29 17:37 * @desc 權限檢查的AOP類 **/ @Aspect @Component public class SecurityAspect { @Autowired AuthService authService; @Pointcut("@annotation(AdminOnly)") public void adminOnly(){ } @Before("adminOnly()") public void check(){ authService.checkAccess(); } }
該類的delete方法用了@AdminOnly註解,因此delete方法會進行權限校驗
package cn.test.demo.base_demo.service; import cn.test.demo.base_demo.entity.Product; import cn.test.demo.base_demo.security.AdminOnly; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @author 王楊帥 * @create 2018-04-29 17:14 * @desc 商品服務層 **/ @Service @Slf4j public class ProductService { private final String className = getClass().getName(); /** * 依賴注入權限校驗服務 */ @Autowired private AuthService authService; public void insert(Product product) { authService.checkAccess(); // 利用權限校驗對象進行權限校驗,不是 」admin" 就會報錯 log.info("===/" + className + "/insert===新增數據"); } @AdminOnly public void delete(Integer id) { // authService.checkAccess(); // 利用權限校驗對象進行權限校驗 log.info("===/" + className + "/delete===刪除數據"); } }
productService.delete(id) 方法中有權限驗證,若是不是「admin"用戶就會報錯【利用AOP實現的】
package cn.test.demo.base_demo.service; import cn.test.demo.base_demo.entity.Product; import cn.test.demo.base_demo.security.CurrentSetHolder; import org.junit.Test; import org.junit.runner.RunWith; import org.omg.CORBA.Current; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import static org.junit.Assert.*; @RunWith(SpringRunner.class) @SpringBootTest public class ProductServiceTest { /** * 依賴注入權限 */ @Autowired private ProductService productService; /** * productService.insert(product) 方法中有權限驗證,若是不是「admin"用戶就會報錯【利用傳統方法實現的】 */ @Test public void annonInsert() { CurrentSetHolder.set("bob"); // 設置用戶 Product product = new Product(); productService.insert(product); } /** * productService.insert(product) 方法中有權限驗證,若是不是「admin"用戶就會報錯【利用傳統方法實現的】 */ @Test public void adminInsert() { CurrentSetHolder.set("admin"); // 設置用戶 Product product = new Product(); productService.insert(product); } /** * productService.delete(id) 方法中有權限驗證,若是不是「admin"用戶就會報錯【利用AOP實現的】 */ @Test public void annoDelete() throws Exception { CurrentSetHolder.set("peter"); productService.delete(3); } /** * productService.delete(id) 方法中有權限驗證,若是不是「admin"用戶就會報錯【利用AOP實現的】 */ @Test public void adminDelete() { CurrentSetHolder.set("admin"); productService.delete(4); } }