SpingBoot的项目实战--模拟电商【1.首页搭建】

🥳🥳Welcome Huihui's Code World ! !🥳🥳

接下来看看由辉辉所写的关于SpringBoot电商项目的相关操作吧 

目录

🥳🥳Welcome Huihui's Code World ! !🥳🥳

一.项目背景及技术点运用

1.项目背景

2.技术点运用

二.数据库表及依赖

1.数据库

2.依赖

pom

yml

三.需求

1.页面分析

2.数据更换(静态➡动态)

(1)分类数据

(2)具体类别商品展示

①装饰摆件

②墙式壁挂

四.代码编写

0.需求

1.代码生成(model,mapper,service)

五.分类数据

1.mapper

2.service

3.controller

4.前端代码

六.类型具体数据

 1.mapper

2.service

3.controller

4.局部修改

摆件花艺

墙式壁挂

5.html页面


一.项目背景及技术点运用

1.项目背景

写此项目的初衷:最近后台接到了蛮多私信,很多的都在问springboot搭建一个项目会使用到哪些技术,以及怎么写这样一个项目。为了将技术更好的运用以及讲解,于是小编利用工作的空闲时间,写了一个可以训练自己技术点的小项目,大家有兴趣的可以订阅这个合集。

提要:因为这个项目只是练手,数据量很少,也就不存在什么请求卡顿之类的问题了,我就没有在sql优化中花费太多心思了

2.技术点运用

FreeMarker,SpringBoot,Mybatis-plus,Auto2,Spring Security,Mysql,Redis

二.数据库表及依赖

1.数据库

数据库脚本也已经上传上去了,在这篇博文可以看见

2.依赖

pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wh</groupId>
    <artifactId>easyshop</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>easyshop</name>
    <description>Demo project for Spring Boot</description>
    <properties>
       <!-- <java.version>17</java.version>-->
    </properties>
    <dependencies>

        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--mybatis-plus的生成插件-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--spring freemarker-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <!--oauth2-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-client</artifactId>
        </dependency>
        <!--security-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!--spring mvc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--热加载工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--security-test-->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!--lombok-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

yml

server:
  port: 8080
