当前位置: 首页 > 面试题库 >

如何使用嵌入式Tomcat 8和Spring Boot将子域转换为路径

赫连照
2023-03-14
问题内容

如何将子域重写为路径?

例:

  • foo.bar .example.com-> example.com / foo / bar

或更好的是(反向文件夹):

  • foo.bar .example.com-> example.com / bar / foo

请求 foo.bar .example.com应该将文件发送到/ src / main / resources / static / bar /
foo
/index.html中。

使用Apache2可以通过 mod_rewrite 完成。我找到了有关使用Tomcat
8
重写的文档,但问题是使用Spring
Boot将这些文件放在哪里?

更新资料

我尝试使用UrlRewriteFilter,但是似乎无法使用正则表达式替换在域路径中定义规则。

这是我的配置:

Maven依赖关系:

<dependency>
    <groupId>org.tuckey</groupId>
    <artifactId>urlrewritefilter</artifactId>
    <version>4.0.3</version>
</dependency>

Spring Java Config注册Servlet过滤器:

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application
{
    public static void main(String[] args)
    {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public FilterRegistrationBean filterRegistrationBean()
    {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();

        registrationBean.setFilter(new UrlRewriteFilter());
        registrationBean.addUrlPatterns("*");
        registrationBean.addInitParameter("confReloadCheckInterval", "5");
        registrationBean.addInitParameter("logLevel", "DEBUG");

        return registrationBean;
    }
}

*/ src / main / webapp / WEB-INF中的 *urlrewrite.xml

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE urlrewrite
    PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN"
    "http://www.tuckey.org/res/dtds/urlrewrite4.0.dtd">

<urlrewrite>
    <rule>
        <name>Translate</name>
        <condition name="host" operator="equal">foo.bar.example.com</condition>
        <from>^(.*)</from>
        <to type="redirect">example.com/bar/foo</to>
    </rule>
</urlrewrite>

使用此 硬编码 域,它可以工作,但它应适用于 每个 子域,如下所示。


问题答案:

创建您自己的过滤器。

该过滤器应:

  • 检查是否必须重写您的请求
  • 如果是,则重写URL和URI
  • 转发请求
  • 它再次通过相同的过滤器到达,但先检查将传递错误
  • 不要忘记,要小心打电话 chain.doFilter

转发不会更改浏览器中的任何URL。只需发送文件内容即可。

遵循代码可能是此类过滤器的实现。这不是任何干净的代码。只是快速而肮脏的工作代码:

@Component
public class SubdomainToReversePathFilter implements Filter {
    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
        final HttpServletRequest req = (HttpServletRequest) request;
        final String requestURI = req.getRequestURI();

        if (!requestURI.endsWith("/")) {
            chain.doFilter(request, response);
        } else {
            final String servername = req.getServerName();
            final Domain domain = getDomain(servername);

            if (domain.hasSubdomain()) {
                final HttpServletRequestWrapper wrapped = wrapServerName(req, domain);
                wrapped.getRequestDispatcher(requestURI + domain.getSubdomainAsPath()).forward(wrapped, response);
            } else {
                chain.doFilter(request, response);
            }
        }
    }

    private Domain getDomain(final String domain) {
        final String[] domainParts = domain.split("\\.");
        String mainDomain;
        String subDomain = null;

        final int dpLength = domainParts.length;
        if (dpLength > 2) {
            mainDomain = domainParts[dpLength - 2] + "." + domainParts[dpLength - 1];

            subDomain = reverseDomain(domainParts);
        } else {
            mainDomain = domain;
        }

        return new Domain(mainDomain, subDomain);
    }
    private HttpServletRequestWrapper wrapServerName(final HttpServletRequest req, final Domain domain) {
        return new HttpServletRequestWrapper(req) {
            @Override
            public String getServerName() {
                return domain.getMaindomain();
            }
            // more changes? getRequesetURL()? ...?
        };
    }

    private String reverseDomain(final String[] domainParts) {
        final List<String> subdomainList = Arrays.stream(domainParts, 0, domainParts.length - 2)//
                .collect(Collectors.toList());

        Collections.reverse(subdomainList);

        return subdomainList.stream().collect(Collectors.joining("."));
    }

    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }
}

