YONGFEIUALL

izheyi.com


  • Home

  • Archives

  • Categories

  • Tags

  • About

  • Search

Dubbo

Posted on 2018-08-11 | In Distribution |

Dubbo是一款分布式服务框架,高性能和透明化的RPC远程服务调用方案。

Dubbo采用全spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可。

Dubbo架构:

  • Provider: 暴露服务的服务提供方。
  • Consumer: 调用远程服务的服务消费方。
  • Registry: 服务注册与发现的注册中心。
  • Monitor: 统计服务的调用次数和调用时间的监控中心。

调用流程

  1. 服务容器负责启动,加载,运行服务提供者。
  2. 服务提供者在启动时,向注册中心注册自己提供的服务。
  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心

ZooKeeper

Posted on 2018-08-11 | In Distribution |

ZooKeeper是一个开源的分布式协调服务,他为分布式应用提供了高效且可靠的分布式协调服务,提供了诸如统一命名空间服务,配置服务和分布式锁等分布式基础服务。

就是一个服务注册中心。一个典型的ZooKeeper集群如下:

ZooKeeper拥有一个层次的命名空间,这个和标准的文件系统非常相似,如下图所示:

安装

  1. 下载并解压;
  2. 创建data和log目录;
  3. 修改config - zoo.cfg;

    1
    2
    dataDir=/opt/zookeeper-3.4.13/data
    dataLogDir=/opt/zookeeper-3.4.13/log
  4. 启动

    1
    2
    3
    4
    5
    6
    7
    8
    [root@Automation bin]# ./zkServer.sh start
    ZooKeeper JMX enabled by default
    Using config: /opt/zookeeper-3.4.13/bin/../conf/zoo.cfg
    Starting zookeeper ... STARTED
    [root@Automation bin]# ./zkServer.sh status
    ZooKeeper JMX enabled by default
    Using config: /opt/zookeeper-3.4.13/bin/../conf/zoo.cfg
    Mode: standalone