spring:
  freemarker:
    cache: false
    suffix: .html
    template-loader-path: classpath:/templates/
  mvc:
    static-path-pattern: /static/**
  datasource:
    url: jdbc:mysql://localhost:3306/easyshop
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    hikari:
      # 最小空闲连接数量
      minimum-idle: 5
      # 空闲连接存活最大时间,默认600000(10分钟)
      idle-timeout: 180000
      # 连接池最大连接数,默认是10
      maximum-pool-size: 10
      # 此属性控制从池返回的连接的默认自动提交行为,默认值:true
      auto-commit: true
      # 连接池名称
      pool-name: MyHikariCP
      # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
      max-lifetime: 1800000
      # 数据库连接超时时间,默认30秒,即30000
      connection-timeout: 30000
mybatis-plus:
  type-aliases-package: com.wh.easyshop.model
#日志配置
logging:
  level:
    com.star.easyshop.mapper: debug

三.需求

1.页面分析

这个已经转成pdf文件上传在这篇博文中了

2.数据更换(静态➡动态)

(1)分类数据

(2)具体类别商品展示

①装饰摆件

②墙式壁挂

四.代码编写

0.需求

需要将数据库中对应的商品信息展示在首页

1.代码生成(model,mapper,service)

代码生成类

package com.wh.easyshop.config;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@Slf4j
public class MySQLGenerator {

    private final static String URL = "jdbc:mysql://localhost:3306/easyshop";
    private final static String USERNAME = "root";
    private final static String PASSWORD = "123456";

    private final static DataSourceConfig.Builder DATA_SOURCE_CONFIG =
            new DataSourceConfig.Builder(URL, USERNAME, PASSWORD);

    public static void main(String[] args) {
        FastAutoGenerator.create(DATA_SOURCE_CONFIG)
                .globalConfig(
                        (scanner, builder) ->
                                builder.author(scanner.apply("请输入作者名称?"))
                                        .outputDir(System.getProperty("user.dir") + "\\src\\main\\java")
                                        .commentDate("yyyy-MM-dd")
                                        .dateType(DateType.TIME_PACK)
                )
                .packageConfig((builder) ->
                        builder.parent("com.wh.easyshop")
                                .entity("model")
                                .service("service")
                                .serviceImpl("service.impl")
                                .mapper("mapper")
                                .xml("mapper.xml")
                                .pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "\\src\\main\\resources\\mapper"))
                )
                .injectionConfig((builder) ->
                        builder.beforeOutputFile(
                                (a, b) -> log.warn("tableInfo: " + a.getEntityName())
                        )
                )
                .strategyConfig((scanner, builder) ->
                        builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all")))
                                .addTablePrefix("tb_", "t_", "lay_", "meeting_", "sys_")
                                .entityBuilder()
                                .enableChainModel()
                                .enableLombok()
                                .enableTableFieldAnnotation()
                                .controllerBuilder()
                                .enableRestStyle()
                                .enableHyphenStyle()
                                .build()
                )
                .templateEngine(new FreemarkerTemplateEngine())
                .execute();
    }

    protected static List<String> getTables(String tables) {
        return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
    }

}

五.分类数据

这个地方因为自己在设计表的时候没有考虑完善,所以这个地方的遍历会有点复杂,我把哪些有二级目录的分类菜单的数据加到了数据库中

但是在其中有一些分类的类别是没有二级菜单的,所以这里需要查询三次

一次是查询有二级菜单的分类菜单

一次是查询没有二级菜单的分类菜单

一次是查询二级菜单的具体数据

1.mapper

package com.wh.easyshop.mapper;

import com.wh.easyshop.model.Goods;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;

/**
 * <p>
 * 商品信息表 Mapper 接口
 * </p>
 *
 * @author wh
 * @since 2023-12-27
 */
@Repository
public interface GoodsMapper extends BaseMapper<Goods> {
   

       /**
     * 首页分类
     * @param type
     * @return
     */
       List<Map<String,Object>> typelist (String type);


}
<?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.wh.easyshop.mapper.GoodsMapper">


	<select id="typelist" resultType="java.util.Map">
		SELECT
		*
	FROM
		t_dict_type dt,
		t_dict_data dd
	WHERE
		dt.dict_type = dd.dict_type
	AND
		dt.dict_type = #{type}
	</select>
</mapper>

2.service

package com.wh.easyshop.service;

import com.wh.easyshop.model.Goods;
import com.baomidou.mybatisplus.extension.service.IService;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

/**
 * <p>
 * 商品信息表 服务类
 * </p>
 *
 * @author wh
 * @since 2023-12-27
 */
public interface IGoodsService extends IService<Goods> {


    /**
     * 首页分类
     * @param type
     * @return
     */
    List<Map<String,Object>> typelist (String type);
}
package com.wh.easyshop.service.impl;

import com.wh.easyshop.model.Goods;
import com.wh.easyshop.mapper.GoodsMapper;
import com.wh.easyshop.service.IGoodsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * <p>
 * 商品信息表 服务实现类
 * </p>
 *
 * @author wh
 * @since 2023-12-27
 */
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements IGoodsService {
@Autowired
private  GoodsMapper goodsMapper;

   

    /**
     * 分类商品
     * @param type
     * @return
     */
    @Override
    public List<Map<String, Object>> typelist(String type) {
        return goodsMapper.typelist(type);
    }


}

3.controller

package com.wh.easyshop.controller;

import com.google.common.collect.Lists;
import com.wh.easyshop.model.DictData;
import com.wh.easyshop.model.DictType;
import com.wh.easyshop.model.Goods;
import com.wh.easyshop.service.IDictDataService;
import com.wh.easyshop.service.IDictTypeService;
import com.wh.easyshop.service.IGoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

/**
 * <p>
 * 商品信息表 前端控制器
 * </p>
 *
 * @author wh
 * @since 2023-12-27
 */
@Controller

