Actual combat of springcloud microservice architecture: merchant management microservice design

Business management micro service design

Merchant management microservice is an independent RESTAPI application that provides functions of merchant information management, merchant authority management and menu resource management through interface services.

The development of merchant management micro service is implemented in the merchant RESTAPI module. For the dependency reference, configuration and startup program design of this type of module, please refer to the relevant instructions in the previous chapter on the development of RESTAPI micro service, which will not be repeated.

The merchant management micro service will directly call the domain service of the permission management model. Before calling, we can conduct a unit test on the domain service layer to verify the correctness of the program of the domain service layer. At the same time, an administrator user can also be generated through unit test to facilitate the later operation experience.

Business management service layer unit test

Firstly, in the merchant rest API module, test the services in various fields developed in Section 10.1, so as to comprehensively verify the development of the whole business field. These tests include the creation of each entity, data acquisition, object update, deletion and paging query.

The test cases for creating merchants and their user entities are as follows:

@RunWith (Spr ingRunner.class)
@ContextConfiguration(classes = {JpaConfiguration.class,
MerchantRestApiAppl ication.class})
@SpringBootTes t
public class UserTest {
private static Logger logger = LoggerFactory. getLogger (UserTest.class) ;
@Autowi red
private UserService userService;
@Autowired
private RoleService roleService;
@Autowired
private ResourceService resourceService;
CAutowired
private ModelService modelService;
CAutowired
private KindService kindService;
@Autowired
private MerchantService merchantService;
@Test
public void insertData() {
Kind kind = new Kind() ;
kind.setName("Merchant system");
kind. setLink ("merchantweb") ;
kindService. save (kind) ;
Assert .notNull (kind.getId(), "create kind error") ;
Model model = new Model () ;
model . setName("user management ") ;
model. setHost ("/user/ index") ;
model. setKind(kind) ;
modelService.save (model) ;
Assert. notNull (model.getId(),"create model error") ;
Resource resource = new Resource() ;
resource.setName("User modification");
resource.setUrl ("/user/edit/**") ;
resource . setModel (model) ;
resourceService. save (resource) ;
Assert. notNull (resource.getId(), "create resource error") ;
Role role = new Role() ;
role.setName("Merchant administrator");
List<Resource> 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 ("Test merchant") ;
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<Role> roles = new ArrayList<>() ;
roles.add(role) ;
user . setRoles (roles) ;
user . setMerchant (merchant) ;
userService. save (user) ;
Assert .notNull (user.getId(), "create user error");
}

}

In this test case, it includes the creation of all entities in the merchant business model, including classification, module, resource, role, merchant, user, etc. If the test passes, a three-level menu composed of categories, modules and resources can be generated, and a user entity with its own merchant, a role and relevant access rights to resources can be created at the same time. The user name and password of this user entity is "admin/123456". In the later development, we can use this user to log in to the system.

If the test fails, you can find the cause of the error in the relevant service components according to the error information prompted in the assertion.

The test cases for acquiring entities are as follows:

@Test
public void getData() {
User user = userService. findOne (1L) ;
Assert.notNull (user, "not find") ;
logger . info("====user==={}", new Gson() . toJson (user));
}

This test case obtains the user information through the user ID. if the test passes, it outputs the complete information of the user entity, including the user, the role owned by the user and the resources contained in the role.

The test of paging query is as follows:

@Test
public 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 merchant
merchantService. findOne (1L) ;
MerchantQo merchantQo = CopyUtil.copy (merchant, MerchantQo .class);
userQo. setMerchant (merchantQo) ;
Page<User> page = userService. findA1l (userQo) ;
Assert.notEmpty (page .getContent(), "list is empty");
List<User> list = page. getContent() ;
for(User user : list) {
logger. info("====user===={},", new Gson() .toJson(user));
}
}

This test case uses the query object UserQo to configure the parameters of paging query to execute paging query of user information.

In the query parameters, attributes such as creation date and merchant are set. After the query is successful, the information of each record will be output, including the user object, the role owned by the user, the resource associated with the role and the module to which the resource belongs.

Other tests related to update and deletion can be designed according to the above method.