这是Domain类:

public static class Domain {
    private final String maindomain;
    private final String subdomain;

    public Domain(final String maindomain, final String subdomain) {
        this.maindomain = maindomain;
        this.subdomain = subdomain;
    }

    public String getMaindomain() {
        return maindomain;
    }

    public String getSubdomain() {
        return subdomain;
    }

    public boolean hasSubdomain() {
        return subdomain != null;
    }

    public String getSubdomainAsPath() {
        return "/" + subdomain.replaceAll("\\.", "/") + "/";
    }
}

而且您需要一个能够捕获所有内容的控制器

@RestController
public class CatchAllController {

    @RequestMapping("**")
    public FileSystemResource deliver(final HttpServletRequest request) {
        final String file = ((String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));

        return new FileSystemResource(getStaticFile(file));
    }

    private File getStaticFile(final String path) {
        try {
            // TODO handle correct
            return new File(CatchAllController.class.getResource("/static/" + path + "/index.html").toURI());
        } catch (final Exception e) {
            throw new RuntimeException("not found");
        }
    }
}

我不确定是否有必要重写中的其他方法HttpServletRequestWrapper。这就是发表评论的原因。

另外,您还必须处理文件传递的情况(不存在,…)。



 类似资料:
  • 如何重写子域到路径? 示例: foo.barexample.com 最好是(反向文件夹): foo.barexample.com 请求foo。酒吧实例com应该在/src/main/resources/static/bar/foo/index中提供一个文件。html。 对于Apache2,它是由mod_rewrite完成的。我发现留档重写与Tomcat 8但问题是在哪里把这个文件使用Spring启

  • 如何配置应用程序,使每个客户端都有其上下文? 例子: 主要 客户1。domain.com 客户1 域名。com/Login-- 我当前的应用程序使用子域的配置,因为springboot本身标识它在不同的上下文中,但是我不明白如何通过路径来做到这一点

  • 我有时会在pom中看到以下声明。xml。。。 如您所见,sping-boo-starter-web被声明为tomcat-embed-jasper。 是不是sping-boo-starter-web已经有一个嵌入式tomcat了?为什么一些开发人员仍然声明tomcat-embed-jasper以及boot-starter-web?还是有什么原因?

  • 我正在尝试将文件的绝对值传递给类路径的read函数。 如果我将绝对路径与类路径一起传递,它就会很好地工作。但当我传递嵌入式表达式时,它不起作用 我的代码如下 给定url appServer给定参数creationMethod=“swagger_first”和路径“/integration/rest/rad” 和头X-CSRF-TOKEN=csrfToken*cookie JSESSIONID=JS

  • 当我试图使用ModelMapper将嵌套的java对象转换为嵌套的DTO时,我遇到了一个问题。在父DTO对象中,子DTO为null。以下是代码片段。 实体类: DTO的课程: 这是映射器代码: 输出: 输出用户DTO:UserDTO[名称=xyz,地址=null,产品=null] 在这里,我想将用户实体转换为UserDTO-dto。我得到了地址和产品DTO的空值。我在这里到底缺少什么?有人知道吗?

  • 如何使用用户指定的架构将dataframe转换为Avro格式?

  • 问题内容: 我在ttf文件中有一种字体,想要生成文本转换为路径的SVG。我不需要图像(因此使用imagettftext或Image Magick字体渲染功能是不够的),我需要可以放大和缩小的形状,我想丢失有关所用字体的信息,并且不想在其中引用它SVG文件(因此此处不能使用字体声明)。可能吗? 问题答案: 我创建了自己的类来处理SVG字体文件并将文本转换为字形。使用示例: 结果示例: 我班的代码:

  • 输入 JSON : 预期输出JSON: 目前,我正在使用JOLTtransformJSON处理器和JOLT规范: 但我得到的输出要么是NULL,要么是原始JSON(带有差异规范)。提前感谢。