public class GoodsController {
    @Autowired
    private IGoodsService goodsService;
    @Autowired
    private IDictTypeService dictTypeService;
    @Autowired
    private  IDictDataService dictDataService;
    /**
     * 首页商品展示+分类
     * @param model
     * @return
     */
    @RequestMapping("/")
    public String index(Model model) {
        //1.首页商品展示
        //商品集合
        List<Goods> g1 = goodsService.showGoods("01", 6);
        //切片
        List<List<Goods>> p1 = Lists.partition(g1, 3);
        //商品集合
        List<Goods> g2 = goodsService.showGoods("07", 12);
        //切片
        List<List<Goods>> p2 = Lists.partition(g2, 4);
        model.addAttribute("p1", p1);
        model.addAttribute("p2", p2);
        //2.分类
        //次类名显示
        //所有商品
        List<Map<String, Object>> allGoods = goodsService.typelist("all_goods");
        //装饰摆件
        List<Map<String, Object>> flowerDer = goodsService.typelist("flowerDer");
        //布艺软饰
        List<Map<String, Object>> decoration = goodsService.typelist("decoration");
        model.addAttribute("allGoods", allGoods);
        model.addAttribute("flowerDer", flowerDer);
        model.addAttribute("decoration", decoration);
        //主类名显示
        List<DictData> other = dictDataService.list();
        model.addAttribute("other", other);
        List<DictType> main = dictTypeService.list();
        model.addAttribute("main", main);

        return "index";
    }




}

4.前端代码

<script type="text/javascript" src="js/jquery-1.12.4.min.js"></script>
<script>
    $(function(){
        let nickname=getCookie("nickname");
        if(null!=nickname&&''!=nickname&&undefined!=nickname) {
            //设置昵称
            $('#nickname').text("您好,"+nickname);
            //隐藏登录注册按钮
            $('p.fl>span:eq(1)').css("display","none");
            //显示昵称和退出按钮
            $('p.fl>span:eq(0)').css("display","block");
        }else{
            //隐藏昵称
            $('#nickname').text("");
            //显示登录注册按钮
            $('p.fl>span:eq(1)').css("display","block");
            //隐藏昵称和退出按钮
            $('p.fl>span:eq(0)').css("display","none");
        }
    });

    function getCookie(cname) {
        var name = cname + "=";
        var decodedCookie = decodeURIComponent(document.cookie);
        var ca = decodedCookie.split(';');
        for(var i = 0; i <ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == ' ') {
                c = c.substring(1);
            }
            if (c.indexOf(name) == 0) {
                return c.substring(name.length, c.length);
            }
        }
        return "";
    }
