jdk升级javaEE切换到spring mvc后path匹配问题

38 阅读1分钟

问题描述

使用spring-boot-migrator工具把项目从jdk8升级到jdk17后,controller中暴漏的rest接口从javaee切换为了springmvc,请求路径以/结尾的接口无法正常访问 比如一个Controller中有如下两个接口,在使用javaee时,/user/可以正常匹配到/user接口,但是切换到springmvc后,/user/调用方式只能匹配到/user/{id}接口


@RequestMapping(value = "/user/{id}", produces = JSON_UTF8, method = RequestMethod.GET)
public User find(@PathVariable("id") String id) {
    return super.find(id);
}

@Override
@RequestMapping(value = "/user",produces = JSON_UTF8, method = RequestMethod.GET)
public List<User> findAll() {
    return super.findAll();
}

解决方案

增加Filter,识别出以/结尾的请求url,修改url为截取/之前的内容

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;

import java.io.IOException;

public class PathModifyingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化代码(如果有的话)
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String requestURI = httpRequest.getRequestURI();

        if (requestURI.endsWith("/")) {
            // 创建一个包装器来修改请求URI
            HttpServletRequestWrapper modifiedRequest = new HttpServletRequestWrapper(httpRequest) {
                @Override
                public String getRequestURI() {
                    return requestURI.substring(0, requestURI.length() - 1);
                }

                @Override
                public StringBuffer getRequestURL() {
                    StringBuffer url = new StringBuffer(httpRequest.getScheme());
                    url.append("://");
                    url.append(httpRequest.getServerName());
                    if (httpRequest.getServerPort() != 80 && httpRequest.getServerPort() != 443) {
                        url.append(":").append(httpRequest.getServerPort());
                    }
                    url.append(getRequestURI());
                    return url;
                }
            };

            // 使用修改后的请求继续过滤链
            chain.doFilter(modifiedRequest, response);
        } else {
            // 如果路径不以/结尾,则直接继续过滤链
            chain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {
        // 销毁代码(如果有的话)
    }
}

把Filter注册到spring中


import jakarta.annotation.Resource;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class SpringWebConfig {
    @Bean
    public FilterRegistrationBean<PathModifyingFilter> registrationPathModifyingFilter() {
        return new FilterRegistrationBean<>(new PathModifyingFilter());
    }
}

这样,当请求/user/后实际会匹配到/user;/user/id会匹配到/user/{id}接口,保持和升级前行为一致。 实际上调用方请求/user接口时最后不应该带/,后续新接口需要规范调用