Spring+zookeeper+dubbo to build the framework of micro-service project

Keywords: Programming xml Mybatis Zookeeper Dubbo

The whole project source code has been submitted to Github, you can see: Project source address

1. First of all, the project structure is built.

Hierarchical multi-module web project (micro-service architecture)
Spring MVC+Spring+mybatis-plus integrated redis

  • commons-parent is the version information of the maven jar package for the parent project management sub-project.
  • commons-util is a common type of storage module in a project.
  • commons-config is the storage module of general configuration files in the project
  • commons-manaeger is a microservice Cohesion Project

    • commons-mananger-dao dao layer code (persistence layer code is here, mybatis-plus Mapper is also here)
    • Storage module of commons-manager-interface interface class
    • Storage paths of commons-manager-model model and pojo types
    • commons-manager-service service service provider
    • Commons-manager-consumer of Web Services

The overall project catalog tree is shown above.
The specific process of project creation is not posted here. It's still very simple to build such a multi-module cohesive project using idea.

2. Start the corresponding pre-middleware service

Start sequence:

Because the project has integrated redis, it's better to start redis services before starting service providers and service subscribers.

After the redis service is started, the zookeeper registry needs to be opened. The zookeeper configuration uses the default port.

When the above two services are started, we can start the service provider project and the service subscriber project separately.

3. Start up service providers and subscribers

The service provider project is actually commons-manager-service. The main purpose of this project is to register the service interface of the project on zookeeper, so I use the main method to start it here. In fact, other ways can be used to start, but here for a simple demonstration, the main method is used;
We open the dubbo.test.DubboProviderTest class under the test file under the commons-manager-service directory:

Start the main method of this class.

If there is no error in the console, the project will start normally 1, and the service has been successfully registered with zookeeper.

To verify that we can use the dubbo-admin project to see if the service has really been successfully registered. Start the dubbo-admin project with tomcat.

Visit the dubbo-admin project and we can see that there is a service registration.

The service provider has already started successfully here.

Then let's start the service subscriber to access the services registered with zookeeper. Actually, the service subscriber is the project commons-manager-web. This is a web project. We just use tomcat to start it.

Similarly, if the console does not report an error, the boot is complete. Let's take a look at the consumer information of dubbo-admin.

You can see that consumers have already subscribed to the service.

So far we've got the project fully started. And the project already has code generated by mybatis-plus code generator based on some tables in the database. So we can call a service in the controller of commons-manager-web to verify whether the service can communicate properly and access the database to return data.
We use the ResourceController class to write a request method for validation:

Restart the service of the project and request through the browser: http://localhost:8080/resource/testResource

As you can see, the interface successfully returns the data queried by the database.

PS: mybatis-plus code generator, I have put it into the project commons-manager-dao, this code generator, I according to the code given by the official website, made some adjustments, so that the generator can generate relevant files according to the directory of multi-module projects, in addition to xml file generation, we need to manually move to the corresponding folder. Other files, mapper, model, service, controller, etc., can be built into the class of the code generator so that we don't have to move manually after generating the code. Specific code you can look at that class:

public class MybatisPlusUtils {

    public static void main(String[] args) {
        String[] models = {"commons-manager/commons-manager-dao", "commons-manager/commons-manager-pojo", "commons-manager/commons-manager-service",
                "commons-manager/commons-manager-interface", "commons-manager/commons-manager-web"};
        for (String model : models) {
            shell(model);
        }
    }