命令操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[root@Automation bin]# ./zkCli.sh -server localhost:2181
Connecting to localhost:2181
2018-06-02 09:26:12,387 [myid:] - INFO [main:Environment@100] - Client environment:zookeeper.version=3.4.13-2d71af4dbe22557fda74f9a9b4309b15a7487f03, built on 06/29/2018 04:05 GMT
2018-06-02 09:26:12,395 [myid:] - INFO [main:Environment@100] - Client environment:host.name=<NA>
2018-06-02 09:26:12,395 [myid:] - INFO [main:Environment@100] - Client environment:java.version=1.8.0_11
2018-06-02 09:26:12,405 [myid:] - INFO [main:Environment@100] - Client environment:java.vendor=Oracle Corporation
2018-06-02 09:26:12,405 [myid:] - INFO [main:Environment@100] - Client environment:java.home=/usr/java/jdk1.8.0_11/jre
2018-06-02 09:26:12,405 [myid:] - INFO [main:Environment@100] - Client environment:java.class.path=/opt/zookeeper-3.4.13/bin/../build/classes:/opt/zookeeper-3.4.13/bin/../build/lib/*.jar:/opt/zookeeper-3.4.13/bin/../lib/slf4j-log4j12-1.7.25.jar:/opt/zookeeper-3.4.13/bin/../lib/slf4j-api-1.7.25.jar:/opt/zookeeper-3.4.13/bin/../lib/netty-3.10.6.Final.jar:/opt/zookeeper-3.4.13/bin/../lib/log4j-1.2.17.jar:/opt/zookeeper-3.4.13/bin/../lib/jline-0.9.94.jar:/opt/zookeeper-3.4.13/bin/../lib/audience-annotations-0.5.0.jar:/opt/zookeeper-3.4.13/bin/../zookeeper-3.4.13.jar:/opt/zookeeper-3.4.13/bin/../src/java/lib/*.jar:/opt/zookeeper-3.4.13/bin/../conf:.:/usr/java/jdk1.8.0_11/lib/dt.jar:/usr/java/jdk1.8.0_11/lib/tools.jar:/usr/java/jdk1.8.0_11/jre/lib
2018-06-02 09:26:12,405 [myid:] - INFO [main:Environment@100] - Client environment:java.library.path=/usr/java/packages/lib/i386:/lib:/usr/lib
2018-06-02 09:26:12,405 [myid:] - INFO [main:Environment@100] - Client environment:java.io.tmpdir=/tmp
2018-06-02 09:26:12,405 [myid:] - INFO [main:Environment@100] - Client environment:java.compiler=<NA>
2018-06-02 09:26:12,405 [myid:] - INFO [main:Environment@100] - Client environment:os.name=Linux
2018-06-02 09:26:12,406 [myid:] - INFO [main:Environment@100] - Client environment:os.arch=i386
2018-06-02 09:26:12,406 [myid:] - INFO [main:Environment@100] - Client environment:os.version=2.6.32-573.el6.x86_64
2018-06-02 09:26:12,406 [myid:] - INFO [main:Environment@100] - Client environment:user.name=root
2018-06-02 09:26:12,406 [myid:] - INFO [main:Environment@100] - Client environment:user.home=/root
2018-06-02 09:26:12,407 [myid:] - INFO [main:Environment@100] - Client environment:user.dir=/opt/zookeeper-3.4.13/bin
2018-06-02 09:26:12,410 [myid:] - INFO [main:ZooKeeper@442] - Initiating client connection, connectString=localhost:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@1e0aca6
Welcome to ZooKeeper!
2018-06-02 09:26:12,484 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1029] - Opening socket connection to server localhost/0:0:0:0:0:0:0:1:2181. Will not attempt to authenticate using SASL (unknown error)
JLine support is enabled
2018-06-02 09:26:12,510 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@879] - Socket connection established to localhost/0:0:0:0:0:0:0:1:2181, initiating session
2018-06-02 09:26:12,572 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1303] - Session establishment complete on server localhost/0:0:0:0:0:0:0:1:2181, sessionid = 0x1003ae6d0d60000, negotiated timeout = 30000

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
[zk: localhost:2181(CONNECTED) 0]

这里不做过多深入学习说明,集群环境搭建,工作原理,Leader选举等,请参见官方文档。

Jmeter - 环境及常用插件

Posted on 2018-08-05 | In Jmeter |

不做过多介绍,下载后,解压运行,即可使用。

插件

插件管理

从官网下载Plugins Manager Download,将其放入jmeter安装目录下的lib/ext目录,然后重启jmeter,即可。

常用插件

插件管理那个我试的时候好像不好用,后来不知道为啥自己又出来了,我们可以手动的来下载配置相应的插件。

下载Old-Style Releases

  • JMeterPlugins-Standard-1.4.0.zip
  • JMeterPlugins-Extras-1.4.0.zip
    解压,将其拷贝到jmeter的lib/ext目录下。

OS监控

从此下载PerfMon Server Agent。

  1. 上传到Server,并启动。
  2. 客户端监听

Stepping Thread Group & Concurrency Thread Group

Java项目实战 - 项目部署

Posted on 2018-07-29 | In Java |

项目实现分布式部署。

系统规划

域名

  • zheyi-manager : manager.zheyi.com
  • zheyi-portal : www.zheyi.com
  • zheyi-rest : rest.zheyi.com
  • zheyi-sso : sso.zheyi.com
  • zheyi-search : search.zheyi.com

所有的域名都配置指向代理服务器(Nginx)。

  • 192.168.22.138 : manager.zheyi.com
  • 192.168.22.138 : www.zheyi.com
  • 192.168.22.138 : rest.zheyi.com
  • 192.168.22.138 : sso.zheyi.com
  • 192.168.22.138 : search.zheyi.com

服务器

  • 图片Server
  • Redis集群
  • Solr集群
  • DB Server
  • Nginx Server
  • zheyi-manager
  • zheyi-portal
  • zheyi-sso
  • zheyi-search
  • zheyi-rest

至少要10台VM。

Nginx

用Nginx来实现反向代理服务器。

虚拟主机

nginx支持三种类型的虚拟主机配置:

  1. 基于ip的虚拟主机
  2. 基于域名的虚拟主机
  3. 基于端口的虚拟主机
    一般都用第3种方式来实现。

    反向代理

    而反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。

配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
upstream manager.zheyi.com {
server 192.168.22.135:8080;
}
upstream rest.zheyi.com {
server 192.168.22.136:8080;
}
upstream search.zheyi.com {
server 192.168.22.136:8081;
}
upstream sso.zheyi.com {
server 192.168.22.136:8082;
}
upstream order.zheyi.com {
server 192.168.22.136:8083;
}
upstream www.zheyi.com {
server 192.168.22.137:8080;
}
server {
listen 80;
server_name manager.zheyi.com;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
proxy_pass http://manager.zheyi.com;
index index.html index.htm;
}
}
server {
listen 80;
server_name rest.zheyi.com;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
proxy_pass http://rest.zheyi.com;
index index.html index.htm;
}
}
server {
listen 80;
server_name search.zheyi.com;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
proxy_pass http://search.zheyi.com;
index index.html index.htm;
}
}
server {
listen 80;
server_name sso.zheyi.com;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
proxy_pass http://sso.zheyi.com;
index index.html index.htm;
}
}
server {
listen 80;
server_name www.zheyi.com;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
proxy_pass http://www.zheyi.com;
index index.html index.htm;
}
}

负载均衡

根据不同策略来实现。

Tomcat热部署

使用maven实现tomcat的热部署。

  1. 在Tomcat中配置用户权限(conf/tomcat-user.xml)

    1
    2
    3
    <role rolename="manager-gui" />
    <role rolename="manager-script" />
    <user username="tomcat" password="tomcat" roles="manager-gui, manager-script"/>
  2. 修改工程pom文件(build)

    1
    2
    3
    <url>http://${deploy server ip}:8080/manager/text</url>
    <username>tomcat</username>
    <password>tomcat</password>
  3. 执行Maven Build,即可实现热部署。

整个POC到此完工,明白了基本的开发流程和中间应用到的框架和工具。

Java项目实战-SSO集成Portal

Posted on 2018-07-28 | In Java |

业务

在Portal点击登录跳转到SSO登录页面,登录后,跳转到Portal首页。

实现

在Portal中需要从cookie中把token取出来。所以必须在登录成功后把token写入cookie,且cookie的值必须在系统之间能共享。
要在SsoService加上cookie:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Override
public TaotaoResult userLogin(String username, String password, HttpServletRequest request, HttpServletResponse response) {
TbUserExample example = new TbUserExample();
Criteria criteria = example.createCriteria();

// username
criteria.andUsernameEqualTo(username);
List<TbUser> list = userMapper.selectByExample(example);

if (list == null || list.size() == 0) {
return TaotaoResult.build(400, "username or password wrong");
}

// password
TbUser user = list.get(0);
if (!DigestUtils.md5DigestAsHex(password.getBytes()).equals(user.getPassword())) {
return TaotaoResult.build(400, "username or password wrong");
}

// token
String token = UUID.randomUUID().toString();

// add redis
redisPool.set(SSO_SESSION_KEY + ":" + token, JsonUtils.objectToJson(user));
redisPool.expire(SSO_SESSION_KEY + ":" + token, SSO_SESSION_EXPIRE);

// add cookie
CookieUtils.setCookie(request, response, "Z_TOKEN", token);

//return token
return TaotaoResult.ok(token);
}

拦截器

Interceptor拦截器用于拦截Controller层接口,以下3个步骤实现:

  1. 需要实现HandlerInterceptor接口。
  2. 实现拦截逻辑
  3. 需要在springmvc.xml中配置。

实现HandlerInterceptor接口

Service:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Service
public class UserServiceImpl implements UserService {

@Value("${SSO_BASE_URL}")
public String SSO_BASE_URL;
@Value("${SSO_USER_TOKEN}")
public String SSO_USER_TOKEN;
@Value("${SSO_USER_LOGIN}")
public String SSO_USER_LOGIN;


@Override
public TbUser getUserByToken(String token) {
try {
String json = HttpClientUtil.doGet(SSO_BASE_URL + SSO_USER_TOKEN + token);
TaotaoResult result = TaotaoResult.formatToPojo(json, TbUser.class);
if (result.getStatus() == 200) {
TbUser user = (TbUser) result.getData();
return user;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

Interceptor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class LoginInterceptor implements HandlerInterceptor {

@Autowired
private UserServiceImpl userService;

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {

/// get token from cookie
String token = CookieUtils.getCookieValue(request, "Z_TOKEN");

// get user by token
TbUser user = userService.getUserByToken(token);

if (user == null) {
response.sendRedirect(userService.SSO_BASE_URL + userService.SSO_USER_LOGIN
+ "?redirect=" + request.getRequestURI());
return false;
}
return true;
}
}

springmvc.xml:

1
2
3
4
5
6
7
8
<!-- 拦截器配置 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 拦截订单类请求 -->
<mvc:mapping path="/item/**"/>
<bean class="com.izheyi.portal.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>

Java项目实战-SSO

Posted on 2018-07-28 | In Java |

创建一个新工程zheyi-sso,要用到Redis和DB。

注册

在注册用户之前,要先检查注册的用户信息的正确性。

Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/*
* check user date
* @see com.izheyi.sso.service.SsoService#checkUserData(java.lang.String, java.lang.Integer)
*/