</script>
<div class="head">
    <div class="wrapper clearfix">
        <div class="clearfix" id="top">
            <h1 class="fl"><a href="${ctx}/"><img src="img/logo.png"/></a></h1>
            <div class="fr clearfix" id="top1">
                <p class="fl">
                    <span>
                        <span id="nickname"></span>
                        <a href="${ctx}/user/userLogout">退出</a>
                    </span>
                    <span style="display: none">
                        <a href="${ctx}/page/login.html" id="login">登录</a>
                        <a href="${ctx}/page/reg.html" id="reg">注册</a>
                    </span>
                </p>
                <form action="#" method="get" class="fl">
                    <input type="text" placeholder="热门搜索:干花花瓶" />
                    <input type="button" />
                </form>
                <div class="btn fl clearfix">
                    <a href="${ctx}/page/mygxin.html"><img src="img/grzx.png"/></a>
                    <a href="#" class="er1"><img src="img/ewm.png"/></a>
                    <a href="${ctx}/shopCar/queryShopCar"><img src="img/gwc.png"/></a>
                    <p><a href="#"><img src="img/smewm.png"/></a></p>
                </div>
            </div>
        </div>
        <ul class="clearfix" id="bott">
            <li><a href="${ctx}/">首页</a></li>
            <li>
                <#list main as m>
                     <#if m.dict_id==2>
                <a href="#">${m.dict_name}</a>
              <!--  <a href="#">所有商品</a>-->
                <div class="sList">
                    <div class="wrapper  clearfix">
                        <a href="${ctx}/page/paint.html">
                            <dl>
                                <dd>${m.dict_label}</dd>
                            </dl>
                        </a>
                    </#if>
                        </#list>
                    </div>
                </div>
            </li>
           <li>
                <#list main as m>
                <#if m.dictId==3>
                <a href="#">${m.dictName}</a>
            </#if>
            </#list>
                <div class="sList2">
                    <div class="clearfix">
                        <#list flowerDer as f>
                        <a href="${ctx}/page/proList.html">${f.dict_label}</a>
                    </#list>
                    </div>
                </div>
            </li>
            <li>
                <#list main as m>
                <#if m.dictId==4>
                <a href="#">${m.dictName}</a>
            </#if>
            </#list>
                <div class="sList2">
                    <div class="clearfix">
                        <#list decoration as d>
                        <a href="${ctx}/page/proList.html">${d.dict_label}</a>
                    </#list>
                    </div>
                </div>
            </li>
            <li><#list other as t>
                <#if t.dictValue=='07'>
                <a href="#">${t.dictLabel}</a>
            </#if>
            </#list>
            </li>

            <li><#list other as t>
                <#if t.dictValue=='08'>
                <a href="#">${t.dictLabel}</a>
            </#if>
            </#list>
            </li>
            <li><#list other as t>
                <#if t.dictValue=='09'>
                <a href="#">${t.dictLabel}</a>
            </#if>
            </#list>
            </li>

        </ul>
    </div>
</div>

六.类型具体数据

 1.mapper

        因为我们展示的商品是按照类别来的,所以我们需要进行条件查询,所以这里我们自己编写一个接口就好了。

        在下面的代码中有一个@Param注解,我们也可以看一下这个注解的作用到底是什么👇👇

@Param注解可用于给Mapper接口中的方法参数起别名。如果一个方法有多个参数,而且这些参数在SQL语句中使用了,则必须给每个参数加上该注解,以便在SQL语句中可以使用参数别名来引用参数

package com.wh.easyshop.mapper;

import com.wh.easyshop.model.Goods;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * <p>
 * 商品信息表 Mapper 接口
 * </p>
 *
 * @author wh
 * @since 2023-12-27
 */
@Repository
public interface GoodsMapper extends BaseMapper<Goods> {

    /**
     * 首页商品展示
     * @param type
     * @param size
     * @return
     */
    List<Goods> showGoods (@Param("type") String type, @Param("size") int size);

}

对了,我们这里因为是自己编写接口的,所以那个mapper.xml也是需要我们自己写的,目前我们在前端只需要展示装饰摆件以及墙式壁挂,但可能以后也会想要换成其他类型,所以我在mapper.xml中并没有把类型以及展示的条数写死,这样我们想要修改的时候,可以直接在controller层中进行修改

<?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.wh.easyshop.mapper.GoodsMapper">

    <select id="showGoods" resultType="com.wh.easyshop.model.Goods">
        SELECT
	    *
    FROM
	    t_goods g,
	    t_dict_data dd
    WHERE
	    dd.dict_value = #{type}
	AND
	    g.goods_type = dd.dict_value
	    limit #{size}
    </select>
</mapper>

2.service

package com.wh.easyshop.service;

import com.wh.easyshop.model.Goods;
import com.baomidou.mybatisplus.extension.service.IService;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * <p>
 * 商品信息表 服务类
 * </p>
 *
 * @author wh
 * @since 2023-12-27
 */
public interface IGoodsService extends IService<Goods> {
    /**
     * 首页商品展示
     * @param type
     * @param size
     * @return
     */
    List<Goods> showGoods (@Param("type") String type, @Param("size") int size);

}
package com.wh.easyshop.service.impl;