    private static void shell(String model) {
        File file = new File(model);
        String path = file.getAbsolutePath();
        System.out.println(path);
        //path = path.substring(0, path.lastIndexOf(File.separator));
        AutoGenerator mpg = new AutoGenerator();
        // Global configuration
        GlobalConfig gc = new GlobalConfig();
        gc.setOutputDir(path + "/src/main/java");
        gc.setFileOverride(true);
        gc.setActiveRecord(true);
        gc.setEnableCache(false);// XML secondary cache
        gc.setBaseResultMap(true);// XML ResultMap
        gc.setBaseColumnList(false);// XML columList
        gc.setAuthor("ChinPangLung");

        // Customize file naming. Note that% s automatically fills in table entity attributes!
        gc.setMapperName("%sMapper");
        gc.setXmlName("%sMapper");
        gc.setServiceName("I%sService");
        gc.setServiceImplName("I%sServiceImpl");
        gc.setControllerName("%sController");
        mpg.setGlobalConfig(gc);

        // Data source configuration
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setDbType(DbType.MYSQL);
        dsc.setTypeConvert(new MySqlTypeConvert() {
            // Custom database table field type conversion [optional]
            @Override
            public DbColumnType processTypeConvert(String fieldType) {
                System.out.println("Conversion type:" + fieldType);
                // Be careful!! ProceTypeConvert has a default type conversion. If you don't want the effect, please customize it and return it directly instead of as follows.
                return super.processTypeConvert(fieldType);
            }
        });
        dsc.setDriverName("com.mysql.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        dsc.setUrl("jdbc:mysql:///managerDB?characterEncoding=utf8");
        mpg.setDataSource(dsc);

        // Policy configuration
        StrategyConfig strategy = new StrategyConfig();
        // Strategy. setCapital Mode (true); // Global Capital Name ORACLE Note
//        strategy.setTablePrefix(new String[]{"tlog_", "tsys_"}); where you can modify your table prefix
        strategy.setNaming(NamingStrategy.underline_to_camel);// Table Name Generation Strategy
        strategy.setInclude(new String[]{"resource"}); // Tables to be generated
        // strategy.setExclude(new String[]{"test"}; // exclude generated tables
        // Customize entity parent class
        //strategy.setSuperEntityClass("com.spf.model.Entity");
        // Custom Entities, Common Fields
        //strategy.setSuperEntityColumns(new String[] { "test_id", "age" });
        // Custom mapper parent class
        // strategy.setSuperMapperClass("com.baomidou.demo.TestMapper");
        // Custom service parent class
        //strategy.setSuperServiceClass("com.baomidou.demo.TestService");
        // Implementing Class Parent Class with Custom service
        //strategy.setSuperServiceImplClass("com.baomidou.demo.TestServiceImpl");
        // Customize the controller parent class
        strategy.setSuperControllerClass("com.lung.common.controller.SuperController");
        // Does [entity] generate field constants (default false)
        // public static final String ID = "test_id";
        // strategy.setEntityColumnConstant(true);
        // Is [entity] the builder model (default false)
        // public User setName(String name) {this.name = name; return this;}
        // strategy.setEntityBuliderModel(true);
        mpg.setStrategy(strategy);

        // Packet configuration
        PackageConfig pc = new PackageConfig();
        pc.setParent("com.lung.application.test");
        pc.setController("controller");
        pc.setEntity("entity");
        pc.setMapper("mapper");
        pc.setService("api");
        pc.setServiceImpl("service");
        //pc.setModuleName("test");
        mpg.setPackageInfo(pc);

        // Inject custom configuration to use cfg.abc in VM
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
                this.setMap(map);
            }
        };

        // Custom xxList.jsp generation
        List<FileOutConfig> focList = new ArrayList<FileOutConfig>();
//    focList.add(new FileOutConfig("/template/list.jsp.vm") {
//       @Override
//       public String outputFile(TableInfo tableInfo) {
//          //Custom input file name
//          return "D://my_" + tableInfo.getEntityName() + ".jsp";
//       }
//    });
//    cfg.setFileOutConfigList(focList);
//    mpg.setCfg(cfg);

        // Demonstration of Adjusting xml Generation Directory
//        focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
//            @Override
//            public String outputFile(TableInfo tableInfo) {
//                return "/develop/code/xml/" + tableInfo.getEntityName() + ".xml";
//            }
//        });
//        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // Turn off the default xml generation and adjust the generation to the root directory
        TemplateConfig tc = new TemplateConfig();
        if ("commons-manager/commons-manager-dao".equals(model)) {
            tc.setController(null);
            tc.setEntity(null);
            tc.setService(null);
            tc.setServiceImpl(null);
//            tc.setXml(null);
        }
        /*else if ("commons-manager/commons-manager-service/src/main/resources/mapper".equals(model)) {
            PackageConfig packageInfo = mpg.getPackageInfo();
            packageInfo.setParent(null);
            packageInfo.setXml("xml");
            tc.setController(null);
            tc.setEntity(null);
            tc.setService(null);
            tc.setServiceImpl(null);
            tc.setMapper(null);
        }*/
        else if ("commons-manager/commons-manager-pojo".equals(model)) {
            tc.setController(null);
            tc.setService(null);
            tc.setServiceImpl(null);
            tc.setMapper(null);
            tc.setXml(null);
        } else if ("commons-manager/commons-manager-service".equals(model)) {
            tc.setController(null);
            tc.setMapper(null);
            tc.setService(null);
            tc.setXml(null);
            tc.setEntity(null);
        } else if ("commons-manager/commons-manager-interface".equals(model)) {
            tc.setController(null);
            tc.setMapper(null);
            tc.setServiceImpl(null);
            tc.setXml(null);
            tc.setEntity(null);
        } else if ("commons-manager/commons-manager-web".equals(model)) {
            tc.setMapper(null);
            tc.setXml(null);
            tc.setService(null);
            tc.setServiceImpl(null);
            tc.setEntity(null);
        }
        mpg.setTemplate(tc);

        // Custom template configuration, you can copy the source code mybatis-plus/src/main/resources/template below the content modification,
        // Place your own project in the src/main/resources/template directory. The default name can be either unconfigured or customized.
        // TemplateConfig tc = new TemplateConfig();
        // tc.setController("...");
        // tc.setEntity("...");
        // tc.setMapper("...");
        // tc.setXml("...");
        // tc.setService("...");
        // tc.setServiceImpl("...");
        // If an empty OR Null is set for any of the above modules, the module will not be generated.
        // mpg.setTemplate(tc);

        // Execution generation
        mpg.execute();

        // Print Injection Settings
        System.err.println(mpg.getCfg().getMap().get("abc"));
    }
}

Posted by sajy2k on Tue, 29 Jan 2019 15:57:16 -0800