@Override
public TaotaoResult checkUserData(String content, Integer type) {
TbUserExample userExample = new TbUserExample();
Criteria criteria = userExample.createCriteria();

if (type == 1) {
criteria.andUsernameEqualTo(content);
}else if (type == 2) {
criteria.andPhoneEqualTo(content);
}else {
criteria.andEmailEqualTo(content);
}

List<TbUser> list = userMapper.selectByExample(userExample);
if (list == null || list.size() == 0) {
return TaotaoResult.ok(true);
}

return TaotaoResult.ok(false);
}

/*
* create user
* @see com.izheyi.sso.service.SsoService#createUser(com.izheyi.pojo.TbUser)
*/

@Override
public TaotaoResult createUser(TbUser user) {
user.setCreated(new Date());
user.setUpdated(new Date());

user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()));
userMapper.insert(user);

return TaotaoResult.ok();
}

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*
* check user data
*/
@RequestMapping("/check/{param}/{type}")
@ResponseBody
public Object checkUserData(@PathVariable String param, @PathVariable Integer type, String callback) {

TaotaoResult result = null;
try {
result = ssoService.checkUserData(param, type);
} catch (Exception e) {
e.printStackTrace();
}

if (!StringUtils.isBlank(callback)) {
MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(result);
mappingJacksonValue.setJsonpFunction(callback);
return mappingJacksonValue;
}else {
return result;
}
}