import com.wh.easyshop.model.Goods;
import com.wh.easyshop.mapper.GoodsMapper;
import com.wh.easyshop.service.IGoodsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 * 商品信息表 服务实现类
 * </p>
 *
 * @author wh
 * @since 2023-12-27
 */
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements IGoodsService {
@Autowired
private  GoodsMapper goodsMapper;
    /**
     * 首页商品展示
     * @param type
     * @param size
     * @return
     */
    @Override
    public List<Goods> showGoods(String type, int size) {
        return goodsMapper.showGoods(type,size);
    }
}

3.controller

package com.wh.easyshop.controller;

import com.google.common.collect.Lists;
import com.wh.easyshop.model.Goods;
import com.wh.easyshop.service.IGoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * <p>
 * 商品信息表 前端控制器
 * </p>
 *
 * @author wh
 * @since 2023-12-27
 */
@Controller

public class GoodsController {
    @Autowired
    private IGoodsService goodsService;

    /**
     * 首页商品展示
     * @param model
     * @return
     */
    @RequestMapping("/")
    public String index(Model model) {
        //商品集合
        List<Goods> g1 = goodsService.showGoods("01", 6);
        //切片
        List<List<Goods>> p1 = Lists.partition(g1, 3);
        //商品集合
        List<Goods> g2 = goodsService.showGoods("07", 12);
        //切片
        List<List<Goods>> p2 = Lists.partition(g2, 4);
        model.addAttribute("p1", p1);
        model.addAttribute("p2", p2);
        return "index";
    }
}

4.局部修改

这时候我们在前端遍历一下,我们的集合,现在就是需要把这个里面的东西都换成数据库来的值

这段是遍历的摆件花艺的值,但是我发现这样子遍历之后,前端的样式不对了

<div class="flower clearfix tran">
			<#list g1 as g>
			<a href="proDetail.html" class="clearfix">
				<dl>
					<dt>
						<span class="abl"></span>
						<img src="${g.goodsImg}"/>
						<span class="abr"></span>
					</dt>
					<dd>${g.goodsTitle}</dd>
					<dd><span>¥ 79.00</span></dd>
				</dl>
			</a>
		</#list>
		</div>

现在这些都是一排展示了,而原本它应该是有两排,每排三个的

也是因为我在遍历的时候是遍历的我拿到的6个元素,所以他就一次遍历出来了,如果我们需要完成那种两排的效果,那么需要做一个处理,让它一次只有三个出来,这里其实我们很容易就能够想到,可以使用切片来完成,使用切片也有许多的方法,这里小编使用的是guava,使用这个之前,需要引入相应的依赖

  <!--guava 切片-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>31.0.1-jre</version>
        </dependency>

然后我们再修改一下controller层的方法以及前端页面

package com.wh.easyshop.controller;

import com.google.common.collect.Lists;
import com.wh.easyshop.model.Goods;
import com.wh.easyshop.service.IGoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * <p>
 * 商品信息表 前端控制器
 * </p>
 *
 * @author wh
 * @since 2023-12-27
 */
@Controller

public class GoodsController {
    @Autowired
    private IGoodsService goodsService;
    @RequestMapping("/")
    public String index(Model model) {
        //商品集合
        List<Goods> g1 = goodsService.showGoods("01", 6);
        //切片
        List<List<Goods>> p1 = Lists.partition(g1, 3);
        //商品集合
        List<Goods> g2 = goodsService.showGoods("07", 12);
        //切片
        List<List<Goods>> p2 = Lists.partition(g2, 4);
        model.addAttribute("p1", p1);
        model.addAttribute("p2", p2);
        return "index";
    }
}

摆件花艺

<#list p1 as p>
		<div class="flower clearfix tran">
			<#list p as g>
			<a href="proDetail.html" class="clearfix">
				<dl>
					<dt>
						<span class="abl"></span>
						<img src="${g.goodsImg}"/>
						<span class="abr"></span>
					</dt>
					<dd>${g.goodsTitle}</dd>
					<dd><span>¥ 79.00</span></dd>
				</dl>
			</a>
		</#list>
		</div>
		</#list>

现在我们再看一下前端的页面展示,就可以发现是两排的啦

墙式壁挂

