IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java Web 请求一个Controller 转发到另一个Controller 的三种解决方式总结(HandlerInterceptorAdapter Filter ModelAndView) -> 正文阅读

[Java知识库]Java Web 请求一个Controller 转发到另一个Controller 的三种解决方式总结(HandlerInterceptorAdapter Filter ModelAndView)

总思路

项目在一些特殊的情况下可能会将一个请求转发给另一个请求去处理,有可能是业务系统直接互相调用。也有可能第一个请求只做了转发不做实际的处理,第二个请求才去做实际的处理。也有可能两个i请求的处理方式都是由第二种给出的等等。

这里我的场景是做请求转发,实际处理依旧是第二个请求去处理。
这里通过资料查询以及实践给出三种请求转发的方式和案例:

一、HandlerInterceptorAdapter 方式(参考资料)

为了准确定位一些Controller的方法,我自定义了注解去判断是否需要执行转发逻辑,或者你也可以直接通过请求路径判断似乎做转发逻辑,示例如下:
我的注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NeedHandle {
}

我的 HandlerInterceptorAdapter 这里只用到了 preHandle 的处理 还有其他方法可以重写

preHandle 为进入实际请求controller 之前的自定义动作

import com.dtdream.dthink.dtalent.dmall.annotation.NeedHandle;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class OpenCheckInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        HandlerMethod handlerMethod = (HandlerMethod)handler;
        // 是否含有我指定的注解
        if (handlerMethod.hasMethodAnnotation(NeedHandle.class)){
            // 获取请求路径
            String requestURI = request.getRequestURI();
            // 含有需要更改的请求路径则需要更正路径  这里我将路径中的 /open  去除了
            String replacePath = requestURI.replace("/open", "");
            // 转发
            request.getRequestDispatcher(replacePath).forward(request, response);
        }
        // 最终放行请求
        return true;
    }

}

当然 如果为一般的 springMvc 你的这个类需要加入到对应xml 中或者直接使用 @Component 注解 将拦截器注入完成
使用注解时 如下:

@Component
public class OpenCheckInterceptor extends HandlerInterceptorAdapter {
   ..........
}

xml 方式如下:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

....................
.................... 其他
....................


    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.aurora.interceptor.HttpInterceptor"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.aurora.interceptor.OpenCheckInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

该方法实际在我的项目中前半段是生效的,但是转发时出现了问题,可能是由于项目框架较老而且内部对请求做了很多其他的特殊处理,实际我修改了部分代码如下 如果你也出现了问题可以参考我的其他思路

这里我替换了
String requestURI = request.getRequestURI(); 为 String requestURI = request.getRequestURL().toString();

实际测验后才进入了我想要进入的controller 中

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        HandlerMethod handlerMethod = (HandlerMethod)handler;
        // 是否含有我指定的注解
        if (handlerMethod.hasMethodAnnotation(NeedHandle.class)){
            // 获取请求路径
            String requestURI = request.getRequestURL().toString();  // 替换部分
            // 含有需要更改的请求路径则需要更正路径 这里我将路径中的 /open  去除了
            String replacePath = requestURI.replace("/open", "");
            // 转发
            request.getRequestDispatcher(replacePath).forward(request, response);
        }
        // 最终放行请求
        return true;
    }

二、Filter

Filte 过滤器的修改方式与上方第一个方法差不多 这里还有其他可重写方法,这里只用到了 doFilter
示例如下:
使用注解的方式:

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter(filterName = "myFilter", urlPatterns = {"/*"})
@Component
public class OpenCheckFilter implements Filter {


    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 不需要httpServletResponse 时可以不判断 HttpServletResponse 仅仅是为了保护
        if ((servletRequest instanceof  HttpServletRequest) && (servletResponse instanceof HttpServletResponse)){
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            // 不需要httpServletResponse 时可以不加
            HttpServletResponse response = (HttpServletResponse) servletResponse;             String requestURI = request.getRequestURI();
            if (requestURI.contains("/open/test")){
                // 含有需要更改的请求路径则需要更正路径
                String replacePath = requestURI.replace("/open", "");
                // 转发
                request.getRequestDispatcher(replacePath).forward(request, response);
            }
        }

        filterChain.doFilter(servletRequest, servletResponse);
    }
}

如果不使用注解的方式 则需要找 web.xml 中添加对应的 filter 类似如下:
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
.............
............. 其他
  <filter>
    <filter-name>openFilter</filter-name>
    <filter-class>com.dtdream.dthink.dtalent.dmall.filter.ReceiveManagerFilter</filter-class>
  </filter>
  
  <filter-mapping>
    <filter-name>openFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <!-- 可以有第二个Mapping 需要的话就加上 一般为一个-->
  <filter-mapping>
    <filter-name>openFilter</filter-name>
    <url-pattern>/api/v1/test/*</url-pattern>
  </filter-mapping>

</web-app>

但是在这里我遇到了和上面一样的问题,依旧失败没能进入目标 controller,所以采用了同样的修改方式

String requestURI = request.getRequestURI();
替换为
String requestURI = request.getRequestURL().toString();

如果遇到可以参考这样的方式;

三、ModelAndView

这个需要是 springframework(spring 框架) 才能使用
方式类似,但ModelAndView 中 View 指定了访问的地址或者资源路径,跳转路径,Model 即携带的参数
使用案例:
这里我重新定义了一个 controller

@RequestMapping("/open")
@RestController
public class OpenApiPathController {

    // 重定向
    private static final String REDIRECT_ ="redirect:";

    @GetMapping("/test/count")
    public ModelAndView messageCount(HttpServletRequest request, HttpServletResponse response){
        String replace = request.getRequestURL().toString().replace("/open/test/count", "/test/count");
        // 获取请求参数
        Map<String, String[]> parameterMap = request.getParameterMap();
        
        ModelAndView modelAndView = new ModelAndView();
        // 指定重定向的地址
        modelAndView.setViewName(REDIRECT_ + replace);
        // 同时携带请求的所有参数
        modelAndView.addAllObjects(parameterMap);
        return modelAndView;
    }

这里我使用 request.getRequestURL() 才最终成功,但也可以试试 request.getRequestURI() 搜寻的资料中大部分用的都是URI 可以成功,但我只有 URL时才成功。

redirect: + 请求 为固定写法 冒号( : )不可以省略
一般来说 redirect: 后默认携带/ 如果你的有问题可以携带 / 再次尝试一次
转发时可以使用 forward:

总结

拦截请求并转发请求可以使用 HandlerInterceptorAdapter,Filter,ModelAndView 三种方式或者其他
如果 request 获取的 requestURI 不能成功则尝试使用 requestURL 。转发请求 不是 forword(转发)就是redirect(重定向)

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-06-16 21:31:54  更:2022-06-16 21:33:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 18:31:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码