电商系统店铺个性化域名实现

来源:互联网 发布:中美7.13南海对峙知乎 编辑:程序博客网 时间:2024/05/06 07:51

一、背景介绍

在C2C电商系统中,用户可以申请成为卖家,然后开设自己的店铺。为了更利于传播,让会员更容易记住,一般会设置店铺的个性域名。如:良品铺子在某猫的个性域名是:lppz.xxmall.com。

二、设计原理

在设计这套系统时,主要是通过设置域名的泛解析到二级或者三级域名,然后根据域名前缀,在程序中转换成对应的店铺id。从而完成个性化域名跳转到对应的店铺网站首页。

三、程序实现

1. 设置域名泛解析

假设域名是:abc.com,设置所有匹配*.m.abc.com的三级域名解析到服务器上,如下图:
这里写图片描述

2. 配置Nginx转发

这里将所有的域名,rewrite成指定的url前缀:/site/domain。domain代表*所匹配的三级域名,代码如下:

server {       listen      80;       server_name *.m.abc.cn;       #设置静态文件路径,不转发       location ~ ^/static/ {             root /webser/test/webapps/test-mobile;        }        #设置域名转发到固定URL:/site/domain       location / {            set $subdomain default;            if ( $http_host ~* "^(.*)\.m\.abc\.cn"){                set $subdomain $1;            }            rewrite ^/(.*)$ /site/$subdomain/$1 break;            proxy_pass http://localhost:8088;            proxy_set_header   Host    $host;            proxy_set_header   X-Real-IP   $remote_addr;            proxy_set_header   X-Forwarded-For             $proxy_add_x_forwarded_for;       }    }
3. 配置Controller

这里使用Spring-mvc做为mvc框架。首先定义一个Controller基类BaseController,所有的controller都继承它。

public class BaseController {}

再定义店铺的Controller类SiteController,拦截所有URL包含/site/domain的请求。这样配置的泛解析域名都会进入这个Controller

@Controller@RequestMapping("/site/{domain}")public class SiteController extends BaseController{}
3.1 实现域名转换成店铺id

方法一:在进入SiteController的某个方法后,通过@PathVariable注解,得到domain,然后在数据库中根据domain查询出对于的店铺id。

@Controller@RequestMapping("/site/{domain}")    @Autowired    private SiteService siteService;    @RequestMapping("/index")    public String index(@PathVariable String domain){        //得到店铺id        Site site = siteService.findSiteByDomain(domain);    }}

这样的写法有个问题,就是每个方法都要写这样的一段代码。假如我们可以在进入Controller某个方法前,就能通过domain得到店铺id,那就更好了。那么Spring-mvc中有没有在进入某个Controller的方法前执行的注解呢?

方法二:在Spring-mvc的注解中,有个注解会在进入Controller每个方法前执行。这个注解就是@ModelAttribute。被@ModelAttribute注释的方法会在此controller每个方法执行前被执行,因此对于一个controller映射多个URL的用法来说,要谨慎使用。
有了这个注解,我们可以在BaseController基类中,定义一个方法来实现域名转换成店铺id的操作。代码如下:

public class BaseController {    //定义店铺id    protected Long siteId = 0L;    @Autowired    private SiteService siteService;    /**     * @Title: getSiteId      * @Description: 将domain转换成店铺id     * @throws     */    @ModelAttribute    public void getSiteId(@PathVariable String domain,Model model,HttpServletRequest request,HttpServletResponse response){        Site site = siteService.findSiteByDomain(domain);        if(site != null){            siteId = site.getId();        }else{            throw new RuntimeException("域名不存在");        }    }}

在上面的代码中,我们定义了一个成员变量siteId,即店铺id,这样在所有继承BaseController的基类中,可以直接使用siteId来获取店铺的数据。
通过@ModelAttribute注解,在所有进入Controller方法前,将域名domain转换成店铺id即siteId。
这里店铺我是定义为Site对象,然后直接从数据库里查询得到。其实可以有优化的方案。通常店铺的个性域名不会随意更改,对于改动比较少的数据,我们可以在程序中缓存起来。所以可以将所有店铺对象和domain对应关系,通过key-value的形式,存在内存map或者redis中,这样获取店铺时,直接通过domain做为key,就可以得到site对象了。

通过这几步,即完成了类似淘宝店铺设置个性化域名的功能。
PS:这里只是提供了一种设计思路和简单的实现,在并发量上千万甚至更大的情况下,这块会更加复杂。如需了解更多,请加我个人微信:jerry0914,请备注csdn博客。

0 0
原创粉丝点击