二级域名接口分享(免费二级域名分发源码)

   360SEO    

在上文Spring MVC之RequestMappingHandlerMapping匹配中我们讲到,Spring在进行request匹配的时候,不仅会匹配url,method,contentType等条件,还会对用户提供的定制条件进行匹配,用户提供的定制条件是使用RequestCondition进行封装的。本文以本人工作的一个实际案例来讲解如果使用RequestCondition进行request的匹配过程进行定制,并且会对这种匹配过程需要注意的问题进行讲解。

1. 背景描述

本人从事的项目主要是售卖房源的,这里每个用户都有自己的网址,这些网址是通过二级域名的方式进行配置的,比如A用户的网址为a.house.com,B用户的网址为b.house.com。另外,我们也为每个用户提供了多套模板进行房源的展示。这种设计的优点在于用户如果需要将其网址进行SEO,那么可以通过统一的方式进行处理,并且通过二级域名我们就可以知道当前网站所属用户是谁。但这里存在的问题是,比如对于同一个页面的不同模板,虽然主体部分是相同的,但是页面细节上是有很大不同的,因而使用不同的接口对其进行处理是很有必要的,但是这样就需要前端每次在调用接口的时候判断当前用户是使用的哪一套模板,然后进行不同接口的调用。这样的话,后续随着模板页面越来越多,代码将变得极其难以维护。

为了解决上述问题,其实问题的根源在于将不同模板带来的复杂性引入到了前端,如果前端在请求同一页面时,无论当前用户是什么模板,都可以使用同一url进行请求,那么这种复杂性将会被屏蔽掉。那么这里需要解决的问题是,在前端通过某一域名链接,比如a.house.com/user/detail请求服务器时,服务器如何通过请求的域名来获取当前属于哪套模板,然后将请求分发到能处理当前模板的接口中。

这个问题其实就可以使用定制RequestCondition的方式进行。首先在服务器编写两个接口,这两个接口的签名完全一致,包括@RequestMapping注解中的属性,这两个接口我们会使用一个自定义的注解进行标注,注解参数值用来表示当前接口可以处理哪几套模板。在前端请求a.house.com/user/detail时,在自定义的RequestCondition中,首先会根据请求的域名获取当前是哪个用户和使用的是哪套模板,然后再获取当前RequestMappingInfo所表示的Handler(Controller中的某个处理请求的方法)所标注的自定义注解支持哪套模板,如果两者是匹配的,则说明当前Handler是可以处理当前请求的,这样就可以达到请求转发的目的。

2. 实现代码

这里我们首先展示目标接口的写法,从下面的代码可以看出,两个接口所使用的@RequestMapping中的参数是一模一样的,只是两个接口所使用的@Template注解的参数值不同,这样就达到了将不同模板的接口进行分离的目的,从而屏蔽了不同模板所造成的接口处理方式不同的复杂性,并且也提供了一个统一的请求方式,即/user/detail给前端,增强了前端代码的可维护性。如下是接口的具体声明:

关于@Template注解的声明,其比较简单,只需要指定其支持的模板即可:

前面我们讲到了,如果需要对RequestMappingHandlerMapping的匹配过程进行定制,则需要为每个注册的RequestMappingInfo注册一个RequestCondition对象。如下是该对象的声明方式:

上述就是对RequestMappingHandlerMapping的匹配过程进行定制的核心代码,这里主要需要关注的是getMatchingCondition()方法,该方法首先会获取当前请求的域名,然后与当前RequestMappingInfo所支持的templates进行比较,如果是其支持的,则返回当前ReqeustCondition对象,否则返回空。这需要说明的是,在进行RequestCondition与request匹配的时候,如果其getMatchingCondition()方法返回值不为空,则表示两者是匹配的,否则就是不匹配的。

关于RequestCondition的注入,我们需要重写RequestMappingHandlerMapping的getCustomMethodCondition()方法,在RequestMappingHandlerMapping扫描BeanFactory中所有的能处理请求的bean(Controller对象)的时候,其会将每个方法都声明为一个RequestMappingInfo对象,并且会调用RequestMappingHandlerMapping.getCustomMethodCondition()方法,获取当前RequestMappingInfo所注册的条件,默认情况下该方法返回值是null。如下是重写的RequestMappingHandlerMapping:

这里重写RequestMappingHandlerMapping其实就是自定义了一个HandlerMapping对象。Spring在初始化时,其会判断当前BeanFactory中是否存在HandlerMapping对象,如果有,则使用用户定义的,如果不存在,才会创建一个RequestMappingHandlerMapping用于处理请求。下面是Spring的xml文件的配置:

将上述代码使用Spring运行于tomcat容器中,然后访问分别http://a.house.com/user/detail?id=1和http://b.house.com/user/detail?id=1,可以看到控制台打印了如下日志:

这说明我们成功的对RequestMappingHandlerMapping的请求过程进行了定制。通过这种定制方式,我们有效的将不同模板所带来的请求方式的复杂性对前端进行了屏蔽,也将同一请求对不同模板的处理方式在后端进行了分离。

3. 注意点

关于RequestCondition的自定义,需要说明的主要有三点:

4. 小结

本文首先介绍了一个本人项目中使用多套模板时所存在的一个问题,然后介绍了使用RequestCondition处理该问题的解决思路,接着以代码的形式将解决方案进行了展示,最后介绍了使用RequestCondition时需要注意的问题。总的来说,本文以一个实际案例对如何定制RequestMappingHandlerMapping的匹配过程进行了讲解。

 标签:

评论留言

我要留言

欢迎参与讨论,请在这里发表您的看法、交流您的观点。