如何使用Spring Boot在H2控制台中设置默认的JDBC URL值 [英] How to set the default JDBC URL value in H2 console using spring boot

查看:119
本文介绍了如何使用Spring Boot在H2控制台中设置默认的JDBC URL值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已在春季启动时启用了H2控制台.但是,当我打开控制台连接页面时,默认URL是保存在H2控制台历史记录中的URL.如何在项目开始时配置项目以将URL填充为与 spring.datasource.url 相同的URL?目前,我在控制台中手动设置了url,但我想由项目本身自动设置它.

I have enable the H2 console in spring boot. However, when I open the console connection page the default url is the one staved in the H2 console history. How can i configure the project to populate the URL to be the same as spring.datasource.url on project start? Currently I set the url in the console manually but I would like to have it setup automatically by the project itself.

yaml:

spring:
  h2:
    console:
      enabled: true
      path: /admin/h2


  datasource:
    url: jdbc:h2:mem:foobar

更新: 我知道最后的连接设置已保存到〜/.h2.server.properties,但是我需要从启动应用程序中设置属性,可能会在其中几个之间切换

update: I know that the last connection settings are saved to ~/.h2.server.properties but what I need is to set the properties from the starting application potentially, potentially switching between several of them

推荐答案

没有提供用于填充设置的挂钩.

There is no hook provided to fill in settings.

好消息是我们可以用一些代码来更改它.

The good news is that we can change that with a bit of code.

当前状态

WebApp.index()

String[] settingNames = server.getSettingNames();
String setting = attributes.getProperty("setting");
if (setting == null && settingNames.length > 0) {
    setting = settingNames[0];
}
String combobox = getComboBox(settingNames, setting);
session.put("settingsList", combobox);
ConnectionInfo info = server.getSetting(setting);
if (info == null) {
    info = new ConnectionInfo();
}
session.put("setting", PageParser.escapeHtmlData(setting));
session.put("name", PageParser.escapeHtmlData(setting));
session.put("driver", PageParser.escapeHtmlData(info.driver));
session.put("url", PageParser.escapeHtmlData(info.url));
session.put("user", PageParser.escapeHtmlData(info.user));
return "index.jsp";

我们想点击server.getSettingNames(),并精确点击下面使用的server.getSettings().

We want to tap into server.getSettingNames(), and precisely into server.getSettings() used underneath.

synchronized ArrayList<ConnectionInfo> getSettings() {
    ArrayList<ConnectionInfo> settings = new ArrayList<>();
    if (connInfoMap.size() == 0) {
        Properties prop = loadProperties();
        if (prop.size() == 0) {
            for (String gen : GENERIC) {
                ConnectionInfo info = new ConnectionInfo(gen);
                settings.add(info);
                updateSetting(info);
            }
        } else {
            for (int i = 0;; i++) {
                String data = prop.getProperty(Integer.toString(i));
                if (data == null) {
                    break;
                }
                ConnectionInfo info = new ConnectionInfo(data);
                settings.add(info);
                updateSetting(info);
            }
        }
    } else {
        settings.addAll(connInfoMap.values());
    }
    Collections.sort(settings);
    return settings;
}

计划

  • 禁用H2ConsoleAutoConfiguration创建的ServletRegistrationBean<WebServlet>
  • 将其替换为带有WebServlet
  • 子类的config类
  • 我们的CustomH2WebServlet将覆盖init并注册CustomH2WebServer(WebServer的子类)
  • CustomH2WebServer中,我们将覆盖getSettings(),然后完成
  • disable ServletRegistrationBean<WebServlet> created by H2ConsoleAutoConfiguration
  • replace it with our config class with a subclass of WebServlet
  • our CustomH2WebServlet will override init and register CustomH2WebServer (subclass of WebServer)
  • in CustomH2WebServer we override getSettings() and we are done

代码

@EnableConfigurationProperties({H2ConsoleProperties.class, DataSourceProperties.class})
@Configuration
public class H2Config {

    private final H2ConsoleProperties h2ConsoleProperties;

    private final DataSourceProperties dataSourceProperties;

    public H2Config(H2ConsoleProperties h2ConsoleProperties, DataSourceProperties dataSourceProperties) {
        this.h2ConsoleProperties = h2ConsoleProperties;
        this.dataSourceProperties = dataSourceProperties;
    }

    @Bean
    public ServletRegistrationBean<WebServlet> h2Console() {
        String path = this.h2ConsoleProperties.getPath();
        String urlMapping = path + (path.endsWith("/") ? "*" : "/*");
        ServletRegistrationBean<WebServlet> registration = new ServletRegistrationBean<>(
                new CustomH2WebServlet(this.dataSourceProperties.getUrl()), urlMapping);
        H2ConsoleProperties.Settings settings = this.h2ConsoleProperties.getSettings();
        if (settings.isTrace()) {
            registration.addInitParameter("trace", "");
        }
        if (settings.isWebAllowOthers()) {
            registration.addInitParameter("webAllowOthers", "");
        }
        return registration;
    }
}

package org.h2.server.web;

import javax.servlet.ServletConfig;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Enumeration;

public class CustomH2WebServlet extends WebServlet {

    private final String dbUrl;

    public CustomH2WebServlet(String dbUrl) {
        this.dbUrl = dbUrl;
    }

    @Override
    public void init() {
        ServletConfig config = getServletConfig();
        Enumeration<?> en = config.getInitParameterNames();
        ArrayList<String> list = new ArrayList<>();
        while (en.hasMoreElements()) {
            String name = en.nextElement().toString();
            String value = config.getInitParameter(name);
            if (!name.startsWith("-")) {
                name = "-" + name;
            }
            list.add(name);
            if (value.length() > 0) {
                list.add(value);
            }
        }
        String[] args = list.toArray(new String[0]);
        WebServer server = new CustomH2WebServer(dbUrl);
        server.setAllowChunked(false);
        server.init(args);
        setServerWithReflection(this, server);
    }

    private static void setServerWithReflection(final WebServlet classInstance, final WebServer newValue) {
        try {
            final Field field = WebServlet.class.getDeclaredField("server");
            field.setAccessible(true);
            field.set(classInstance, newValue);
        }
        catch (SecurityException|NoSuchFieldException|IllegalArgumentException|IllegalAccessException ex) {
            throw new RuntimeException(ex);
        }
    }
}

package org.h2.server.web;

import java.util.ArrayList;
import java.util.Collections;

class CustomH2WebServer extends WebServer {

    private final String connectionInfo;

    CustomH2WebServer(String dbUrl) {

        this.connectionInfo = "Test H2 (Embedded)|org.h2.Driver|" +dbUrl+"|sa";
    }

    synchronized ArrayList<ConnectionInfo> getSettings() {
        ArrayList<ConnectionInfo> settings = new ArrayList<>();
        ConnectionInfo info = new ConnectionInfo(connectionInfo);
        settings.add(info);
        updateSetting(info);
        Collections.sort(settings);
        return settings;
    }
}

spring.h2.console.enabled=false
spring.datasource.url=jdbc:h2:mem:foobar

除了需要通过反射设置的一个私有字段之外,一切都变得很模糊.

Everything went smoolthly, except of one private field that needed to be set via reflection.

提供的代码适用于H2 1.4.199

The code provided works with H2 1.4.199

这篇关于如何使用Spring Boot在H2控制台中设置默认的JDBC URL值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