<div class="people">
	<div class="wrapper">
		<h2><img src="img/ih3.jpg"/></h2>
		<#list p2 as p>
		<div class="pList clearfix tran">
				<#list p as g>
			<a href="proDetail.html">
					<dl>
						<dt>
							<span class="abl"></span>
							<img src="${g.goodsImg}"/>
							<span class="abr"></span>
						</dt>
						<dd>${g.goodsTitle}</dd>
						<dd><span>¥${g.goodsPrice}</span></dd>
					</dl>
				</a>
			</#list>
		</div>
	</#list>
		</div>

5.html页面

<!DOCTYPE html>
<html>
<head lang="en">
	<#include "common/head.html">
	<link rel="stylesheet" type="text/css" href="css/public.css"/>
	<link rel="stylesheet" type="text/css" href="css/index.css" />
</head>
<body>
<!------------------------------head------------------------------>
<#include "common/top.html">

<!-------------------------banner--------------------------->
<div class="block_home_slider">
	<div id="home_slider" class="flexslider">
		<ul class="slides">
			<li>
				<div class="slide">
					<img src="img/banner2.jpg"/>
				</div>
			</li>
			<li>
				<div class="slide">
					<img src="img/banner1.jpg"/>
				</div>
			</li>
		</ul>
	</div>
</div>

<!------------------------------thImg------------------------------>
<div class="thImg">
	<div class="clearfix">
		<a href="${ctx}/page/vase_proList.html"><img src="img/i1.jpg"/></a>
		<a href="${ctx}/page/proList.html"><img src="img/i2.jpg"/></a>
		<a href="#2"><img src="img/i3.jpg"/></a>
	</div>
</div>

<!------------------------------news------------------------------>
<div class="news">
	<div class="wrapper">
		<h2><img src="img/ih1.jpg"/></h2>
		<div class="top clearfix">
			<a href="${ctx}/page/proDetail.html"><img src="img/n1.jpg"/><p></p></a>
			<a href="${ctx}/page/proDetail.html"><img src="img/n2.jpg"/><p></p></a>
			<a href="${ctx}/page/proDetail.html"><img src="img/n3.jpg"/><p></p></a>
		</div>
		<div class="bott clearfix">
			<a href="${ctx}/page/proDetail.html"><img src="img/n4.jpg"/><p></p></a>
			<a href="${ctx}/page/proDetail.html"><img src="img/n5.jpg"/><p></p></a>
			<a href="${ctx}/page/proDetail.html"><img src="img/n6.jpg"/><p></p></a>
		</div>
		<h2><img src="img/ih2.jpg"/></h2>
	<#list p1 as p>
		<div class="flower clearfix tran">
			<#list p as g>
			<a href="proDetail.html" class="clearfix">
				<dl>
					<dt>
						<span class="abl"></span>
						<img src="${g.goodsImg}"/>
						<span class="abr"></span>
					</dt>
					<dd>${g.goodsTitle}</dd>
					<dd><span>¥${g.goodsPrice}</span></dd>
				</dl>
			</a>
		</#list>
		</div>
		</#list>

	</div>
</div>

<!------------------------------ad------------------------------>
<a href="#" class="ad"><img src="img/ib1.jpg"/></a>

<!------------------------------people------------------------------>
<div class="people">
	<div class="wrapper">
		<h2><img src="img/ih3.jpg"/></h2>
		<#list p2 as p>
		<div class="pList clearfix tran">
				<#list p as g>
			<a href="proDetail.html">
					<dl>
						<dt>
							<span class="abl"></span>
							<img src="${g.goodsImg}"/>
							<span class="abr"></span>
						</dt>
						<dd>${g.goodsTitle}</dd>
						<dd><span>¥${g.goodsPrice}</span></dd>
					</dl>
				</a>
			</#list>
		</div>
	</#list>
		</div>

	</div>
</div>

<#include "common/footer.html"/>