/*
* create user
*/
@RequestMapping(value="/register", method=RequestMethod.POST)
@ResponseBody
public TaotaoResult createUser(TbUser user) {
TaotaoResult result = null;

try {
result = ssoService.createUser(user);

} catch (Exception e) {
e.printStackTrace();
}

return result;
}

登录

Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Override
public TaotaoResult userLogin(String username, String password) {
TbUserExample example = new TbUserExample();
Criteria criteria = example.createCriteria();

// username
criteria.andUsernameEqualTo(username);
List<TbUser> list = userMapper.selectByExample(example);

if (list == null || list.size() == 0) {
return TaotaoResult.build(400, "username or password wrong");
}

// password
TbUser user = list.get(0);
if (!DigestUtils.md5DigestAsHex(password.getBytes()).equals(user.getPassword())) {
return TaotaoResult.build(400, "username or password wrong");
}

// token
String token = UUID.randomUUID().toString();

// add redis
redisPool.set(SSO_SESSION_KEY + ":" + token, JsonUtils.objectToJson(user));
redisPool.expire(SSO_SESSION_KEY + ":" + token, SSO_SESSION_EXPIRE);

//return token
return TaotaoResult.ok(token);
}

Controller

1
2
3
4
5
6
7
8
9
10
11
@RequestMapping(value="/login", method=RequestMethod.POST)
@ResponseBody
public TaotaoResult userLogin(String username, String password){
try {
TaotaoResult result = ssoService.userLogin(username, password);
return result;
} catch (Exception e) {
e.printStackTrace();
return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}
}

查询用户 By Token

Service

