在简单的Spring云实施中,一台服务器上的gateway
应用控制着对其他服务器上运行的ui
个应用和resource
应用的访问。在简单的再现中,服务器使用localhost上的不同端口建模。可以通过ui
加载gateway
,但resource
应用会引发500 error
,然后通过{{1} gateway
应用调用localhost:8080/ui
以及通过localhost:9000
调用它时。 如何解决此500错误,以便在通过网关应用程序调用时在用户的浏览器中加载资源应用程序?
我不知道问题是在资源应用程序本身,还是在Spring云配置中,还是在Spring会话配置中,但我在三个非常简单的应用程序中创建了一个简单的问题再现,使用以下显式可在任何机器上轻松复制的步骤:
创建网关应用
首先,我将终端导航到eclipse工作区的根文件夹,然后输入:
# mkdir gateway
# chmod -R 777 gateway
# cd gateway
# curl https://cloud-start.spring.io/starter.tgz -d style=web -d style=security -d style=cloud-zuul -d name=gateway -d style=redis | tar -xzvf -
我再次导航到eclipse项目的根目录并再次键入chmod -R 777 gateway
。然后我将新项目导入eclipse,如下所示:
Eclipse > File > Import > Existing Maven Project > (navigate to the gateway directory)
接下来,我通过将GatewayApplication.java
更改为:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@SpringBootApplication
@EnableRedisHttpSession
@EnableZuulProxy
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
我为ui
和resource
定义了单独的路由,我还设置了网关来处理身份验证和会话,方法是将src/main/resources/application.properties
更改为以下内容:
zuul.routes.ui.url: http://localhost:8081
zuul.routes.resource.url: http://localhost:9000
security.user.password: password
security.sessions: ALWAYS
创建资源应用
然后我按以下步骤创建了资源应用程序。首先,我将终端导航到同一个eclipse工作区的根目录,然后输入以下内容:
# mkdir resource
# chmod -R 777 resource
# cd resource
# curl https://start.spring.io/starter.tgz -d style=web -d name=resource -d language=java | tar -xzvf -
我将自动生成的应用程序导入eclipse,如下所示:
Eclipse > Import > Existing Maven Project (navigate to resource folder just created)
我将以下内容添加到pom.xml
应用中的resource
:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
我尝试通过将com.example.ResourceApplication.java
更改为以下内容将resrouce应用程序连接到正在运行的Redis服务器:
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
@EnableRedisHttpSession
public class ResourceApplication {
@RequestMapping("/resource")
public Map<String,Object> home() {
Map<String,Object> model = new HashMap<String,Object>();
model.put("id", UUID.randomUUID().toString());
model.put("content", "Hello World");
return model;
}
public static void main(String[] args) {
SpringApplication.run(ResourceApplication.class, args);
}
}
我将应用程序配置为在端口9000上运行,并且永远不会创建自己的会话(从而将会话管理和身份验证推迟到网关,方法是将以下内容放入:src/main/resources/application.properties
:
server.port: 9000
security.sessions: NEVER
接下来,我将终端导航到资源应用程序的根目录,然后输入以下命令启动资源应用程序:
# mvn spring-boot:run
在一个单独的终端窗口中,我导航到网关应用程序的根目录并输入:
# mvn spring-boot:run
我创建并推出了ui
应用程序,我很乐意分享这些应用程序,但我在此省略了这一点以保持这一点。我认为通过在浏览器中输入以下两个网址,可以通过上述步骤重新处理错误:
localhost:8080/resource
localhost:9000
但上述网址中的两个导致500个错误。当我输入ui
时,localhost:8080/ui
ap(此处未显示)在浏览器中正确加载,但Firefox开发人员工具在500 error
调用中对resource
应用的调用显示相同的localhost:8080/ui
。我省略了ui
应用代码,因为我认为问题可以在没有它的情况下重新创建,我想保持这个简单。
那么如何更改上面的代码才能让resource
应用在localhost:8080/resource
正确加载?
稍后,我会担心锁定对网址的直接访问,并且只能访问ui应用。但就目前而言,我希望Spring cloud,Redis和Spring会话能够跨服务器处理身份验证。