diff --git a/README.md b/README.md index e9dc7d4aec47b105198ff26223525af94be23043..da4823b0c1e1cf36ba09a0986a37e1e7f1686d19 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,24 @@ This is a Dubbo-Go Project tool.
This Plugin is only for IntelliJ IDEA And GoLand. Which is base on Dubbo-Go and more flexible and convenient. Welcome to issue and PR. +## Feature | Feature | IDEA | GoLand | |:------------------:|:----:|:------:| | Hessian2 Generator | ✅️ | ✅️ | | New Project/Module | ✅️ | ✅️ | +### Project/Module Template +| Project/Module Template | Progress | +|:-----------------------:|:--------:| +| Sample | ✅️ | +| Empty Project | ✅️ | -| Project/Module Template | Progress | -|:------------------------------:|:--------:| -| Sample (client, server) | ✅️ | -| Empty Project (minimum import) | ✅️ | -| Dubbo + Gin | ⬜ | +#### Empty Project Template Middleware +| Middleware | Module | Support | +|:------------:|:-------------------------------------:|:-------:| +| Web Service | [Gin](github.com/gin-gonic/gin) | ✅️ | +| Memory Cache | [Redis](github.com/go-redis/redis/v8) | ✅️ | +| Database | [Gorm](gorm.io/gorm) | ✅️ | ## Install @@ -34,8 +41,11 @@ Restart IDE. ![](https://plugins.jetbrains.com/files/18581/screenshot_efb3cb95-ef25-44f5-8205-c19679ddff9d) #### 2. Choose Dubbo Go Project -![](https://plugins.jetbrains.com/files/18581/screenshot_29460bb0-c841-43e5-b408-fbab2854c7e5) +![](https://plugins.jetbrains.com/files/18581/screenshot_ef70924c-667f-4b50-8001-12c9ba93d5c2) +#### 3. Custom Config +* Select dubbo registry +* Add some middlewares ### Generate Hessian Register Statement Valid only in `*.go` files. diff --git a/build.gradle b/build.gradle index a79e6144d9fdbbe8cb48f9f11a2d4a2c82e79f72..efec8f2181ef5576d069a731be2c0f32863e0d08 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group 'com.chansos' -version '0.1.4' +version '0.2.1' repositories { mavenCentral() @@ -18,7 +18,7 @@ repositories { // See https://github.com/JetBrains/gradle-intellij-plugin/ intellij { version = '2021.3.2' -// plugins = ['org.intellij.intelliLang', 'com.intellij.java', 'com.intellij.java.ide'] +// type = 'IU' } patchPluginXml { @@ -27,7 +27,11 @@ patchPluginXml { - Add New Project New Project: - Add Sample Code Template - - Add Empty Project Template""" + - Add Empty Project Template + Empty Project: + - Dubbo Registry Config + - Middleware Config + """ version = project.version diff --git a/src/main/java/com/chansos/dubbogo/common/Registry.java b/src/main/java/com/chansos/dubbogo/common/Registry.java index 7a27fc5eb6e2094e42b967fad0cbae648949236d..08f41d1a66c160afee4514f1bc3a4d837a7aaa84 100644 --- a/src/main/java/com/chansos/dubbogo/common/Registry.java +++ b/src/main/java/com/chansos/dubbogo/common/Registry.java @@ -1,8 +1,8 @@ package com.chansos.dubbogo.common; public enum Registry { - zookeeper("zookeeper", "127.0.0.1:2181", true), - nacos("nacos", "127.0.0.1:8848", false); + Zookeeper("zookeeper", "127.0.0.1:2181", true), + Nacos("nacos", "127.0.0.1:8848", false); private final String name; private final String defaultAddress; @@ -28,13 +28,13 @@ public enum Registry { public static Registry parse(String name) { if (null == name) { - return zookeeper; + return Zookeeper; } for (Registry value : values()) { if (value.name().equals(name)) { return value; } } - return zookeeper; + return Zookeeper; } } diff --git a/src/main/java/com/chansos/dubbogo/project_generator/EmptyProjectGenerator.java b/src/main/java/com/chansos/dubbogo/project_generator/EmptyProjectGenerator.java index 730b406160fb3cc9cf4d0134ab039163560fa1e2..98b7f8544920a1993471b308c6fee1b69dd2d96f 100644 --- a/src/main/java/com/chansos/dubbogo/project_generator/EmptyProjectGenerator.java +++ b/src/main/java/com/chansos/dubbogo/project_generator/EmptyProjectGenerator.java @@ -1,5 +1,6 @@ package com.chansos.dubbogo.project_generator; +import com.chansos.dubbogo.ui.ComponentsGroup; import com.chansos.dubbogo.util.TemplateUtils; import com.intellij.openapi.project.Project; @@ -8,26 +9,84 @@ import java.util.List; import java.util.Map; public class EmptyProjectGenerator implements ProjectGenerator { + private final String basePath = "/project_template/empty_project"; private final List templateFiles = new ArrayList<>() {{ - String basePath = "/project_template/empty_project"; // Go Module add(new TemplateFileModel(basePath, "/mod", "/go.mod")); - // Dubbo Go Main - add(new TemplateFileModel(basePath, "/main", "/cmd/main.go")); + // Application main + add(new TemplateFileModel(basePath, "/cmd/main.go1", "/cmd/main.go")); - // Dubbo Go Config - add(new TemplateFileModel(basePath, "/config", "/conf/dubbogo.yaml")); + // Application config file + add(new TemplateFileModel(basePath, "/resources/application.yml", "/resources/application.yml")); + + // Application constant file + add(new TemplateFileModel(basePath, "/common/constant.go1", "/common/constant.go")); + // Application config loader + add(new TemplateFileModel(basePath, "/config/loader.go1", "/config/loader.go")); + // Application components + add(new TemplateFileModel(basePath, "/middleware/dubbo.go1", "/middleware/dubbo.go")); + add(new TemplateFileModel(basePath, "/middleware/init.go1", "/middleware/init.go")); + + // Dubbo Go Sample + add(new TemplateFileModel(basePath, "/service/api_ping.go1", "/service/api_ping.go")); + add(new TemplateFileModel(basePath, "/dto/api_ping.go1", "/dto/api_ping.go")); + add(new TemplateFileModel(basePath, "/service/dubbo_api_ping.go1", "/service/dubbo_api_ping.go")); // Project Run Configuration add(new TemplateFileModel(basePath, "/.run/main.run.xml", "/.run/main.run.xml")); }}; + // Web Service + private final List webServiceTemplateFiles = new ArrayList<>() {{ + add(new TemplateFileModel(basePath, "/middleware/router.go1", "/middleware/router.go")); + add(new TemplateFileModel(basePath, "/controller/api_home.go1", "/controller/api_home.go")); + }}; + + // Memory Cache + private final List memoryCacheTemplateFiles = new ArrayList<>() {{ + add(new TemplateFileModel(basePath, "/component/redis.go1", "/component/redis.go")); + add(new TemplateFileModel(basePath, "/middleware/redis.go1", "/middleware/redis.go")); + add(new TemplateFileModel(basePath, "/util/redis_util.go1", "/util/redis_util.go")); + }}; + + // Database + private final List databaseTemplateFiles = new ArrayList<>() {{ + add(new TemplateFileModel(basePath, "/component/database.go1", "/component/database.go")); + add(new TemplateFileModel(basePath, "/middleware/database.go1", "/middleware/database.go")); + }}; + + + private ComponentsGroup.ComponentConfigs components; + @Override public void generate(Project projectName, String path, Map args) { - for (TemplateFileModel templateFile : templateFiles) { + List allTemplateFile = new ArrayList<>(templateFiles); + ComponentsGroup.WebServiceConfig webServiceConfig = components.getWebServiceConfig(); + if (webServiceConfig != null) { + allTemplateFile.addAll(webServiceTemplateFiles); + args.put("${web-service-yml-config}", TemplateUtils.replaceContent(webServiceConfig.toString(), args)); + } else { + args.put("${web-service-yml-config}", ""); + } + ComponentsGroup.MemoryCacheConfig memoryCacheConfig = components.getMemoryCacheConfig(); + if (memoryCacheConfig != null) { + allTemplateFile.addAll(memoryCacheTemplateFiles); + args.put("${memory-cache-yml-config}", TemplateUtils.replaceContent(memoryCacheConfig.toString(), args)); + } else { + args.put("${memory-cache-yml-config}", ""); + } + ComponentsGroup.DatabaseConfig databaseConfig = components.getDatabaseConfig(); + if (databaseConfig != null) { + allTemplateFile.addAll(databaseTemplateFiles); + args.put("${database-yml-config}", TemplateUtils.replaceContent(databaseConfig.toString(), args)); + } else { + args.put("${database-yml-config}", ""); + } + + for (TemplateFileModel templateFile : allTemplateFile) { String content = TemplateUtils.readTemplate(templateFile.getTemplatePath()); if (content != null) { content = TemplateUtils.replaceContent(content, args); @@ -35,5 +94,21 @@ public class EmptyProjectGenerator implements ProjectGenerator { TemplateUtils.writeTemplate(templateFile.getTargetPath(), content); } } +// try { +// GeneralCommandLine go_mod_tidy = new GeneralCommandLine("go"); +// go_mod_tidy.withEnvironment("GO111MODULE", "on"); +// go_mod_tidy.withParameters("get", "-u", "dubbo.apache.org/dubbo-go/v3"); +// go_mod_tidy.setWorkDirectory(path); +// Process process = go_mod_tidy.createProcess(); +// process.waitFor(); +// System.out.println(process.exitValue()); +// } catch (Exception e) { +// e.printStackTrace(); +// } + } + + + public void setComponents(ComponentsGroup.ComponentConfigs components) { + this.components = components; } } diff --git a/src/main/java/com/chansos/dubbogo/project_generator/GoGenericTemplate.java b/src/main/java/com/chansos/dubbogo/project_generator/GoGenericTemplate.java index 0419c36d52bc2f8aa6dcbf7489a3149c3143c26a..5fb65591c541a8122752c76214e6853d4643ff9d 100644 --- a/src/main/java/com/chansos/dubbogo/project_generator/GoGenericTemplate.java +++ b/src/main/java/com/chansos/dubbogo/project_generator/GoGenericTemplate.java @@ -6,8 +6,8 @@ import javax.swing.*; import java.util.List; public enum GoGenericTemplate { - SampleCode("Sample Code (includes: client, server)", PluginIcons.Default_Template_Icon, new SampleCodeGenerator()), - EmptyProject("Empty Project (only import necessary packages)", PluginIcons.Default_Template_Icon, new EmptyProjectGenerator()), + EmptyProject("Empty Project", PluginIcons.Default_Template_Icon, new EmptyProjectGenerator()), + SampleCode("Sample Code", PluginIcons.Default_Template_Icon, new SampleCodeGenerator()), ; GoGenericTemplate(String name, Icon icon, ProjectGenerator generator) { diff --git a/src/main/java/com/chansos/dubbogo/project_generator/GoModuleBuilder.java b/src/main/java/com/chansos/dubbogo/project_generator/GoModuleBuilder.java index 41af14cb1a4354c39129f7413bbcb0578f85a568..1e29cddfdfd5208473af85b572ca1e467176e057 100644 --- a/src/main/java/com/chansos/dubbogo/project_generator/GoModuleBuilder.java +++ b/src/main/java/com/chansos/dubbogo/project_generator/GoModuleBuilder.java @@ -5,6 +5,7 @@ import com.chansos.dubbogo.util.ResourceUtils; import com.intellij.ide.util.projectWizard.ModuleWizardStep; import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.openapi.Disposable; +import com.intellij.openapi.module.Module; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.SdkTypeId; @@ -28,11 +29,11 @@ public class GoModuleBuilder extends com.intellij.ide.util.projectWizard.ModuleB @Override public boolean isSuitableSdkType(SdkTypeId sdkType) { - return false; + return true; } @Override - public void setupRootModel(@NotNull ModifiableRootModel modifiableRootModel) throws ConfigurationException { + public void setupRootModel(@NotNull ModifiableRootModel modifiableRootModel) { ContentEntry contentEntry = doAddContentEntry(modifiableRootModel); if (contentEntry == null) { return; @@ -50,15 +51,23 @@ public class GoModuleBuilder extends com.intellij.ide.util.projectWizard.ModuleB Project project = modifiableRootModel.getProject(); Map commonArgs = getDefaultArgs(rootPath, project); - template.getGenerator().generate(project, rootPath, commonArgs); + ProjectGenerator generator = template.getGenerator(); + if (generator instanceof EmptyProjectGenerator) { + ((EmptyProjectGenerator) generator).setComponents(moduleWizardStep.getComponents()); + } + generator.generate(project, rootPath, commonArgs); - ResourceUtils.updateProjectProperties(project); - ResourceUtils.updateModuleIml(modifiableRootModel.getModule().getModuleFilePath()); ResourceUtils.init(rootPath); VfsUtil.markDirtyAndRefresh(false, true, true, root); } + @Override + protected void setupModule(Module module) throws ConfigurationException { + module.setModuleType("WEB_MODULE"); + super.setupModule(module); + } + @NotNull private Map getDefaultArgs(String rootPath, Project project) { Map commonArgs = new HashMap<>(); diff --git a/src/main/java/com/chansos/dubbogo/project_generator/GoModuleType.java b/src/main/java/com/chansos/dubbogo/project_generator/GoModuleType.java index 9d7313caaafd6923bac3441e8414018353941ed9..1a4d614574e6634847f556ef135ab6073760edf9 100644 --- a/src/main/java/com/chansos/dubbogo/project_generator/GoModuleType.java +++ b/src/main/java/com/chansos/dubbogo/project_generator/GoModuleType.java @@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; public class GoModuleType extends com.intellij.openapi.module.ModuleType { - public static final String ID = "DUBBO_GO_MODULE"; + public static final String ID = "GO_MODULE"; public static final GoModuleType INSTANCE = (GoModuleType) ModuleTypeManager.getInstance().findByID(ID); protected GoModuleType() { @@ -16,22 +16,28 @@ public class GoModuleType extends com.intellij.openapi.module.ModuleType { + + private boolean useWebService; + private JTextField webServicePortText; + + private boolean useMemoryCache; + private JTextField memoryCacheAddressText; + private JTextField memoryCachePortText; + private JTextField memoryCachePasswordText; + private JTextField memoryCacheDefaultDBText; + + private boolean useDatabase; + private JBRadioButton mysql; + private JBRadioButton postgres; + private JTextField databaseAddressText; + private JTextField databasePortText; + private JTextField databaseNameText; + private JTextField databaseUsernameText; + private JTextField databasePasswordText; + + public ComponentsGroup() { + super(new FlowLayout(FlowLayout.LEFT)); + JBLabel label = new JBLabel("Middleware: "); + label.setPreferredSize(new Dimension(100, (int) label.getPreferredSize().getHeight())); + add(label); + + Box box = Box.createVerticalBox(); + + addWebService(box); + addRedisDriver(box); + addDatabaseDriver(box); + + add(box); + } + + private void addWebService(Box box) { + JBPanel panel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); + JBCheckBox checkBox = new JBCheckBox("Web service (Gin)"); + checkBox.setPreferredSize(new Dimension(170, (int) checkBox.getPreferredSize().getHeight())); + panel.add(checkBox); + + Box innerBox = Box.createVerticalBox(); + + JBPanel infoPanel; + { + infoPanel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); + JBLabel portLabel = new JBLabel("Port"); + portLabel.setPreferredSize(new Dimension(60, (int) portLabel.getPreferredSize().getHeight())); + infoPanel.add(portLabel); + webServicePortText = new JTextField(); + webServicePortText.setDocument(new PortInputDocument(webServicePortText)); + webServicePortText.setPreferredSize(new Dimension(64, 28)); + webServicePortText.setText("8280"); + infoPanel.add(webServicePortText); + innerBox.add(infoPanel); + } + + innerBox.setVisible(false); + checkBox.addChangeListener(e -> { + boolean enable = checkBox.isSelected(); + ComponentsGroup.this.useWebService = enable; + innerBox.setVisible(enable); + }); + panel.add(innerBox); + box.add(panel); + } + + private void addRedisDriver(Box box) { + JBPanel panel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); + JBCheckBox checkBox = new JBCheckBox("Memory cache (Redis)"); + checkBox.setPreferredSize(new Dimension(170, (int) checkBox.getPreferredSize().getHeight())); + panel.add(checkBox); + + Box innerBox = Box.createVerticalBox(); + innerBox.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, JBColor.GRAY)); + + JBPanel infoPanel; + { + infoPanel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); + JBLabel addressLabel = new JBLabel("Address"); + addressLabel.setPreferredSize(new Dimension(60, (int) addressLabel.getPreferredSize().getHeight())); + infoPanel.add(addressLabel); + memoryCacheAddressText = new JTextField(); + memoryCacheAddressText.setPreferredSize(new Dimension(140, 28)); + memoryCacheAddressText.setText("127.0.0.1"); + infoPanel.add(memoryCacheAddressText); + innerBox.add(infoPanel); + } + + { + infoPanel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); + JBLabel portLabel = new JBLabel("Port"); + portLabel.setPreferredSize(new Dimension(60, (int) portLabel.getPreferredSize().getHeight())); + infoPanel.add(portLabel); + memoryCachePortText = new JTextField(); + memoryCachePortText.setDocument(new PortInputDocument(memoryCachePortText)); + memoryCachePortText.setPreferredSize(new Dimension(64, 28)); + memoryCachePortText.setText("6379"); + infoPanel.add(memoryCachePortText); + innerBox.add(infoPanel); + } + + { + infoPanel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); + JBLabel passwordLabel = new JBLabel("Password"); + passwordLabel.setPreferredSize(new Dimension(60, (int) passwordLabel.getPreferredSize().getHeight())); + infoPanel.add(passwordLabel); + memoryCachePasswordText = new JTextField(); + memoryCachePasswordText.setPreferredSize(new Dimension(140, 28)); + memoryCachePasswordText.setText("root"); + infoPanel.add(memoryCachePasswordText); + innerBox.add(infoPanel); + } + + { + infoPanel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); + JBLabel dbLabel = new JBLabel("DB"); + dbLabel.setPreferredSize(new Dimension(60, (int) dbLabel.getPreferredSize().getHeight())); + infoPanel.add(dbLabel); + memoryCacheDefaultDBText = new JTextField(); + memoryCacheDefaultDBText.setPreferredSize(new Dimension(64, 28)); + memoryCacheDefaultDBText.setDocument(new PortInputDocument(memoryCacheDefaultDBText, 0, 15)); + memoryCacheDefaultDBText.setText("0"); + infoPanel.add(memoryCacheDefaultDBText); + innerBox.add(infoPanel); + } + + innerBox.setVisible(false); + checkBox.addChangeListener(e -> { + boolean enable = checkBox.isSelected(); + ComponentsGroup.this.useMemoryCache = enable; + innerBox.setVisible(enable); + }); + + panel.add(innerBox); + box.add(panel); + } + + private void addDatabaseDriver(Box box) { + JBPanel panel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); + JBCheckBox checkBox = new JBCheckBox("Database driver (Gorm)"); + checkBox.setPreferredSize(new Dimension(170, (int) checkBox.getPreferredSize().getHeight())); + panel.add(checkBox); + + Box innerBox = Box.createVerticalBox(); + innerBox.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, JBColor.GRAY)); + + JBPanel infoPanel; + { + infoPanel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); + JBLabel dialectLabel = new JBLabel("Dialect"); + dialectLabel.setPreferredSize(new Dimension(60, (int) dialectLabel.getPreferredSize().getHeight())); + infoPanel.add(dialectLabel); + ButtonGroup databaseDialectGroup = new ButtonGroup(); + mysql = new JBRadioButton("mysql", true); +// mysql.setPreferredSize(new Dimension(70, (int) mysql.getPreferredSize().getHeight())); + postgres = new JBRadioButton("postgres", false); +// postgres.setPreferredSize(new Dimension(70, (int) postgres.getPreferredSize().getHeight())); + databaseDialectGroup.add(mysql); + databaseDialectGroup.add(postgres); + infoPanel.add(mysql); + infoPanel.add(postgres); + innerBox.add(infoPanel); + } + + { + infoPanel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); + JBLabel addressLabel = new JBLabel("Address"); + addressLabel.setPreferredSize(new Dimension(60, (int) addressLabel.getPreferredSize().getHeight())); + infoPanel.add(addressLabel); + databaseAddressText = new JTextField(); + databaseAddressText.setPreferredSize(new Dimension(140, 28)); + databaseAddressText.setText("127.0.0.1"); + infoPanel.add(databaseAddressText); + innerBox.add(infoPanel); + } + + { + infoPanel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); + JBLabel portLabel = new JBLabel("Port"); + portLabel.setPreferredSize(new Dimension(60, (int) portLabel.getPreferredSize().getHeight())); + infoPanel.add(portLabel); + databasePortText = new JTextField(); + databasePortText.setDocument(new PortInputDocument(databasePortText)); + databasePortText.setPreferredSize(new Dimension(64, 28)); + databasePortText.setText("3306"); + infoPanel.add(databasePortText); + innerBox.add(infoPanel); + } + + { + infoPanel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); + JBLabel databaseLabel = new JBLabel("Database"); + databaseLabel.setPreferredSize(new Dimension(60, (int) databaseLabel.getPreferredSize().getHeight())); + infoPanel.add(databaseLabel); + databaseNameText = new JTextField(); + databaseNameText.setPreferredSize(new Dimension(140, 28)); + databaseNameText.setText(""); + infoPanel.add(databaseNameText); + innerBox.add(infoPanel); + } + + { + infoPanel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); + JBLabel usernameLabel = new JBLabel("Username"); + usernameLabel.setPreferredSize(new Dimension(60, (int) usernameLabel.getPreferredSize().getHeight())); + infoPanel.add(usernameLabel); + databaseUsernameText = new JTextField(); + databaseUsernameText.setPreferredSize(new Dimension(140, 28)); + databaseUsernameText.setText("root"); + infoPanel.add(databaseUsernameText); + innerBox.add(infoPanel); + } + + { + infoPanel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); + JBLabel passwordLabel = new JBLabel("Password"); + passwordLabel.setPreferredSize(new Dimension(60, (int) passwordLabel.getPreferredSize().getHeight())); + infoPanel.add(passwordLabel); + databasePasswordText = new JTextField(); + databasePasswordText.setPreferredSize(new Dimension(140, 28)); + databasePasswordText.setText("root"); + infoPanel.add(databasePasswordText); + innerBox.add(infoPanel); + } + + innerBox.setVisible(false); + checkBox.addChangeListener(e -> { + boolean enable = checkBox.isSelected(); + ComponentsGroup.this.useDatabase = enable; + innerBox.setVisible(enable); + }); + + panel.add(innerBox); + box.add(panel); + } + + static class PortInputDocument extends PlainDocument { + JTextField textField; + + private int min = 1; + private int max = 65535; + + public PortInputDocument(JTextField textField) { + this.textField = textField; + } + + public PortInputDocument(JTextField textField, int min, int max) { + this.textField = textField; + this.min = min; + this.max = max; + } + + public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { + if (textField.getText().length() >= 5) { + return; + } + char[] source = str.toCharArray(); + char[] result = new char[source.length]; + int j = 0; + + for (int i = 0; i < result.length; i++) { + if (Character.isDigit(source[i])) { + result[j++] = source[i]; + } else { + Toolkit.getDefaultToolkit().beep(); + } + } + super.insertString(offs, new String(result, 0, j), a); + + int port = Integer.parseInt(textField.getText()); + int port1 = Math.min(max, Math.max(min, port)); + if (port != port1) { + textField.setText(String.valueOf(port1)); + } + } + } + + public boolean isUseWebService() { + return useWebService; + } + + public static class WebServiceConfig { + private String port; + + public WebServiceConfig(String port) { + this.port = port; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + @Override + public String toString() { + return "server: # Web Service\n" + " host: 0.0.0.0\n" + " port: " + port + "\n"; + } + } + + public WebServiceConfig getWebServiceConfig() { + if (!isUseWebService()) { + return null; + } + return new WebServiceConfig(webServicePortText.getText()); + } + + public boolean isUseMemoryCache() { + return useMemoryCache; + } + + public static class MemoryCacheConfig { + private String address; + private String port; + private String password; + private String defaultDB; + + public MemoryCacheConfig(String address, String port, String password, String defaultDB) { + this.address = address; + this.port = port; + this.password = password; + this.defaultDB = defaultDB; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getDefaultDB() { + return defaultDB; + } + + public void setDefaultDB(String defaultDB) { + this.defaultDB = defaultDB; + } + + @Override + public String toString() { + return "redis: # Redis driver\n" + " host: " + address + "\n" + " port: " + port + "\n" + " password: " + password + "\n" + " defaultDb: " + defaultDB + "\n"; + } + } + + public MemoryCacheConfig getMemoryCacheConfig() { + if (!isUseMemoryCache()) { + return null; + } + return new MemoryCacheConfig(memoryCacheAddressText.getText(), memoryCachePortText.getText(), memoryCachePasswordText.getText(), memoryCacheDefaultDBText.getText()); + } + + public boolean isUseDatabase() { + return useDatabase; + } + + public static class DatabaseConfig { + private String dialect; + private String address; + private String port; + private String database; + private String username; + private String password; + + public DatabaseConfig(String dialect, String address, String port, String database, String username, String password) { + this.dialect = dialect; + this.address = address; + this.port = port; + this.database = database; + this.username = username; + this.password = password; + } + + public String getDialect() { + return dialect; + } + + public void setDialect(String dialect) { + this.dialect = dialect; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + public String getDatabase() { + return database; + } + + public void setDatabase(String database) { + this.database = database; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public String toString() { + return "database: # Database driver\n" + " dialect: " + dialect + "\n" + " host: " + address + "\n" + " port: " + port + "\n" + " database: ${project-name}-db\n" + " username: " + username + "\n" + " password: " + password + "\n"; + } + } + + public DatabaseConfig getDatabaseConfig() { + if (!isUseDatabase()) { + return null; + } + String dialect = mysql.isSelected() ? mysql.getText() : postgres.getText(); + return new DatabaseConfig(dialect, databaseAddressText.getText(), databasePortText.getText(), databaseNameText.getText(), databaseUsernameText.getText(), databasePasswordText.getText()); + } + + public static class ComponentConfigs { + private WebServiceConfig webServiceConfig; + private MemoryCacheConfig memoryCacheConfig; + private DatabaseConfig databaseConfig; + + public ComponentConfigs(WebServiceConfig webServiceConfig, MemoryCacheConfig memoryCacheConfig, DatabaseConfig databaseConfig) { + this.webServiceConfig = webServiceConfig; + this.memoryCacheConfig = memoryCacheConfig; + this.databaseConfig = databaseConfig; + } + + public WebServiceConfig getWebServiceConfig() { + return webServiceConfig; + } + + public void setWebServiceConfig(WebServiceConfig webServiceConfig) { + this.webServiceConfig = webServiceConfig; + } + + public MemoryCacheConfig getMemoryCacheConfig() { + return memoryCacheConfig; + } + + public void setMemoryCacheConfig(MemoryCacheConfig memoryCacheConfig) { + this.memoryCacheConfig = memoryCacheConfig; + } + + public DatabaseConfig getDatabaseConfig() { + return databaseConfig; + } + + public void setDatabaseConfig(DatabaseConfig databaseConfig) { + this.databaseConfig = databaseConfig; + } + } + + public ComponentConfigs getComponentConfigs() { + return new ComponentConfigs(getWebServiceConfig(), getMemoryCacheConfig(), getDatabaseConfig()); + } +} diff --git a/src/main/java/com/chansos/dubbogo/ui/GoNewProjectPanel.java b/src/main/java/com/chansos/dubbogo/ui/GoNewProjectPanel.java index 075f3b35daf2219ab639a6cc484b16d6ea73d12b..1c7135ce895e1a351c26585ede0ecc3ce7150ac0 100644 --- a/src/main/java/com/chansos/dubbogo/ui/GoNewProjectPanel.java +++ b/src/main/java/com/chansos/dubbogo/ui/GoNewProjectPanel.java @@ -10,8 +10,6 @@ import com.intellij.ui.components.JBScrollPane; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; import java.awt.*; import java.util.List; @@ -21,13 +19,8 @@ public class GoNewProjectPanel { private static final JBList templateList = new JBList<>(templateListModel) {{ setSelectionMode(ListSelectionModel.SINGLE_SELECTION); setSelectedIndex(0); - addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - GoNewProjectPanel.update(); - } - }); - setCellRenderer(new ColoredListCellRenderer() { + addListSelectionListener(e -> GoNewProjectPanel.update()); + setCellRenderer(new ColoredListCellRenderer<>() { @Override protected void customizeCellRenderer(@NotNull JList list, GoGenericTemplate value, int index, boolean selected, boolean hasFocus) { @@ -40,20 +33,25 @@ public class GoNewProjectPanel { }}; private static final RegistriesGroup registriesGroup = new RegistriesGroup(); + private static final ComponentsGroup componentsGroup = new ComponentsGroup(); - public final static JBPanel panel = new JBPanel() {{ + public final static JBPanel panel = new JBPanel<>() {{ setLayout(new BorderLayout()); JBLabel label = new JBLabel(); - label.setText("Dubbo Go Template"); + label.setText("Dubbo Go template"); label.setPreferredSize(new Dimension(320, 32)); add(label, BorderLayout.NORTH); JBScrollPane scrollablePanel = new JBScrollPane(templateList); add(scrollablePanel, BorderLayout.CENTER); - JBPanel bottom = new JBPanel(new BorderLayout()); + JBPanel bottom = new JBPanel<>(new BorderLayout()); bottom.add(registriesGroup, BorderLayout.NORTH); - add(bottom, BorderLayout.SOUTH); + componentsGroup.setVisible(false); + bottom.add(componentsGroup, BorderLayout.CENTER); + scrollablePanel = new JBScrollPane(bottom); + scrollablePanel.setPreferredSize(new Dimension((int) scrollablePanel.getPreferredSize().getWidth(), 400)); + add(scrollablePanel, BorderLayout.SOUTH); }}; public static GoGenericTemplate getSelection() { @@ -64,15 +62,11 @@ public class GoNewProjectPanel { return registriesGroup.getSelection(); } - private static void update() { - // TODO -// switch (getSelection()) { -// case SampleCode: -// break; -// case EmptyProject: -// break; -// default: -// break; -// } + public static ComponentsGroup.ComponentConfigs getComponents() { + return componentsGroup.getComponentConfigs(); + } + + public static void update() { + componentsGroup.setVisible(getSelection() == GoGenericTemplate.EmptyProject); } } diff --git a/src/main/java/com/chansos/dubbogo/ui/RegistriesGroup.java b/src/main/java/com/chansos/dubbogo/ui/RegistriesGroup.java index 7f9c32f959aead52e626bc81b2dbfa5f99d8d752..fcc18b6a339a12081fb4c2fe38acba3da1fae711 100644 --- a/src/main/java/com/chansos/dubbogo/ui/RegistriesGroup.java +++ b/src/main/java/com/chansos/dubbogo/ui/RegistriesGroup.java @@ -11,7 +11,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -public class RegistriesGroup extends JBPanel { +public class RegistriesGroup extends JBPanel { ButtonGroup registries = new ButtonGroup(); List options = new ArrayList<>() {{ @@ -22,11 +22,18 @@ public class RegistriesGroup extends JBPanel { public RegistriesGroup() { super(new FlowLayout(FlowLayout.LEFT)); - add(new JBLabel("Registry: ")); + JBLabel label = new JBLabel("Registry: "); + label.setPreferredSize(new Dimension(100, (int) label.getPreferredSize().getHeight())); + add(label); + + Box box = Box.createVerticalBox(); + JBPanel panel = new JBPanel<>(new FlowLayout(FlowLayout.LEFT)); for (JBRadioButton option : options) { registries.add(option); - add(option); + panel.add(option); } + box.add(panel); + add(box); } public void clear() { diff --git a/src/main/java/com/chansos/dubbogo/util/ResourceUtils.java b/src/main/java/com/chansos/dubbogo/util/ResourceUtils.java index 86e67c42f60cb05fd5060d1b829004ac6c85a1a7..674ff0eea912861aaf54c3e33e16149164857c41 100644 --- a/src/main/java/com/chansos/dubbogo/util/ResourceUtils.java +++ b/src/main/java/com/chansos/dubbogo/util/ResourceUtils.java @@ -1,12 +1,7 @@ package com.chansos.dubbogo.util; import com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.ide.util.PropertiesComponent; -import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.NotNull; -import java.io.BufferedWriter; -import java.io.FileWriter; import java.io.InputStream; public class ResourceUtils { @@ -18,29 +13,10 @@ public class ResourceUtils { return null; } - public static void updateProjectProperties(@NotNull Project project) { - PropertiesComponent service = project.getService(PropertiesComponent.class); - service.setValue("DefaultGoTemplateProperty", "Go File"); - service.setValue("go.format.on.save.advertiser.fired", "true"); - service.setValue("go.formatter.settings.were.checked", "true"); - service.setValue("go.import.settings.migrated", "true"); - service.setValue("go.sdk.automatically.set", "true"); - } - - public static void updateModuleIml(String path) { - try { - BufferedWriter os = new BufferedWriter(new FileWriter(path)); - os.write("\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""); - os.flush(); - os.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - public static void init(String path) { try { GeneralCommandLine go_mod_tidy = new GeneralCommandLine("go"); + go_mod_tidy.withEnvironment("GO111MODULE", "on"); go_mod_tidy.withParameters("mod", "tidy"); go_mod_tidy.setWorkDirectory(path); Process process = go_mod_tidy.createProcess(); diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 3fe45e9a2378d78058b29fd8c9b49c9eaa0ff101..8328f584dce67300dedf356e1e540f904b6d36d3 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -13,6 +13,8 @@