<script src="js/public.js" type="text/javascript" charset="utf-8"></script>
<script src="js/nav.js" type="text/javascript" charset="utf-8"></script>
<script src="js/jquery.flexslider-min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
	$(function() {
		$('#home_slider').flexslider({
			animation: 'slide',
			controlNav: true,
			directionNav: true,
			animationLoop: true,
			slideshow: true,
			slideshowSpeed:2000,
			useCSS: false
		});

	});
</script>
</body>
</html>

好啦,今天的分享就到这了,希望能够帮到你呢!😊😊 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/276284.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

你知道继电保护测试仪的价格是多少吗?

继电保护测试仪是电气设备检测中经常使用的检测仪器。它能准确、快速地检测到每个继电保护装置的一些潜在故障和问题&#xff0c;帮助电力检测工人锁定问题点&#xff0c;使继电保护装置能够正常工作&#xff0c;保护电力需求。继电保护测试仪贵吗&#xff1f;哪些因素影响价格…

链表:如何利用“假头,新指针,双指针”解决链表问题

Java学习面试指南&#xff1a;https://javaxiaobear.cn 链表是一种线性数据结构&#xff0c;其中的每个元素实际上是一个单独的对象&#xff0c;而所有对象都通过每个元素中的引用字段链接在一起。 链表是一种物理存储单元上非连续、非顺序的存储结构&#xff0c;其物理结构不能…

C# Winform教程(二):基础窗口程序

1、介绍 winform应用程序是一种智能客户端技术&#xff0c;我们可以使用winform应用程序帮助我们获得信息或者传输信息等。 2、常用属性 Name&#xff1a;在后台要获得前台的控件对象&#xff0c;需要使用Name属性。 Visible&#xff1a;指示一个控件是否可见、 Enable&…

基于动态窗口的航线规划

MATLAB2016b可以运行 % ------------------------------------------------------------------------- % File : DWA 算法 % Discription : Mobile Robot Motion Planning with Dynamic Window Approach % Author :Yuncheng Jiang % License : Modified BSD Software License A…

MySQL按月分片

一、按照月分片 使用场景为按照自然月来分片,每个自然月为一个分片,但是一年有12个月,是不是要有12个数据节点才行呢?并不是。例如我现在只有三个分片数据库,这样就可以1月在第一个数据分片中,2月在第二个数据分片中,3月在第三个数据分片中,当来到4月的时候,就会重新开…

echarts中给图表X轴和Y轴加单位以及给tooltip(提示框)增加单位

左边没有单位&#xff0c;右图是增加单位的效果。 1.x轴y轴设置单位 增加单位不管是x轴还是y轴都可以设置name字段&#xff0c;设置完name后效果是红色箭头效果。如果想要蓝色箭头效果可以使用x轴y轴的都有的 axisLabel 属性里面有formatter配置项&#xff0c;formatter支持字…

Python【json模块常用函数】

json模块常用函数 json模块是Python标准库中的一个内置模块&#xff0c;用于处理JSON&#xff08;JavaScript Object Notation&#xff09;格式的数据。它提供了一组函数来解析、序列化和操作JSON数据。 下面是json模块中常用的几个函数&#xff1a; .loads() 用于将JSON字…

YOLOv5-Lite 树莓派4B 15帧教程

【前言】 由于v5Lite仓库遗漏了不少历史问题&#xff0c;最大的问题是毕业后卷起来了&#xff0c;找不到时间更新。 上面是这篇博客的背景&#xff0c;那么先说下结论&#xff0c;使用 v5lite-e 模型&#xff0c;在 树莓派4B&#xff08;4G内存&#xff09; 上&#xff0c;有三…

C#高级 02异步编程

基础知识 1.什么是异步任务 包含了异步任务的各种状态的一个引用类型 1)正在运行、完成、结果、报错等 2)另有ValueTask值类型版本对于异步任务的抽象 1)开启异步任务后&#xff0c;当前线程并不会阻塞&#xff0c;而是可以去做其他事情 2)异步任务&#xff08;默认&#xff…

两张图片沿着斜对角线合并成一张图片

