We can show our newly arrived products on the home page.

Update Product Model

Replace the original content with the following one in the Product.java file under the common/src/main/java/co.dongchen.shop.common/model directory:

  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
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package co.dongchen.shop.common.model;

import com.google.common.collect.Lists;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

public class Product {

    private Long id;
    private Integer createdAt;
    private Integer updatedAt;
    private String sku;
    private String name;
    private Integer stock;
    private Integer price;
    private Boolean isEnabled;
    private String images;
    private String description;
    private Long userId;
    private List<Long> ids;
    // NEWLY ADDED CODE 1 BEGIN
    private String orderBy;
    // NEWLY ADDED CODE 1 END

    private String mainImage;
    private List<String> imageList = Lists.newArrayList();
    private Boolean isFavourite;
    private List<MultipartFile> imageFiles;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Integer getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Integer createdAt) {
        this.createdAt = createdAt;
    }

    public Integer getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(Integer updatedAt) {
        this.updatedAt = updatedAt;
    }

    public String getSku() {
        return sku;
    }

    public void setSku(String sku) {
        this.sku = sku;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getStock() {
        return stock;
    }

    public void setStock(Integer stock) {
        this.stock = stock;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    public Boolean getEnabled() {
        return isEnabled;
    }

    public void setEnabled(Boolean enabled) {
        isEnabled = enabled;
    }

    public String getImages() {
        return images;
    }

    public void setImages(String images) {
        this.images = images;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public List<Long> getIds() {
        return ids;
    }

    public void setIds(List<Long> ids) {
        this.ids = ids;
    }

    // NEWLY ADDED CODE 2 BEGIN
    public String getOrderBy() {
        return orderBy;
    }

    public void setOrderBy(String orderBy) {
        this.orderBy = orderBy;
    }
    // NEWLY ADDED CODE 2 END

    public String getMainImage() {
        return mainImage;
    }

    public void setMainImage(String mainImage) {
        this.mainImage = mainImage;
    }

    public List<String> getImageList() {
        return imageList;
    }

    public void setImageList(List<String> imageList) {
        this.imageList = imageList;
    }

    public Boolean getFavourite() {
        return isFavourite;
    }

    public void setFavourite(Boolean favourite) {
        isFavourite = favourite;
    }

    public List<MultipartFile> getImageFiles() {
        return imageFiles;
    }

    public void setImageFiles(List<MultipartFile> imageFiles) {
        this.imageFiles = imageFiles;
    }
}

Update product.xml

Replace the original content with the following one in the product.xml file under the service/src/main/resources/mapper directory:

 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
<?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="co.dongchen.shop.mapper.ProductMapper">
    <sql id="productFields">
        p.id, p.created_at, p.updated_at, p.sku, p.name, p.stock, p.price, p.is_enabled, p.images, p.description, p.user_id
    </sql>
    <sql id="whereCondition">
        <where>
            <if test="productCondition.id != null and productCondition.id != 0">
                and p.id = #{productCondition.id}
            </if>
            <if test="productCondition.isEnabled != null and productCondition.isEnabled == true">
                and p.is_enabled = 1
            </if>
            <if test="productCondition.isEnabled != null and productCondition.isEnabled == false">
                and p.is_enabled = 0
            </if>
            <if test="productCondition.name != null and productCondition.name != ''">
                <bind name="likeName" value="'%' + productCondition.name + '%'"/>
                and p.name like #{likeName}
            </if>
            <if test="productCondition.ids != null and productCondition.ids.size() > 0 ">
                and p.id in
                <foreach collection="productCondition.ids" item="item" index="index" open="(" separator="," close=")" >
                    #{item}
                </foreach>
            </if>
        </where>
    </sql>
    <select id="queryPagedProducts" resultType="product">
        select <include refid="productFields"/>
        from product p
        <include refid="whereCondition"/>
        <!-- NEWLY ADDED CODE BEGIN -->
        <choose>
            <when test="productCondition.orderBy != null and productCondition.orderBy == 'created_at'">
                order by p.created_at desc
            </when>
        </choose>
        <!-- NEWLY ADDED CODE END -->
        <if test="pageHelperCondition.offSet != null and pageHelperCondition.limit != null">
            limit #{pageHelperCondition.offSet},#{pageHelperCondition.limit}
        </if>
        <if test="pageHelperCondition.offSet == null and pageHelperCondition.limit != null">
            limit #{pageHelperCondition.limit}
        </if>
    </select>
    <select id="queryPagedCount" resultType="long">
        select count(id)
        from product p
        <include refid="whereCondition"/>
    </select>
</mapper>

Update TopProductService

Replace the original content with the following one in the TopProductService.java file under the service/src/main/java/co.dongchen.shop/service directory:

 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
package co.dongchen.shop.service;

import co.dongchen.shop.common.model.Product;
import co.dongchen.shop.common.util.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class TopProductService {

    private static final String TOP_PRODUCT_KEY = "TOP_PRODUCT_KEY";

    @Autowired
    private ProductService productService;

    public void increase(Long id) {
        Jedis jedis = new Jedis("127.0.0.1");
        // Adds the score value of the member named the product id in the TOP_PRODUCT_KEY sorted set to one and returns the new score value of the member.
        jedis.zincrby(TOP_PRODUCT_KEY, 1.0D, String.valueOf(id));
        // Removes members after the fifth of the top five ranked members in the TOP_PRODUCT_KEY sorted set and returns the number of removed members.
        jedis.zremrangeByRank(TOP_PRODUCT_KEY, 5, -1);
        jedis.close();
    }

    private List<Long> getTopIds() {
        Jedis jedis = new Jedis("127.0.0.1");
        // Retrieve all members of the sorted set named TOP_PRODUCT_KEY.
        Set<String> ids = jedis.zrevrange(TOP_PRODUCT_KEY, 0, -1);
        jedis.close();
        return ids.stream().map(Long::parseLong).collect(Collectors.toList());
    }

    public List<Product> getTopProducts(int size) {
        Product productCondition = new Product();
        List<Long> topIds = getTopIds();
        // Retrieve minimum available products from the beginning.
        topIds = topIds.subList(0, Math.min(topIds.size(), size));
        if (topIds.isEmpty()) {
            return Lists.newArrayList();
        }
        productCondition.setIds(topIds);
        final List<Long> orderedIds = topIds;
        List<Product> products = productService.queryWithImgs(productCondition, PageHelper.init(size, 1));
        Ordering<Product> productOrdering = Ordering.natural().onResultOf(ps -> {
            return orderedIds.indexOf(ps.getId());
        });
        return productOrdering.sortedCopy(products);
    }

    // NEWLY ADDED CODE BEGIN
    public List<Product> getNewArrivals() {
        Product productCondition = new Product();
        productCondition.setOrderBy("created_at");
        return productService.queryWithImgs(productCondition, PageHelper.init(6, 1));
    }
    // NEWLY ADDED CODE END

}

Create HomeController

  • Right click controller/src/main/java/co.dongchen.shop/controller directory: New > Java Class
  • Fill in “HomeController”
  • Click “OK” button
img

After inputting the name, press Enter.

Copy and paste the following content into HomeController.java:

 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
package co.dongchen.shop.controller;

import co.dongchen.shop.common.model.Product;
import co.dongchen.shop.service.TopProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
public class HomeController {

    @Autowired
    private TopProductService topProductService;

    @RequestMapping("/")
    public String index(ModelMap modelMap) {
        List<Product> products = topProductService.getNewArrivals();
        modelMap.put("newArrivals", products);
        return "index";
    }

}

Update index.ftl

Replace the original content with the following one in the index.ftl file under the controller/src/main/resources/templates directory:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<html lang="en-NZ">
<@common.header/>
<body>
Shop Home Page
    <#foreach product in newArrivals>
        <div>
            <p>${product.name}</p>
        </div>
    </#foreach>
</body>
<@common.footer/>
</html>

Verify

Run the App

1
2
// Short Cut for "Run the Program"
Alt + Shift + F10
img

Choose the correspondent option and press enter.

View Index Page in the Browser

1
http://localhost:8080

Visit index page, and we will get a similar result as follows:

img

Buy me a coffeeBuy me a coffee