还原背景
大家都做过b-s架构的应用,也就是基于浏览器的软件应用。现在呢有个场景就是FE端也就是前端工程是前后端分离的,采用主流的前端框架VUE编写。服务端采用的是springBoot架构。
现在有另外一个服务也需要与前端页面交互,但是由于之前前端与服务端1交互时有鉴权与登录体系逻辑控制以及分布式session存储逻辑都在服务1中,没有把认证流程放到网关。所以新服务与前端交互则不想再重复编写一套鉴权认证逻辑。最终想通过服务1进行一个代理把前端固定的请求转发到新加的服务2上。
怎么实现
思路:客户端发送请求,由代理服务端通过匹配请求内容,然后在作为代理去访问真实的服务器,最后由真实的服务器将响应返回给代理,代理再返回给浏览器。
技术:说道反向代理,可能首先想到的就是nginx。不过在我们的需求中,对于转发过程有更多需求:
-
需要操作session,根据session的取值决定转发行为
-
需要修改Http报文,增加Header或是QueryString
第一点决定了我们的实现必定是基于Servlet的。springboot提供的ProxyServlet就可以满足我们的要求,ProxyServlet直接继承自HttpServlet,采用异步的方式调用内部服务器,因此效率上不会有什么问题,并且各种可重载的函数也提供了比较强大的定制机制。
实现过程
-
引入依赖
<dependency>
<groupId>org.mitre.dsmiley.httpproxy</groupId>
<artifactId>smiley-http-proxy-servlet</artifactId>
<version>1.11</version>
</dependency>
-
构建一个配置类
@Configuration
public class ProxyServletConfiguration {
private final static String REPORT_URL = "/newReport_proxy/*";
@Bean
public ServletRegistrationBean proxyServletRegistration() {
List<String> list = new ArrayList<>();
list.add(REPORT_URL); //如果需要匹配多个url则定义好放到list中即可
ServletRegistrationBean registrationBean = new ServletRegistrationBean();
registrationBean.setServlet(new ThreeProxyServlet());
registrationBean.setUrlMappings(list);
//设置默认网址以及参数
Map<String, String> params = ImmutableMap.of("targetUri", "null", "log", "true");
registrationBean.setInitParameters(params);
return registrationBean;
}
}
-
编写代理逻辑
public class ThreeProxyServlet extends ProxyServlet {
private static final long serialVersionUID = -9125871545605920837L;
private final Logger logger = LoggerFactory.getLogger(ThreeProxyServlet.class);
public String prox