1
2
3
4
5
6
7
8
9
10
11
12
@Override
public TaotaoResult getUserByToken(String token) {
String result = redisPool.get(SSO_SESSION_KEY + ":" + token);

if (StringUtils.isBlank(result)) {
return TaotaoResult.build(400, "session expired, please relogin");
}

redisPool.expire(SSO_SESSION_KEY + ":" + token, SSO_SESSION_EXPIRE);

return TaotaoResult.ok(JsonUtils.jsonToPojo(result, TbUser.class));
}

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@RequestMapping("/token/{token}")
@ResponseBody
public Object getUserByToken(@PathVariable String token, String callback) {
TaotaoResult result = null;

try {
result = ssoService.getUserByToken(token);
} catch (Exception e) {
e.printStackTrace();
result = TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}

if (!StringUtils.isBlank(callback)) {
MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(result);
mappingJacksonValue.setJsonpFunction(callback);
return mappingJacksonValue;
}else {
return result;
}

}

实现SSO功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Controller
@RequestMapping("/user")
public class UserController {

@RequestMapping("/register")
public String registerPage() {
return "register";
}

@RequestMapping("/login")
public String loginPage(String redirect, Model model) {
model.addAttribute("redirect", redirect);
return "login";
}
}

这,登录和注册的功能在SSO系统中完成,其他系统可调用。

Java项目实战 - 展示商品详情页

Posted on 2018-07-25 | In Java |

发布服务

zheyi-rest实现:商品基本信息和描述的显示,并添加缓存。

Dao

