商家管理微服务设计
商家管理微服务是一个独立的RESTAPI应用,这个应用通过接口服务对外提供商家信息管理、商家权限管理和菜单资源管理等方面的功能。
商家管理微服务开发在merchant-restapi模块中实现,有关这一类型模块的依赖引用、配置、启动程序的设计等,可以参考前面章节中有关RESTAPI微服务开发中的相关说明,不再重复。
商家管理微服务将直接调用权限管理模型的领域服务,在调用之前,我们可以对领域服务层进行一个单元测试,以验证领域服务层的程序正确性。同时,也可以通过单元测试生成一个管理员用户,以方便后面的操作体验。
商家管理服务层单元测试
首先,在merchant-restapi模块中,对10.1节开发的各个领域服务进行测试,从而对整个商家业务领域的开发进行全面的验证。这些测试包括各个实体的创建、数据获取、对象更新、删除和分页查询等内容。
创建商家及其用户实体的测试用例如下所示:
@RunWith (Spr ingRunner.class)@ContextConfiguration(classes = {JpaConfiguration.class,MerchantRestApiAppl ication.class})@SpringBootTes tpublic class UserTest {private static Logger logger = LoggerFactory. getLogger (UserTest.class) ;@Autowi redprivate UserService userService;@Autowiredprivate RoleService roleService;@Autowiredprivate ResourceService resourceService;CAutowiredprivate ModelService modelService;CAutowiredprivate KindService kindService;@Autowiredprivate MerchantService merchantService;@Testpublic void insertData() {Kind kind = new Kind() ;kind.setName("商家系统");kind. setLink ("merchantweb") ;kindService. save (kind) ;Assert .notNull (kind.getId(), "create kind error") ;Model model = new Model () ;model . setName("用户管理") ;model. setHost ("/user/ index") ;model. setKind(kind) ;modelService.save (model) ;Assert. notNull (model.getId(),"create model error") ;Resource resource = new Resource() ;resource.setName("用户修改");resource.setUrl ("/user/edit/**") ;resource . setModel (model) ;resourceService. save (resource) ;Assert. notNull (resource.getId(), "create resource error") ;Role role = new Role() ;role.setName("商家管理员");List resources = new ArrayList<>() ;resources. add (resource) ;role. setResources (resources) ;roleService.save (role) ;Assert. notNull (role.getId(),"create role error") ;Merchant merchant = new Merchant() ;merchant . setName ("测试商家") ;merchantService. save (merchant) ;Assert .notNull (merchant.getId(), "create merchant error") ;User user = new User() ;user. setName ("admin") ;BCryptPasswordEncoder bpe = new BCryptPasswordEncoder() ;user. setPassword (bpe. encode ("123456")) ;user . setEmail ("admin@com.cn") ;List roles = new ArrayList<>() ;roles.add(role) ;user . setRoles (roles) ;user . setMerchant (merchant) ;userService. save (user) ;Assert .notNull (user.getId(), "create user error");}}
在这个测试用例中,包含了商家业务模型中所有实体的创建,这些实体包括分类、模块、资源、角色、商家、用户等。如果测试通过,则可以生成一个由分类、模块和资源组成的三级菜单,同时创建一个具有所属商家、 具有一个角色和相关访问资源权限的用户实体。这个用户实体的用户名和密码为“admin/123456”。在后面的开发中,我们可以使用这个用户来登录系统。
如果测试不能通过,则可以根据断言中提示的错误信息,在相关的服务组件中查找出错的原因。
获取实体的测试用例如下所示:
@Testpublic void getData() {User user = userService. findOne (1L) ;Assert.notNull (user, "not find") ;logger . info("====user==={}", new Gson() . toJson (user));}
这个测试用例通过用户ID获取用户信息,如果测试通过,则输出用户实体的完整信息,包括用户、用户拥有的角色和角色包含的资源等。
分页查询的测试如下所示:
@Testpublic void findAll() throws Exception{SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");Date date = sdf.parse ("2017-01-0100:00:00") ;UserQo userQo = new UserQo() ;userQo. setCreated(date) ;Merchant merchantmerchantService. findOne (1L) ;MerchantQo merchantQo = CopyUtil.copy (merchant, MerchantQo .class);userQo. setMerchant (merchantQo) ;Page page = userService. findA1l (userQo) ;Assert.notEmpty (page .getContent(), "list is empty");List list = page. getContent() ;for(User user : list) {logger. info("====user===={},", new Gson() .toJson(user));}}
这个测试用例使用查询对象UserQo配置了分页查询的参数,来执行用户信息的分页查询。
在查询参数中设定了创建日期和所属商家等属性。在查询成功后,将输出每条记录的信息,这些信息有用户对象、用户拥有的角色、角色关联的资源和资源所属的模块等。
其他有关更新和删除等测试,可以参照上面的方法进行设计。
单元测试在进行工程打包时,可以作为程序正确性的一一个验证手段。如果测试不通过,则不能成功打包。当使用Maven进行项目管理时,这项功能默认是打开的。如果想要在关闭打包时执行测试,可以在工程中使用下面所示的配置:
org. apache . maven.pluginsmaven-surefire-plugin2.20true configuration>
商家服务的接口开发
在商家管理的REST API应用中,包含了商家信息管理、商家用户权限管理和菜单资源管理等接口的开发。每一个接口的设计我们分别使用一个RestController来实现。这些接口的设计基本上大同小异,下面我们以用户接口的设计为例进行说明。
用户的查询接口是使用GET方法实现的,几种查询接口的实现方法如下所示:
@RestController@RequestMapping("/user")public class UserControllerprivate static Logger logger 二LoggerFactory .getLogger (UserController.class) ;@Autowi redprivate UserService userService;@RequestMapping("/{id}")public String findById (EPathVariable Long id) {return new Gson() . toJson (userService. findOne(id));@RequestMapping ("/names/ {name}")public String findByName (@PathVariable String name) {return new Gson() . toJson (userService. findByName (name)) ;@RequestMapping("/list")public String findList() {return new Gson() . toJson (userService. findAll());@RequestMapping (value = "/page")public String findPage (Integer index, Integer size, String name, LongmerchantId) {try {UserQo userQo = new UserQo() ;if (Commonutils. isNotNull (index)) {userQo. setPage (index) ;if (CommonUtils. isNotNull (size)) {userQo.setSize (size) ;}if (CommonUtils. isNotNull (name)) {userQo. setName (name) ;if (CommonUtils. isNotNull (merchantId)) {MerchantQo merchantQo = new MerchantQo();merchantQo . setId (merchantId) ;userQo. setMerchant (merchantQo) ;Page users = userService. findAll (userQo) ; Map page = new HashMap<>() ;page.put ("content", users .getContent());page .put ("totalPages", users . getTotalPages();page.put ("totalelements", users . getTotalElements());return new Gson() . toJson(page) ;} catch (Exception e) {e. printStackTrace() ;return null ;}}
这些查询接口有单个对象查询、列表查询和分页查询等。因为是接口调用,所以查询的结果最终都是以JSON结构的方式返回文本数据。
如果要新建-一个商家用户,则可以使用POST方法实现,代码如下所示:
@RestControllerERequestMapping ("/user")public class UserControllerprivate static Logger logger =LoggerFactory . getLogger (UserController.class) ;@Autowiredprivate UserService userService;CRequestMapping (value=" /save", method = RequestMethod. POST)public String save (@RequestBody UserQo userQo) throws Exception{User user = CopyUtil. copy (userQo, User.class);List roleList = CopyUtil. copyList (userQo . getRoles(), Role.class);user.setRoles (roleList) ;user.setMerchant (CopyUtil. copy (userQo. getMerchant (),Merchant.class));String ret = userService. insert (user) ;logger. info("新增=" + ret) ;return ret;}}
当创建实体提交给数据服务进行处理时,必须将输入参数中的查询对象转化为实体,使用实体调用领域服务进行数据保存。并且在创建-一个商家用户实体时,为了保证商家用户的合法性,还必须指定用户的所属商家,并且给其分配一个角色,这样,这个商家用户才可以用来登录商家系统。
商家用户的更新设计可以使用PUT方法实现,代码如下所示:
@RestController@RequestMapping ("/user")public class UserControllerprivate static Logger logger =LoggerFactory.getLogger (UserController.class) ;@Autowi redprivate UserService userService;@RequestMapping (value=" /update", methodRequestMethod. PUT)public String update (@RequestBody UserQo userQo) throws Exception{User user = CopyUtil.copy (userQo, User. class);List roleList = CopyUtil.copyList (userQo.getRoles(), Role.class);user .setRoles (roleList) ;user . setMerchant (CopyUtil.copy (userQo. getMerchant (), Merchant.class));String ret = userService. update (user);logger. info("修改="+ ret) ;return ret;}}
商家用户的更新设计与创建一个商 家用户的实现方法相差不多,不同之处在于请求方法及传输的参数。
删除一个商家用户的设计可以使用DELETE方法实现,代码如下所示:
@RestController@RequestMapping (" /user")public class UserControllerprivate static Logger logger = LoggerFactory. getLogger (UserController .class) ;@Autowiredprivate UserService userService;@Reques tMapping (value="/delete/{id}",method = RequestMethod . DELETE)public String delete(@Pathvariable Long id) throws Exception {String ret = userService .delete(id) ;logger. info("删除=" + ret) ;return ret;}}
当要删除的实体具有关联关系时,则必须先删除它们之间的关联关系,然后才能执行删除操作。例如,在角色删除的设计中,使用了如下所示的设计: .
@RequestMapping (value="/delete/ {id}", method = RequestMethod. DELETE)public String delete (@PathVariable Long id) throws Exception {//让具有此角色的用户脱离关系List userList = userService. findByRoleId(id) ;if (userList != null && userList.size() > 0) {for(User user : userList) {for (Role role : user.getRoles()) {if(role.getId() .equals(id)) {user .getRoles() . remove (role) ;userService. update (user) ;break;}}}}//安全删除角色String ret = roleService.delete(id) ;logger. info("删除=" + ret) ;return ret;}
即在删除角色之前,要保证角色没有被用户关联。如果已经存在关联关系,则必须将这些关联关系删除之后,才能成功删除角色。
在完成接口开发之后,可以启动REST API应用,对一些查询接口可以使用浏览器进行-一个简单的测试。例如,对于用户信息的分页查询,可以使用如下所示的链接进行测试:
http://localhost: 9081/user/page
如果数据库中存在商家用户数据,则打开链接之后,可以看到如图10-3所示的JSON结构的数据。
对于上面设计的这些接口调用方法,我们都以FeignClient的方式进行了封装。更详细的信息可以参照前面章节中相关内容的说明。商家服务的接口调用设计,在模块merchant-client 中实现。在后面的开发中,我们只需在项目管理中配置模块merchant-client的依赖引用,就可以使用这些接口调用方法实现商家管理的各项功能设计了。
本文给大家讲解的内容商家管理后台与sso设计:商家管理微服务设计
- 下篇文章给大家讲解的是商家管理后台与sso设计: SSO设计;
- 觉得文章不错的朋友可以转发此文关注小编;
- 感谢大家的支持!