您的位置:首页 > 其它

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

2016-09-11 22:30 197 查看

一、背景介绍

在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博客。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息