Unit testing can be used as a means to verify the correctness of the program when packaging the project. If the test fails, the package cannot be successfully packaged. When Maven is used for project management, this function is turned on by default. If you want to perform tests when packaging is turned off, you can use the following configuration in your project:

<plugin>
<group Id>org. apache . maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<skipTests>true</skipTests>
</ configuration>
</plugin>

Interface development of merchant services

The REST API Application of business management includes the development of interfaces such as business information management, business user authority management and menu resource management. We use a RestController to implement the design of each interface. The design of these interfaces is basically the same. Let's take the design of user interface as an example.

The user's query interface is implemented using the GET method. The implementation methods of several query interfaces are as follows:

@RestController
@RequestMapping("/user")
public class UserController
private static Logger logger two LoggerFactory .getLogger (UserController.
class) ;
@Autowi red
private 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, Long
merchantId) {
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<User> users = userService. findAll (userQo) ; 
Map<String, object> 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 ;
}
}

These query interfaces include single object query, list query and paging query. Because it is an interface call, the query results will eventually return text data in the form of JSON structure.

If you want to create - a merchant user, you can use the POST method. The code is as follows:

@RestController
ERequestMapping ("/user")
public class UserController
private static Logger logger =
LoggerFactory . getLogger (UserController.class) ;
@Autowired
private UserService userService;
CRequestMapping (value=" /save", method = RequestMethod. POST)
public String save (@RequestBody UserQo userQo) throws Exception{
User user = CopyUtil. copy (userQo, User.class);
List<Role> 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("newly added=" + ret) ;
return ret;
}
}

When the created entity is submitted to the data service for processing, the query object in the input parameters must be transformed into an entity, and the entity calls the domain service to save the data. When creating - a merchant user entity, in order to ensure the legitimacy of the merchant user, the merchant to which the user belongs must be specified and assigned a role. In this way, the merchant user can be used to log in to the merchant system.

The update design of merchant users can be realized by PUT method, and the code is as follows:

@RestController
@RequestMapping ("/user")
public class UserController
private static Logger logger =
LoggerFactory.getLogger (UserController.class) ;
@Autowi red
private UserService userService;
@RequestMapping (value=" /update", method
RequestMethod. PUT)
public String update (@RequestBody UserQo userQo) throws Exception{
User user = CopyUtil.copy (userQo, User. class);
List<Role> 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("modify="+ ret) ;
return ret;
}
}

There is little difference between the update design of business users and the implementation method of creating a business user. The difference lies in the request method and transmission parameters.

Deleting the design of a merchant user can be realized by using the DELETE method. The code is as follows:

@RestController
@RequestMapping (" /user")
public class UserController
private static Logger logger = LoggerFactory. getLogger (UserController .
class) ;
@Autowired
private 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("delete=" + ret) ;
return ret;
}
}

When the entity to be deleted has an association relationship, the association relationship between them must be deleted before deleting. For example, in the design of role deletion, the following design is used:

@RequestMapping (value="/delete/ {id}", method = RequestMethod. DELETE)
public String delete (@PathVariable Long id) throws Exception {
//Disassociate users with this role
List<User> 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;
}
}
}
}
//Safely delete roles
String ret = roleService.delete(id) ;
logger. info("delete=" + ret) ;
return ret;
}

That is, before deleting a role, ensure that the role is not associated with the user. If there are already association relationships, you must delete them before you can successfully delete the role.

After completing the interface development, you can start the REST API Application, and use the browser to test some query interfaces - a simple test. For example, the paging query of user information can be tested with the following links:

http://localhost: 9081/user/page

If there is business user data in the database, after opening the link, you can see the data of JSON structure as shown in Figure 10-3.

For these interface call methods designed above, we have encapsulated them in the way of FeignClient. For more detailed information, please refer to the description of relevant contents in the previous chapter. The interface call design of merchant service is implemented in the module merchant client. We only need to use the merchant client management module to implement these functions in the merchant development module.

The content of this article is business management background and sso design: business management micro service design

  1. The next article will explain the business management background and SSO design: SSO design;
  2. Friends who think the article is good can forward this article and pay attention to the Xiaobian;
  3. Thank you for your support!

Keywords: Java Programming Programmer Spring Cloud architecture

Added by Flames on Tue, 15 Feb 2022 09:15:53 +0200