У меня проблема с Java 8, MySQL Server 5.7.23, MySQL Connector для Java v5.1.45 и Tomcat v9.0.12 (работает на Ubuntu Server 18.04).
Я собралпростое Java-приложение (war), которое выполняет запрос в базе данных MySQL.
My context.xml (я поставил 2 узла ресурсов, один для производства и один для среды разработки), из сценария реального приложения Iпрочитав из CATALINA_OPTS параметр с именем "env" и прочитав его с помощью System.getProperty ("env"), приложение может выбрать соответствующий источник данных для использования.
<Context>
<!-- MySQL - Production -->
<Resource
name="prod-jdbc/ds-1" auth="Container"
type="javax.sql.DataSource" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/testdb?useSSL=false"
username="dbuser" password="dbUserPwd!"
autoReconnect="true" maxTotal="10"
minIdle="3" maxIdle="5" maxActive="10" maxWaitMillis="10000"
removeAbandonedOnBorrow="true" removeAbandonedOnMaintenance="true"
logAbandoned="true" removeAbandonedTimeout="1000"
closeMethod="close" testOnBorrow="true"
testWhileIdle="true" timeBetweenEvictionRunsMillis="60000"
validationQueryTimeout="10" validationInterval="6000"
validationQuery="SELECT 1"
/>
<!-- MySQL - Development -->
<Resource
name="dev-jdbc/ds-1" auth="Container"
type="javax.sql.DataSource" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/localdb?useSSL=false"
username="root" password="root"
autoReconnect="true" maxTotal="10"
minIdle="3" maxIdle="5" maxActive="10"
maxWaitMillis="10000" removeAbandonedOnBorrow="true"
removeAbandonedOnMaintenance="true" logAbandoned="true"
removeAbandonedTimeout="1000" closeMethod="close"
testOnBorrow="true" testWhileIdle="true"
timeBetweenEvictionRunsMillis="60000" validationQueryTimeout="10"
validationInterval="6000" validationQuery="SELECT 1"
/>
</Context>
Простой класс тестера:
package main;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.sql.DataSource;
import javax.ws.rs.core.Application;
public class ConnectionTester extends Application implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent arg0) {
Context ctx = null; Connection con = null; Statement stmt = null; ResultSet rs = null;
try{
ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:/comp/env/prod-jdbc/ds-1");
con = ds.getConnection();
stmt = con.createStatement();
rs = stmt.executeQuery("SELECT nome FROM Customers");
while(rs.next()) {
System.out.println(rs.getString("name"));
}
}
catch(NamingException | SQLException e){
e.printStackTrace();
}
finally{
try {
rs.close(); stmt.close(); con.close(); ctx.close();
} catch (SQLException e) {
System.out.println("Exception in closing DB resources");
} catch (NamingException e) {
System.out.println("Exception in closing Context");
}
}
} // contextInitialized
} // ConnectionTester
Я установил разрешение MySQL таким образом (мне также нужно разрешить внешний доступ для dbuser, потому что у меня есть внешний клиент, который подключается к этой базе данных MySQL):
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'veryStrongPwd';
CREATE USER 'dbuser'@'localhost' IDENTIFIED BY 'dbUserPwd!';
GRANT ALL PRIVILEGES ON *.* TO 'dbuser'@'localhost' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON *.* TO 'dbuser'@'%' IDENTIFIED BY 'dbUserPwd!' WITH GRANT OPTION;
FLUSH PRIVILEGES;
Tomcat неУ меня нет какой-либо конкретной конфигурации или настроенного ресурса, это просто v9.0.12, распакованный в папку.
Я попытался поместить в context.xml и учетные данные "root" и "dbuser"t когда я запускаю Tomcat, я получаю следующую проблему:
ConnectionPool.init Unable to create initial connections of pool.
java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:965)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:873)
at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1710)
at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1226)
...
И после выброса этих исключений он печатает набор записей, но зачем ему нужен root-доступ, даже если в context.xml я установил dbuserучетные данные?
Я прочитал поиск в StackOverflow и прочитал, что мне нужно проверить таблицу mysql.user, если я запущу:
SELECT user, host, plugin, authentication_string FROM mysql.user;
Я получаю это (столбец «plugin» имеет значение «mysql_native_password» для каждой записи):
![image](https://i.stack.imgur.com/1IHXR.png)
Если я пытаюсь войти на сервер MySQL из оболочки с помощью:
mysql -u root (or dbuser) -p
Я могу успешно войти в систему.
РЕДАКТИРОВАТЬ: я обнаружил, что при удалении второго узла «Ресурс» из context.xml (тот, который создан для среды разработки), проблема исчезает, но я все еще не понимаюпочему это происходит, потому что в поиске я выбираю ресурс prod (ctx.lookup ("java: / comp / env / prod-jdbc / ds-1")).
Чего мне не хватает?Заранее спасибо