This is a Dubbo-Go Project tool.

This Plugin is only for IntelliJ IDEA And GoLand. Which is base on Dubbo-Go and more flexible and convenient. Welcome to issue and PR.

+

+Feature

@@ -34,6 +36,8 @@
+

+Project/Module Template

@@ -43,16 +47,40 @@ - + - + + +
Sample (client, server)Sample ✅️
Empty Project (minimum import)Empty Project ✅️
+

+Empty Project Template Middleware

+ + - - + + + + + + + + + + + + + + + + + + + +
Dubbo + GinMiddlewareModuleSupport
Web ServiceGin✅️
Memory CacheRedis✅️
DatabaseGorm✅️
@@ -86,7 +114,13 @@

2. Choose Dubbo Go Project

-

+

+

+3. Custom Config

+
    +
  • Select dubbo registry
  • +
  • Add some middlewares
  • +

Generate Hessian Register Statement

Valid only in *.go files.

@@ -119,7 +153,7 @@ - + diff --git a/src/main/resources/META-INF/pluginIcon.svg b/src/main/resources/META-INF/pluginIcon.svg index 4873f7cf3ada35eb8f46f2a1afb1e4ff05f3b7e0..646d01a566a395284a66e4714f01475a115ff0b2 100644 --- a/src/main/resources/META-INF/pluginIcon.svg +++ b/src/main/resources/META-INF/pluginIcon.svg @@ -1,7 +1,8 @@ - - - + - + - + diff --git a/src/main/resources/project_template/empty_project/cmd/main.go1 b/src/main/resources/project_template/empty_project/cmd/main.go1 new file mode 100644 index 0000000000000000000000000000000000000000..a817d1653a9054687f44034562425ddccba247c9 --- /dev/null +++ b/src/main/resources/project_template/empty_project/cmd/main.go1 @@ -0,0 +1,62 @@ +package main + +import ( + "os" + "os/signal" + "syscall" + "time" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/common/logger" +) + +import ( + "${project-name}/config" + "${project-name}/middleware" +) + +var ( + survivalTimeout = int(3e9) +) + +// export CONF_APPLICATION_FILE_PATH=${project-path}/resources/application.yml +func main() { + err := config.Load() // load application config + if err != nil { + logger.Error(err) + return + } + logger.Debug("Load application config complete.") + + err = middleware.Install() // boot application + if err != nil { + logger.Error(err) + return + } + + initSignal() // wait close signal +} + +func initSignal() { + signals := make(chan os.Signal, 1) + // It is not possible to block SIGKILL or syscall.SIGSTOP + signal.Notify(signals, os.Interrupt, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) + for { + sig := <-signals + logger.Infof("get signal %s", sig.String()) + switch sig { + case syscall.SIGHUP: + // reload() + default: + time.AfterFunc(time.Duration(survivalTimeout), func() { + logger.Warnf("app exit now by force...") + os.Exit(1) + }) + + // The program exits normally or timeout forcibly exits. + logger.Infof("provider app exit now...") + return + } + } +} diff --git a/src/main/resources/project_template/empty_project/common/constant.go1 b/src/main/resources/project_template/empty_project/common/constant.go1 new file mode 100644 index 0000000000000000000000000000000000000000..813611a40f4a519ddd5d51b21c52f572231cd30a --- /dev/null +++ b/src/main/resources/project_template/empty_project/common/constant.go1 @@ -0,0 +1,8 @@ +package common + +// System Config +const ( + ApplicationConfigFilePathKey = "CONF_APPLICATION_FILE_PATH" + DefaultApplicationConfigFilePath = "resources/application.yml" + DubboConfigFilePathKey = "DUBBO_GO_CONFIG_PATH" +) diff --git a/src/main/resources/project_template/empty_project/component/database.go1 b/src/main/resources/project_template/empty_project/component/database.go1 new file mode 100644 index 0000000000000000000000000000000000000000..aa51c1658e9b3f227e705ae7703f3ca79d652530 --- /dev/null +++ b/src/main/resources/project_template/empty_project/component/database.go1 @@ -0,0 +1,17 @@ +package component + +import ( + "gorm.io/gorm" +) + +var ( + DatabaseComponent = &databaseComponent{} +) + +type databaseComponent struct { + Db *gorm.DB +} + +func GetDatabase() *gorm.DB { + return DatabaseComponent.Db +} diff --git a/src/main/resources/project_template/empty_project/component/redis.go1 b/src/main/resources/project_template/empty_project/component/redis.go1 new file mode 100644 index 0000000000000000000000000000000000000000..c8f6842d922011e4238b8ad115b0d4c1b290d21f --- /dev/null +++ b/src/main/resources/project_template/empty_project/component/redis.go1 @@ -0,0 +1,43 @@ +package component + +import ( + "sync" +) + +import ( + "github.com/go-redis/redis/v8" +) + +import ( + "${project-name}/util" +) + +var ( + RedisComponent = &redisComponent{} +) + +type redisComponent struct { + sync.Mutex + + Addr string + Password string + MaxRetries int + + Redis *redis.Client + + DbMap map[int]*redis.Client +} + +func GetRedis() *redis.Client { + return RedisComponent.Redis +} + +func GetRedisByIndex(dbIndex int) *redis.Client { + RedisComponent.Lock() + if client, notNil := RedisComponent.DbMap[dbIndex]; !notNil || client == nil { + client = util.NewRedisDb(RedisComponent.Addr, RedisComponent.Password, dbIndex, RedisComponent.MaxRetries) + RedisComponent.DbMap[dbIndex] = client + } + RedisComponent.Unlock() + return RedisComponent.DbMap[dbIndex] +} diff --git a/src/main/resources/project_template/empty_project/config/loader.go1 b/src/main/resources/project_template/empty_project/config/loader.go1 new file mode 100644 index 0000000000000000000000000000000000000000..695872339b5577a6cfa7f0a16733a36908629f11 --- /dev/null +++ b/src/main/resources/project_template/empty_project/config/loader.go1 @@ -0,0 +1,137 @@ +package config + +import ( + "fmt" + "os" + "strconv" + "strings" + "time" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/common/logger" + "gopkg.in/yaml.v2" +) + +import ( + "${project-name}/common" +) + +type ApplicationConfig struct { + Server *ServerConfig `yaml:"server"` + Redis *RedisConfig `yaml:"redis"` + Database *Database `yaml:"database"` +} + +type ServerConfig struct { + Host string `yaml:"host"` + Port string `yaml:"port"` +} + +type RedisConfig struct { + Host string `yaml:"host"` + Port string `yaml:"port"` + Password string `yaml:"password"` + DefaultDB int `yaml:"defaultDb"` + MaxRetries int `yaml:"max_retries"` +} + +type Database struct { + Dialect string `yaml:"dialect"` + Host string `yaml:"host"` + Port string `yaml:"port"` + Database string `yaml:"database"` + Username string `yaml:"username"` + Password string `yaml:"password"` +} + +var ( + Config ApplicationConfig + + ClusterId int64 = 0 + ClusterStartTimestamp int64 = time.Now().UnixNano() + WorkerId int64 = 0 +) + +var ( + configPath string + dubboConfigPath string +) + +func getEnvAndTrim(key string) string { + return strings.TrimSpace(os.Getenv(key)) +} + +func presetEnv() { + configPath = getEnvAndTrim(common.ApplicationConfigFilePathKey) // 通过环境变量获取应用配置文件 + dubboConfigPath = getEnvAndTrim(common.DubboConfigFilePathKey) // Dubbo服务配置文件 + + if configPath == "" { + configPath = common.DefaultApplicationConfigFilePath // 默认配置文件 + } + if dubboConfigPath == "" { // 默认配置文件 + err := os.Setenv(common.DubboConfigFilePathKey, common.DefaultApplicationConfigFilePath) + if err != nil { + logger.Error(err) + } else { + dubboConfigPath = common.DefaultApplicationConfigFilePath + } + } +} + +func checkFile(path string, pathKey string) (file *os.File, err error) { + file, err = os.Open(path) + if err != nil { + logger.Error(err) + err = fmt.Errorf("环境变量[%s]所配置的文件地址[%s]不存在", pathKey, path) + } + return +} + +func Load() (err error) { + presetEnv() + + var configFile *os.File + configFile, err = checkFile(configPath, common.ApplicationConfigFilePathKey) + if err != nil { + return + } + err = yaml.NewDecoder(configFile).Decode(&Config) + if err != nil { + return + } + _, err = checkFile(dubboConfigPath, common.DubboConfigFilePathKey) + return +} + +func parseIntOrDefault(key string, getDef func() int64) int64 { + res, err := strconv.ParseInt(key, 10, 64) + if err == nil { + return res + } + return getDef() +} + +func parseK8sClusterIndex(k8sClusterId string) int64 { + return parseIntOrDefault(k8sClusterId, func() int64 { + return ClusterStartTimestamp % 3 + }) +} + +func parseK8sClusterStartTimestamp(k8sClusterStartTimestamp string) int64 { + return parseIntOrDefault(k8sClusterStartTimestamp, func() int64 { + return ClusterStartTimestamp + }) +} + +func parseK8sPodIndex(k8sPodName string) int64 { + keyIndex := strings.LastIndex(k8sPodName, "-") + getDef := func() int64 { + return ClusterStartTimestamp % 127 + } + if keyIndex > 0 && keyIndex+1 < len(k8sPodName) { + k8sPodIndex := k8sPodName[keyIndex+1:] + return parseIntOrDefault(k8sPodIndex, getDef) + } + return getDef() +} diff --git a/src/main/resources/project_template/empty_project/controller/api_home.go1 b/src/main/resources/project_template/empty_project/controller/api_home.go1 new file mode 100644 index 0000000000000000000000000000000000000000..5bf038e049adfb8ece92c55237371df1028d4310 --- /dev/null +++ b/src/main/resources/project_template/empty_project/controller/api_home.go1 @@ -0,0 +1,38 @@ +package controller + +import ( + "context" + "net/http" +) + +import ( + "github.com/gin-gonic/gin" + "dubbo.apache.org/dubbo-go/v3/common/logger" +) + +import ( + "${project-name}/dto" + "${project-name}/service" +) + +func ApiPingLocal(ctx *gin.Context) { + result := service.ApiPing() + ctx.JSON(http.StatusOK, gin.H{ + "result": result, + }) +} + +func ApiPingRemote(ctx *gin.Context) { + result, err := service.ApiPingService.Ping(context.Background(), &dto.ApiPingRequestDTO{}) + if err != nil { + logger.Errorf(err.Error()) + ctx.JSON(http.StatusOK, gin.H{ + "code": "ERROR", + }) + return + } + ctx.JSON(http.StatusOK, gin.H{ + "code": "SUCCESS", + "result": result, + }) +} diff --git a/src/main/resources/project_template/empty_project/dto/api_ping.go1 b/src/main/resources/project_template/empty_project/dto/api_ping.go1 new file mode 100644 index 0000000000000000000000000000000000000000..906aa426eefcbc0aa0045199fbe7340d23b8dd08 --- /dev/null +++ b/src/main/resources/project_template/empty_project/dto/api_ping.go1 @@ -0,0 +1,25 @@ +package dto + +import ( + hessian "github.com/apache/dubbo-go-hessian2" +) + +type ApiPingRequestDTO struct { +} + +func (*ApiPingRequestDTO) JavaClassName() string { + return "com.chansos.dubbogo.dto.ApiPingRequestDTO" +} + +type ApiPingResponseDTO struct { + Result string `json:"result"` +} + +func (*ApiPingResponseDTO) JavaClassName() string { + return "com.chansos.dubbogo.dto.ApiPingResponseDTO" +} + +func init() { + hessian.RegisterPOJO(&ApiPingRequestDTO{}) + hessian.RegisterPOJO(&ApiPingResponseDTO{}) +} diff --git a/src/main/resources/project_template/empty_project/main b/src/main/resources/project_template/empty_project/main deleted file mode 100644 index cb10cecaf2cf36344218ea6e130935053959ed8c..0000000000000000000000000000000000000000 --- a/src/main/resources/project_template/empty_project/main +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import ( - "dubbo.apache.org/dubbo-go/v3/common/logger" - "dubbo.apache.org/dubbo-go/v3/config" - _ "dubbo.apache.org/dubbo-go/v3/imports" -) - -// export DUBBO_GO_CONFIG_PATH= ${project-path}/conf/dubbogo.yaml -func main() { - if err := config.Load(); err != nil { - panic(err) - } - - logger.Info("start to dubbo") -} diff --git a/src/main/resources/project_template/empty_project/middleware/database.go1 b/src/main/resources/project_template/empty_project/middleware/database.go1 new file mode 100644 index 0000000000000000000000000000000000000000..d94bd923d1d7e712d89c1bef60efdcc8cda17e24 --- /dev/null +++ b/src/main/resources/project_template/empty_project/middleware/database.go1 @@ -0,0 +1,79 @@ +package middleware + +import ( + "fmt" + "log" + "os" + "time" +) + +import ( + "gorm.io/driver/mysql" + "gorm.io/driver/postgres" + "gorm.io/gorm" + "gorm.io/gorm/logger" + "gorm.io/gorm/schema" +) + +import ( + "${project-name}/component" + "${project-name}/config" +) + +var ( + db = &databaseComponent{} +) + +func init() { + registrySetup(db) +} + +type databaseComponent struct { +} + +func databaseLogger() logger.Interface { + return logger.New( + log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer + logger.Config{ + SlowThreshold: time.Second, // 慢 SQL 阈值 + LogLevel: logger.Info, // Log level + Colorful: false, // 禁用彩色打印 + }, + ) +} + +func (c *databaseComponent) Init() error { + dbConfig := config.Config.Database + dialect := dbConfig.Dialect + host := dbConfig.Host + port := dbConfig.Port + database := dbConfig.Database + username := dbConfig.Username + password := dbConfig.Password + var dialector gorm.Dialector + if dialect == "mysql" { + dialector = mysql.Open(fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&parseTime=True&loc=Local", + username, password, host, port, database)) + } else if dialect == "postgres" { + dialector = postgres.Open(fmt.Sprintf("user=%s password=%s host=%s port=%s DB.name=%s sslmode=disable TimeZone=Asia/Shanghai", + username, password, host, port, database)) + } + if dialector == nil { + return fmt.Errorf("无效的数据库配置") + } + db, err := gorm.Open(dialector, &gorm.Config{ + NamingStrategy: schema.NamingStrategy{ + SingularTable: true, + }, + Logger: databaseLogger(), + }) + if err != nil { + return err + } + component.DatabaseComponent.Db = db + return nil +} + +func (c *databaseComponent) Async() bool { + return false +} diff --git a/src/main/resources/project_template/empty_project/middleware/dubbo.go1 b/src/main/resources/project_template/empty_project/middleware/dubbo.go1 new file mode 100644 index 0000000000000000000000000000000000000000..eb1d1de6cec0d2a574dd46aa46a4f4a323b2c460 --- /dev/null +++ b/src/main/resources/project_template/empty_project/middleware/dubbo.go1 @@ -0,0 +1,55 @@ +package middleware + +import ( + "time" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/common/logger" + dubboConfig "dubbo.apache.org/dubbo-go/v3/config" + _ "dubbo.apache.org/dubbo-go/v3/imports" +) + +import ( + _ "${project-name}/dto" + _ "${project-name}/service" +) + +var ( + dubbo = &dubboComponent{} +) + +func init() { + registrySetup(dubbo) +} + +type dubboComponent struct { +} + +func (c *dubboComponent) Init() error { + initDubboService(func(err interface{}) { + if err != nil { + logger.Debug("Dubbo服务加载失败[5s后重试]") + time.Sleep(5 * time.Second) + _ = c.Init() + return + } + logger.Debug("Dubbo服务加载成功") + }) + return nil +} + +func initDubboService(hook func(interface{})) { + defer func() { + if err := recover(); err != nil { + hook(err) + } else { + hook(nil) + } + }() + _ = dubboConfig.Load() +} + +func (c *dubboComponent) Async() bool { + return true +} diff --git a/src/main/resources/project_template/empty_project/middleware/init.go1 b/src/main/resources/project_template/empty_project/middleware/init.go1 new file mode 100644 index 0000000000000000000000000000000000000000..be02d7f35c38605df54230e9eb4f9dc50f5cf7d2 --- /dev/null +++ b/src/main/resources/project_template/empty_project/middleware/init.go1 @@ -0,0 +1,40 @@ +package middleware + +import ( + "dubbo.apache.org/dubbo-go/v3/common/logger" +) + +var ( + setupComponents []SetupComponent +) + +type SetupComponent interface { + Init() error + + Async() bool +} + +func registrySetup(component SetupComponent) { + setupComponents = append(setupComponents, component) +} + +func Install() error { + var err error + for _, c := range setupComponents { + if c.Async() { + go func(c SetupComponent) { + e := c.Init() + if e != nil { + logger.Error(e) + } + }(c) + } else { + err = c.Init() + if err != nil { + logger.Error(err) + return err + } + } + } + return nil +} diff --git a/src/main/resources/project_template/empty_project/middleware/redis.go1 b/src/main/resources/project_template/empty_project/middleware/redis.go1 new file mode 100644 index 0000000000000000000000000000000000000000..39a720dfbf334aded84000a468e00fa4cf839ca6 --- /dev/null +++ b/src/main/resources/project_template/empty_project/middleware/redis.go1 @@ -0,0 +1,45 @@ +package middleware + +import ( + "fmt" +) + +import ( + "github.com/go-redis/redis/v8" +) + +import ( + "${project-name}/component" + "${project-name}/config" + "${project-name}/util" +) + +var ( + rds = &redisComponent{} +) + +func init() { + registrySetup(rds) +} + +type redisComponent struct { +} + +func (c *redisComponent) Init() error { + rdConfig := config.Config.Redis + component.RedisComponent.Addr = fmt.Sprintf("%s:%s", rdConfig.Host, rdConfig.Port) + component.RedisComponent.Password = rdConfig.Password + component.RedisComponent.MaxRetries = rdConfig.MaxRetries + + component.RedisComponent.DbMap = make(map[int]*redis.Client) + + dbIndex := rdConfig.DefaultDB + defaultClient := util.NewRedisDb(component.RedisComponent.Addr, component.RedisComponent.Password, dbIndex, component.RedisComponent.MaxRetries) + component.RedisComponent.Redis = defaultClient + component.RedisComponent.DbMap[dbIndex] = defaultClient + return nil +} + +func (c *redisComponent) Async() bool { + return false +} diff --git a/src/main/resources/project_template/empty_project/middleware/router.go1 b/src/main/resources/project_template/empty_project/middleware/router.go1 new file mode 100644 index 0000000000000000000000000000000000000000..5b9e32a790b1bab7e933c7594d16e7bc19719ef0 --- /dev/null +++ b/src/main/resources/project_template/empty_project/middleware/router.go1 @@ -0,0 +1,49 @@ +package middleware + +import ( + "fmt" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/common/logger" + "github.com/gin-gonic/gin" +) + +import ( + "${project-name}/config" + "${project-name}/controller" +) + +var ( + router = &routerComponent{} +) + +func init() { + registrySetup(router) +} + +type routerComponent struct { + Router *gin.Engine +} + +func (c *routerComponent) Init() error { + routerEngine := gin.New() + + apiGroup := routerEngine.Group("/api") + apiGroup.GET("/ping/local", controller.ApiPingLocal) + apiGroup.GET("/ping/remote", controller.ApiPingRemote) + + serverConfig := config.Config.Server + err := routerEngine.Run(fmt.Sprintf("%s:%s", serverConfig.Host, serverConfig.Port)) + if err != nil { + logger.Error(err) + return err + } + + c.Router = routerEngine + return nil +} + +func (c *routerComponent) Async() bool { + return false +} diff --git a/src/main/resources/project_template/empty_project/mod b/src/main/resources/project_template/empty_project/mod index e6c32121573d5ea0475e4e498d37771b61a7a531..80eec2d3a27f14c799e74118dca666228a15e215 100644 --- a/src/main/resources/project_template/empty_project/mod +++ b/src/main/resources/project_template/empty_project/mod @@ -1,7 +1,12 @@ module ${project-name} require ( - dubbo.apache.org/dubbo-go/v3 v3.0.0 - github.com/dubbogo/grpc-go v1.42.7 - github.com/dubbogo/triple v1.1.7 + dubbo.apache.org/dubbo-go/v3 v3.0.1 + github.com/apache/dubbo-go-hessian2 v1.11.0 + github.com/gin-gonic/gin v1.7.7 + github.com/go-redis/redis/v8 v8.11.4 + gopkg.in/yaml.v2 v2.4.0 + gorm.io/driver/mysql v1.3.2 + gorm.io/driver/postgres v1.3.1 + gorm.io/gorm v1.23.1 ) diff --git a/src/main/resources/project_template/empty_project/config b/src/main/resources/project_template/empty_project/resources/application.yml similarity index 36% rename from src/main/resources/project_template/empty_project/config rename to src/main/resources/project_template/empty_project/resources/application.yml index 83967e28f1da862744e2c96c406ce6d4ddbe84c4..c010310c8f3bdc23fc2355937bfd124a51c9eb15 100644 --- a/src/main/resources/project_template/empty_project/config +++ b/src/main/resources/project_template/empty_project/resources/application.yml @@ -1,4 +1,10 @@ -dubbo: +${web-service-yml-config} + +${memory-cache-yml-config} + +${database-yml-config} + +dubbo: # Dubbo Go Service registries: ${project-name}: protocol: ${registry-protocol} @@ -7,10 +13,20 @@ dubbo: group: DEFAULT_GROUP namespace: public protocols: - triple: - name: tri + dubbo: + name: dubbo port: 20000 consumer: references: + ApiPingConsumer: + protocol: dubbo + interface: com.chansos.dubbogo.service.ApiPingService + version: 1.0.0 + group: dubbo-go provider: services: + ApiPingProvider: + protocol: dubbo + interface: com.chansos.dubbogo.service.ApiPingService + version: 1.0.0 + group: dubbo-go diff --git a/src/main/resources/project_template/empty_project/service/api_ping.go1 b/src/main/resources/project_template/empty_project/service/api_ping.go1 new file mode 100644 index 0000000000000000000000000000000000000000..26200a10f884488dcd1f0fc823fa6fc4a1f369bc --- /dev/null +++ b/src/main/resources/project_template/empty_project/service/api_ping.go1 @@ -0,0 +1,5 @@ +package service + +func ApiPing() string { + return "pong" +} diff --git a/src/main/resources/project_template/empty_project/service/dubbo_api_ping.go1 b/src/main/resources/project_template/empty_project/service/dubbo_api_ping.go1 new file mode 100644 index 0000000000000000000000000000000000000000..d05af80de4fa14b7fbddb684be92c1a0e36dfd22 --- /dev/null +++ b/src/main/resources/project_template/empty_project/service/dubbo_api_ping.go1 @@ -0,0 +1,51 @@ +package service + +import ( + "context" + "fmt" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/config" +) + +import ( + "${project-name}/dto" +) + +var ApiPingService = &ApiPingConsumer{} + +type ApiPingProvider struct { +} + +func (*ApiPingProvider) MethodMapper() map[string]string { + return map[string]string{ + "Ping": "ping", + } +} + +func (*ApiPingProvider) Ping(ctx context.Context, req *dto.ApiPingRequestDTO) (*dto.ApiPingResponseDTO, error) { + if req == nil { + return nil, fmt.Errorf("Invalid parameter") + } + return &dto.ApiPingResponseDTO{ + Result: ApiPing(), + }, nil +} + +func (*ApiPingProvider) Reference() string { + return "ApiPingProvider" +} + +type ApiPingConsumer struct { + Ping func(ctx context.Context, req *dto.ApiPingRequestDTO) (*dto.ApiPingResponseDTO, error) `dubbo:"ping"` +} + +func (*ApiPingConsumer) Reference() string { + return "ApiPingConsumer" +} + +func init() { + config.SetProviderService(&ApiPingProvider{}) + config.SetConsumerService(ApiPingService) +} diff --git a/src/main/resources/project_template/empty_project/util/redis_util.go1 b/src/main/resources/project_template/empty_project/util/redis_util.go1 new file mode 100644 index 0000000000000000000000000000000000000000..873caba32a26be8a369cdd8366d81babb06ad932 --- /dev/null +++ b/src/main/resources/project_template/empty_project/util/redis_util.go1 @@ -0,0 +1,15 @@ +package util + +import ( + "github.com/go-redis/redis/v8" +) + +func NewRedisDb(addr, password string, db, maxRetries int) *redis.Client { + client := redis.NewClient(&redis.Options{ + Addr: addr, + Password: password, + DB: db, + MaxRetries: maxRetries, + }) + return client +} diff --git a/static/new_project_1.jpg b/static/new_project_1.jpg index e2c027056115f1cc0b471cbfbc39d6053ff6d7b6..629650d5b44db2025200403f590b64ef6d4476d3 100644 Binary files a/static/new_project_1.jpg and b/static/new_project_1.jpg differ