无。

Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
@Service
public class ItemServiceImpl implements ItemService {

@Value("${REDIS_ITEM_KEY}")
private String REDIS_ITEM_KEY;
@Value("${REDIS_ITEM_EXPIRE}")
private Integer REDIS_ITEM_EXPIRE;


@Autowired
private TbItemMapper itemMapper;

@Autowired
private TbItemDescMapper itemDescMapper;

@Autowired
private RedisUtils redisUtils;

@Override
public TaotaoResult getItemBasicInfo(long itemId) {

//get cache
try {
String cache = redisUtils.get(REDIS_ITEM_KEY + ":" + itemId + ":basic");
if (!StringUtils.isBlank(cache)) {
TbItem item = JsonUtils.jsonToPojo(cache, TbItem.class);
return TaotaoResult.ok(item);
}
} catch (Exception e) {
e.printStackTrace();
}


TbItem item = itemMapper.selectByPrimaryKey(itemId);

//add cache
try {
redisUtils.set(REDIS_ITEM_KEY + ":" + itemId + ":basic", JsonUtils.objectToJson(item));
redisUtils.expire(REDIS_ITEM_KEY + ":" + itemId + ":basic", REDIS_ITEM_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
return TaotaoResult.ok(item);
}

@Override
public TaotaoResult getItemDesc(long itemId) {

//get cache
try {
String cache = redisUtils.get(REDIS_ITEM_KEY + ":" + itemId + ":desc");
if (!StringUtils.isBlank(cache)) {

TbItemDesc itemDesc = JsonUtils.jsonToPojo(cache, TbItemDesc.class);
return TaotaoResult.ok(itemDesc);
}
} catch (Exception e) {
// TODO: handle exception
}

TbItemDesc itemDesc = itemDescMapper.selectByPrimaryKey(itemId);

//add cache
try {
redisUtils.set(REDIS_ITEM_KEY + ":" + itemId + ":desc", JsonUtils.objectToJson(itemDesc));
redisUtils.expire(REDIS_ITEM_KEY + ":" + itemId + ":desc", REDIS_ITEM_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
return TaotaoResult.ok(itemDesc);
}

}

Portal调用

zheyi-portal实现:当用户访问商品详情页面时,需要加载商品信息。

Dao

需要添加POJO:

1
2
3
4
5
6
7
8
9
10
11
public class ItemInfo extends TbItem{

public String[] getImages() {
String image = getImage();
if (image != null) {
String[] images = image.split(",");
return images;
}
return null;
}
}

Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Service
public class ItemServiceImpl implements ItemService {

@Value("${REST_BASE_URL}")
private String REST_BASE_URL;
@Value("${ITEM_INFO}")
private String ITEM_INFO;
@Value("${ITEM_DESC_URL}")
private String ITEM_DESC_URL;

@Override
public ItemInfo getItemById(Long itemId) {
try {
String itemJson = HttpClientUtil.doGet(REST_BASE_URL + ITEM_INFO + itemId);
if (!StringUtils.isBlank(itemJson)) {
TaotaoResult result = TaotaoResult.formatToPojo(itemJson, ItemInfo.class);
if (result.getStatus() == 200) {
ItemInfo itemInfo = (ItemInfo) result.getData();
return itemInfo;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

@Override
public String getItemDescById(Long itemId) {
try {
//查询商品描述
String json = HttpClientUtil.doGet(REST_BASE_URL + ITEM_DESC_URL + itemId);
//转换成java对象
TaotaoResult taotaoResult = TaotaoResult.formatToPojo(json, TbItemDesc.class);
if (taotaoResult.getStatus() == 200) {
TbItemDesc itemDesc = (TbItemDesc) taotaoResult.getData();
//取商品描述信息
String result = itemDesc.getItemDesc();
return result;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}


}

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Controller
public class ItemController {

@Autowired
private ItemService itemService;

@RequestMapping("/item/{itemId}")
public String getItem(@PathVariable Long itemId, Model model){
ItemInfo itemInfo = itemService.getItemById(itemId);

model.addAttribute("item", itemInfo);

return "item";
}

@RequestMapping(value="/item/desc/{itemId}", produces=MediaType.TEXT_HTML_VALUE+";charset=utf-8")
@ResponseBody
public String getItemDesc(@PathVariable Long itemId) {
String string = itemService.getItemDescById(itemId);
return string;
}
}

Java项目实战 - solr实现前端商品搜索

Posted on 2018-07-22 | In Java |

在zheyi-portal工程中实现。

Dao

无。

Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Service
public class SearchServiceImpl implements SearchService {

@Value("${SEARCH_BASE_URL}")
private String SEARCH_BASE_URL;

@Override
public SearchResult search(String query, int page) {
Map<String, String> param = new HashMap<>();
param.put("q", query);
param.put("page", page + "");
try {
String getString = HttpClientUtil.doGet(SEARCH_BASE_URL, param);
TaotaoResult result = TaotaoResult.formatToPojo(getString, SearchResult.class);
if (result.getStatus() == 200) {
SearchResult searchResult = (SearchResult) result.getData();
return searchResult;
}
} catch (Exception e) {
e.printStackTrace();
}

return null;
}

}

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Controller
public class SearchServiceController {

@Autowired
private SearchService searchService;

@RequestMapping("/search")
public String search(@RequestParam("q")String query, @RequestParam(defaultValue="1")Integer page,
Model model) {

if (query != null) {
try {
query = new String(query.getBytes("iso8859-1"), "utf-8");
} catch (Exception e) {
e.printStackTrace();
}

}
SearchResult searchResult = searchService.search(query, page);

model.addAttribute("query", query);
model.addAttribute("totalPages", searchResult.getTotalPageCount());
model.addAttribute("itemList", searchResult.getItemList());
model.addAttribute("page", page);

return "search";
}

}

Java项目实战 - solr发布搜索服务

Posted on 2018-07-22 | In Java |

发布搜索服务供其它工程调用。

Dao

要定义返回的POJO:

1
2
3
4
5
6
7
8
public class SearchResult {

private List<Item> itemList;
private long totalItemCount;
private long totalPageCount;
private long currentPageNumber;
private long currentRowCount;
}

并实现Dao:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@Repository
public class SearchDaoImpl implements SearchDao {

@Autowired
private SolrServer solrServer;

@Override
public SearchResult search(SolrQuery query) throws Exception {
// return result
SearchResult resultList = new SearchResult();

// solr search
QueryResponse response = solrServer.query(query);
SolrDocumentList solrDocumentList = response.getResults();

// highlight
Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();

//get item list
List<Item> itemList = new ArrayList<>();

for (SolrDocument solrDocument : solrDocumentList) {
Item item = new Item();

item.setId((String) solrDocument.get("id"));
//get highlight
List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
String title = "";
if(list != null && list.size()>0){
title = list.get(0);
}else{
title = (String) solrDocument.get("item_title");
}
item.setTitle(title);
item.setImage((String) solrDocument.get("item_image"));
item.setPrice((long) solrDocument.get("item_price"));
item.setSell_point((String) solrDocument.get("item_sell_point"));
item.setCategory_name((String) solrDocument.get("item_category_name"));

itemList.add(item);
}

resultList.setItemList(itemList);

// get total item number
resultList.setTotalItemCount(solrDocumentList.getNumFound());

return resultList;
}

}

Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@Service
public class ServiceSearchImpl implements SearchService {

@Autowired
private SearchDao searchDao;

@Override
public SearchResult search(String query, int page, int rows) throws Exception {
SolrQuery solrQuery = new SolrQuery();

solrQuery.setQuery(query);

solrQuery.setStart((page -1) * rows);
solrQuery.setRows(rows);

solrQuery.set("df", "item_keywords");

solrQuery.setHighlight(true);
solrQuery.addHighlightField("item_title");
solrQuery.setHighlightSimplePre("<em style=\"color:red\">");
solrQuery.setHighlightSimplePost("</em>");

SearchResult result = searchDao.search(solrQuery);

long totalItemCount = result.getTotalItemCount();
long totalPageCount = totalItemCount / rows;
if (totalItemCount % rows > 0){
totalPageCount++;
}

result.setTotalPageCount(totalPageCount);
result.setCurrentPageNumber(page);
result.setCurrentRowCount(rows);
return result;
}

}

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Controller
public class SearchServiceController {

@Autowired
private SearchService searchService;

@RequestMapping(value="/query", method=RequestMethod.GET)
@ResponseBody
public TaotaoResult search(@RequestParam("q")String query,
@RequestParam(defaultValue="1")Integer page,
@RequestParam(defaultValue="20")Integer rows){

//query is null
if(StringUtils.isBlank(query))
return TaotaoResult.build(400, "Should contain query string");

SearchResult searchResult = null;
try {
query = new String(query.getBytes("iso8859-1"), "utf-8");
searchResult = searchService.search(query, page, rows);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return TaotaoResult.ok(searchResult);
}

}

Java项目实战 - solr导入索引库

Posted on 2018-07-22 | In Java |

实现:
使用java程序读取mysql数据库中的商品信息,然后创建solr文档对象,把商品信息写入索引库。

Dao

多表查询,要创建相应的POJO和Mapper。
POJO:

1
2
3
4
5
6
7
8
9
public class Item {
private String id;
private String title;
private String sell_point;
private long price;
private String image;
private String category_name;
private String item_des;
}

Mapper:

1
2
3
public interface ItemMapper {
List<Item> getItemList();
}

  • xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.izheyi.search.mapper.ItemMapper" >

    <select id="getItemList" resultType="com.izheyi.search.pojo.Item">
    SELECT
    a.id,
    a.title,
    a.sell_point,
    a.price,
    a.image,
    b. NAME category_name
    FROM
    tb_item a
    LEFT JOIN tb_item_cat b ON a.cid = b.id
    </select>
    </mapper>

Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@Service
public class ItemServiceImpl implements ItemService {

@Autowired
private ItemMapper itemMapper;

@Autowired
private SolrServer solrServer;

@Override
public TaotaoResult importItemsToSolr() {
try {

//查询商品列表
List<Item> list = itemMapper.getItemList();
//把商品信息写入索引库
for (Item item : list) {
//创建一个SolrInputDocument对象
SolrInputDocument document = new SolrInputDocument();
document.setField("id", item.getId());
document.setField("item_title", item.getTitle());
document.setField("item_sell_point", item.getSell_point());
document.setField("item_price", item.getPrice());
document.setField("item_image", item.getImage());
document.setField("item_category_name", item.getCategory_name());
document.setField("item_desc", item.getItem_des());
//写入索引库
solrServer.add(document);
}
//提交修改
solrServer.commit();
} catch (Exception e) {
e.printStackTrace();
return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}
return TaotaoResult.ok();
}
}

需要配置applicationContext-solr.xml。

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Controller
@RequestMapping("/manager")
public class ItemController {

@Autowired ItemService itemService;

@RequestMapping("/import")
@ResponseBody
public TaotaoResult importItemsToSolr(){
TaotaoResult result = itemService.importItemsToSolr();

return result;
}

}

1…91011…40
唐胡璐

唐胡璐

i just wanna live while i am alive

393 posts
42 categories
74 tags
RSS
LinkedIn Weibo GitHub E-Mail
Creative Commons
© 2022 唐胡璐
Powered by Hexo
|
Theme — NexT.Pisces v5.1.4