嗨,我之前在服务器上有一个需要SSH连接的数据库。
为此,我按照此post的说明创建隧道和端口转发。
我没有做同样的事情,但我实现了这个class(我在没有所有对话框的情况下直接创建了..)
然后在我的application.properties中我有这一行:
spring.datasource.url = jdbc:mysql://localhost:3307/my_database?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
但是当我手动启动第一个类时,这个工作,然后我启动我的春季启动应用程序。
如何在应用程序启动此类之前自动执行此操作。
那是我的PortFrowarding类:
package com.demo.demo;
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/**
* This program will demonstrate the port forwarding like option -L of
* ssh command; the given port on the local host will be forwarded to
* the given remote host and port on the remote side.
* $ CLASSPATH=.:../build javac PortForwardingL.java
* $ CLASSPATH=.:../build java PortForwardingL
* You will be asked username, hostname, port:host:hostport and passwd.
* If everything works fine, you will get the shell prompt.
* Try the port on localhost.
*
*/
import com.jcraft.jsch.*;
import java.awt.*;
import javax.swing.*;
public class PortForwardingLR{
public static void main(String[] arg){
int lport;
String rhost;
int rport;
try{
JSch jsch=new JSch();
String host=null;
if(arg.length>0){
host=arg[0];
}
else{
host="demo@8.8.8.8";
}
String user=host.substring(0, host.indexOf('@'));
host=host.substring(host.indexOf('@')+1);
Session session=jsch.getSession(user, host, 22);
String foo="3307:8.8.8.8:3306";
lport=Integer.parseInt(foo.substring(0, foo.indexOf(':')));
foo=foo.substring(foo.indexOf(':')+1);
rhost=foo.substring(0, foo.indexOf(':'));
rport=Integer.parseInt(foo.substring(foo.indexOf(':')+1));
// username and password will be given via UserInfo interface.
UserInfo ui=new MyUserInfo();
session.setUserInfo(ui);
session.connect();
//Channel channel=session.openChannel("shell");
//channel.connect();
int assinged_port=session.setPortForwardingL(lport, rhost, rport);
System.out.println("localhost:"+assinged_port+" -> "+rhost+":"+rport);
}
catch(Exception e){
System.out.println(e);
}
}
public static class MyUserInfo implements UserInfo, UIKeyboardInteractive{
public String getPassword(){ return passwd; }
public boolean promptYesNo(String str){
// Object[] options={ "yes", "no" };
// int foo=JOptionPane.showOptionDialog(null,
// str,
// "Warning",
// JOptionPane.DEFAULT_OPTION,
// JOptionPane.WARNING_MESSAGE,
// null, options, options[0]);
// return foo==0;
return true;
}
String passwd;
// JTextField passwordField=(JTextField)new JPasswordField(20);
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){ return true; }
public boolean promptPassword(String message){
// Object[] ob={passwordField};
// int result=
// JOptionPane.showConfirmDialog(null, ob, message,
// JOptionPane.OK_CANCEL_OPTION);
// if(result==JOptionPane.OK_OPTION){
passwd="ItsNotMyPwd";
return true;
// }
// else{ return false; }
}
public void showMessage(String message){
JOptionPane.showMessageDialog(null, message);
}
final GridBagConstraints gbc =
new GridBagConstraints(0,0,1,1,1,1,
GridBagConstraints.NORTHWEST,
GridBagConstraints.NONE,
new Insets(0,0,0,0),0,0);
private Container panel;
public String[] promptKeyboardInteractive(String destination,
String name,
String instruction,
String[] prompt,
boolean[] echo){
panel = new JPanel();
panel.setLayout(new GridBagLayout());
gbc.weightx = 1.0;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridx = 0;
panel.add(new JLabel(instruction), gbc);
gbc.gridy++;
gbc.gridwidth = GridBagConstraints.RELATIVE;
JTextField[] texts=new JTextField[prompt.length];
for(int i=0; i<prompt.length; i++){
gbc.fill = GridBagConstraints.NONE;
gbc.gridx = 0;
gbc.weightx = 1;
panel.add(new JLabel(prompt[i]),gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weighty = 1;
if(echo[i]){
texts[i]=new JTextField(20);
}
else{
texts[i]=new JPasswordField(20);
}
panel.add(texts[i], gbc);
gbc.gridy++;
}
if(JOptionPane.showConfirmDialog(null, panel,
destination+": "+name,
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE)
==JOptionPane.OK_OPTION){
String[] response=new String[prompt.length];
for(int i=0; i<prompt.length; i++){
response[i]=texts[i].getText();
}
return response;
}
else{
return null; // cancel
}
}
}
}
我尝试在应用程序运行之前启动此方法并且它不起作用:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SymspringdemoApplication {
public static void main(String[] args) {
someMethodThatDoesForwarding();
SpringApplication.run(SymspringdemoApplication.class, args);
}
private static void someMethodThatDoesForwarding() {
PortForwardingLR.main(null);;
}
}
感谢。
答案 0 :(得分:1)
如果您实际发布了自己的代码,那么帮助/理解会更容易,但是如果您想在Spring启动之前建立端口转发它自己的引导,只需在Spring开始创建bean之前执行代码(最终与DB相关)豆)。
E.g:
...
/* Execute your custom port-forwarding here */
someMethodThatDoesForwarding();
/* SpringBoot code continues.. */
SpringApplication.run(DemoApplication.class, args);
...
答案 1 :(得分:1)
您有几种选择。
PortForwardingLR.main()
。PortForwardingLR
。您也可以使用OpenSSH进行端口转发。PortForwardingLR.main()
拨打主要方法。在我的选择中,最好将PortForwardingLR
中的代码重写为两种方法:一种用于打开连接,另一种用于关闭连接。目标是得到这样的东西:
class MyDatabaseWorker {
public void run() {
// Do stuff here
}
public static void main(String[] args) {
PortForwardingLR forwarder = new PortForwardingLR(hostname, user, password);
forwarder.addPortForward(3306);
forwarder.connect();
MyDatabaseWorker worker = new MyDatabaseWorker();
worker.run();
forwarder.disconnect();
}
}
这样,您可以为不同的项目重用PortForwardingLR类,您的数据库类受到最低程度的污染,并确保您的数据库类永远不会在没有端口转发的情况下运行。
但要小心,因为如果有另一个进程监听您要转发的端口,则此方案将失败。