在图像融合领域&#xff0c;论文中的对比算法可视化&#xff0c;需要将红外图像和可见光图像沿着斜对角线合并成一张图片。 红外与可见光图像举例&#xff1a; 然后做出这样的效果&#xff1a; 用Python的PIL库&#xff0c;将两张图片沿着斜对角线合并成一张图片。 from PIL …

【Python基础篇】【19.异常处理】(附案例,源码)

异常处理 异常处理常见异常elsefinallyraise获取异常信息sys.exc_info()traceback 处理异常基本原则assert断点调试两种方式Debugger窗口各图标的含义1.Show Execution Point &#xff08;Alt F10&#xff09;2.Step Over&#xff08;F8&#xff09;3.Step Into &#xff08;F…

GBASE南大通用常用错误代码

错误代码为 GBASE南大通用Server 返回给应用的错误编号&#xff0c;用于唯一的标识一个错误。错误码在 GBaseErrorCode 枚举中定义。 下表仅提供通过 GBASE南大通用数据库返回给应用的常用错误码及错误描述的参考&#xff0c; 具体错误码请参考 GBase 数据库相关手册。

活动回顾 (下) | 机器学习系统趋势研判,大咖金句汇总

作者&#xff1a;三羊、李宝珠、李玮栋、Yudi、xixi 编辑&#xff1a;李宝珠 在大模型时代的浪潮中&#xff0c;机器学习系统正经历着前所未有的变革。模型规模的急剧膨胀&#xff0c;让我们见证了 AI 能力的巨大提升&#xff0c;然而这种提升不仅为各个领域带来了新的机遇&…

汇编语言学习中的Dosbox自动配置方法

学到期末才发现可以自动配置 一、先找到dosbox的下载/安装路径 二、打开其下的Dosbox *.**(这里是版本号) Options.bat 三、在其打开的文件的最下面输入你经常打开dosbox要输入的内容 例如&#xff1a; mount c e:\masm c:

UEFI模拟环境搭建——windows+EDKII

目录 0 说明 1 安装软件 1.1 VS2019的安装 1.2 Python的安装 1.3 IASL的安装 1.4 NASM的安装 1.5 git的下载 2 EDKII的下载 3 配置环境 0 说明 个人感觉UEFI的环境搭建非常复杂&#xff0c;在经过很长一段折磨后&#xff0c;终于还是搭建成功&#xff0c;写下来记录一…

MS761比较器可兼容MAX9030

MS761/762 是一款低噪声&#xff0c;低输入失调电压的高精度比较器&#xff0c;输入失调电压室温下典型值为 200μV&#xff0c;整个温度范围内最大为 1mV。可兼容MAX9030。MS761 有关断脚可以关闭整个器件&#xff0c;减小电流消耗。 MS761/762 具有 CMOS 输入及推挽输出&…

Python入门知识点分享——(十一)if条件语句

if条件语句是一种编程语言中用于控制程序流程的结构。它根据一个条件的真假来决定执行不同的代码块。 if条件语句通常由if关键字、一个条件表达式和一个代码块组成。条件表达式可以是一个返回布尔值的表达式&#xff0c;如果条件为真&#xff0c;则执行代码块中的代码&#xf…

C# 操作非持久化内存映射文件

目录 写在前面 代码实现 进程A 进程B 进程C 调用示例 总结 写在前面 多个进程之间&#xff0c;通过操作未映射到磁盘上现有文件的内存映射文件&#xff0c;可以实现数据共享和类似进程间通讯的功能。以下示例展示了使用三个独立进程&#xff0c;先各自将布尔值写入内存…

所有逐个位置相加的方法

989. 【加法模板】秒杀所有逐位相加 参考教程

水产行业的数字化“狂飙”:风浪越大,“鱼”越鲜美

作者 | 曾响铃 文 | 响铃说 自古以来&#xff0c;深受中国饮食文化的影响&#xff0c;消费者对水产品的需求特别强调“鲜”。从字面结构来看&#xff0c;“鲜”字以“鱼”为部首&#xff0c;这反映了中国人对于水产品“鲜美”朴素而至高的追求。 但若要完美达到“鲜”这一标…