实训项目

实训项目–京东商城

1.项目目标

a.商品分类列表展示
b.商品分类新增
c.七牛云文件上传
d.登录业务
e.验证码
f.记住密码
g.腾讯滑动验证
h.单点登录

2.京东商城项目概要设计

在这里插入图片描述

3.京东商城项目详细设计

在这里插入图片描述
在这里插入图片描述

4、门户系统商品分类列表展示

在这里插入图片描述

5、管理员系统商品分类列表展示

在这里插入图片描述

6、商品分类新增功能实现

在这里插入图片描述

7、登录相关功能实现

在这里插入图片描述
在这里插入图片描述

8、单点登录功能实现

在这里插入图片描述

9.具体功能设计与实现

01.商品分类列表展示功能的设计与实现
 @Service
@Transactional
public class GoodsCategoryServiceImpl implements GoodsCategoryService {

    @Autowired
    private GoodsCategoryMapper goodsCategoryMapper;

    @Override
    public List<GoodsCategory> selectGoodsCategoryList() {
        //return selectGoodsCategoryListPlanA();
        return selectGoodsCategoryListPlanB();
    }

    // 查询商品分类列表 方案二
    private List<GoodsCategory> selectGoodsCategoryListPlanB() {
        // 查询所有分类信息
        List<GoodsCategory> gcList = goodsCategoryMapper.selectGoodsCategoryListPlanB();
        System.out.println(gcList.size());
        // 按照父 id 进行分组
        Map<Short, List<GoodsCategory>> groupMap = gcList.stream()
                .collect(Collectors.groupingBy(GoodsCategory::getParentId));
        // 查询下级分类并设置至父级
        gcList.forEach(g -> g.setChildren(groupMap.get(g.getId())));
        // 返回一级分类
        return gcList.stream().filter(g -> 1 == g.getLevel()).collect(Collectors.toList());
    }

    // 查询商品分类列表 方案一
    private List<GoodsCategory> selectGoodsCategoryListPlanA() {
        // 查询一级分类
        List<GoodsCategory> gcList01 = goodsCategoryMapper.selectGoodsCategoryListPlanA((short) 0);
        // 循环查询下级
        gcList01.forEach(g01 -> {
            // 查询二级
            List<GoodsCategory> gcList02 = goodsCategoryMapper.selectGoodsCategoryListPlanA(g01.getId());
            // 循环查询下级
            gcList02.forEach(g02 -> {
                // 查询三级并将三级集合设置至二级分类
                g02.setChildren(goodsCategoryMapper.selectGoodsCategoryListPlanA(g02.getId()));
            });
            g01.setChildren(gcList02);
               });
        return gcList01;
    }
02.管理员系统商品分类列表的设计与实现
@Service
public class GoodsCategoryServiceImpl implements GoodsCategoryService {

    @Autowired
    private GoodsCategoryMapper goodsCategoryMapper;

    @Override
    public List<GoodsCategory> selectGoodsCategoryList() {
        //return selectGoodsCategoryListPlanA();
        return selectGoodsCategoryListPlanB();
    }

    // 根据父 id 查询下级分类
    @Override
    public List<GoodsCategory> selectGoodsCategoryListByParentId(Short parentId) {
        return goodsCategoryMapper.selectGoodsCategoryListPlanA(parentId);
    }

    // 商品分类新增
    @Override
    public BaseResult goodsCategorySave(GoodsCategory goodsCategory) {
        int result = goodsCategoryMapper.goodsCategorySave(goodsCategory);
        return result > 0 ? BaseResult.success() : BaseResult.error();
    }

    // 查询商品分类列表 方案二
    private List<GoodsCategory> selectGoodsCategoryListPlanB() {
        // 查询所有分类信息
        List<GoodsCategory> gcList = goodsCategoryMapper.selectGoodsCategoryListPlanB();
        System.out.println(gcList.size());
        // 按照父 id 进行分组
        Map<Short, List<GoodsCategory>> groupMap = gcList.stream()
                .collect(Collectors.groupingBy(GoodsCategory::getParentId));
        // 查询下级分类并设置至父级
        gcList.forEach(g -> g.setChildren(groupMap.get(g.getId())));
        // 返回一级分类
        return gcList.stream().filter(g -> 1 == g.getLevel()).collect(Collectors.toList());
    }

    // 查询商品分类列表 方案一
    private List<GoodsCategory> selectGoodsCategoryListPlanA() {
        // 查询一级分类
        List<GoodsCategory> gcList01 = goodsCategoryMapper.selectGoodsCategoryListPlanA((short) 0);
        // 循环查询下级
        gcList01.forEach(g01 -> {
            // 查询二级
            List<GoodsCategory> gcList02 = goodsCategoryMapper.selectGoodsCategoryListPlanA(g01.getId());
            // 循环查询下级
            gcList02.forEach(g02 -> {
                // 查询三级并将三级集合设置至二级分类
                g02.setChildren(goodsCategoryMapper.selectGoodsCategoryListPlanA(g02.getId()));
            });
            g01.setChildren(gcList02);
        });
        return gcList01;
    }

}
03.商品分类新增功能的设计与实现
package com.shsxt.result;

import com.shsxt.enums.BaseResultEnum;

import java.io.Serializable;

/**
 * @see(功能介绍) : 公共保存状态返回对象
 * @version(版本号) : 1.0
 * @author(创建人) : Mrhelloworld
 * @since : JDK 1.8
 */
public class BaseResult implements Serializable {
    // 状态编码
    private Integer code;
    // 状态描述
    private String message;

    //成功返回的对象
    public static BaseResult success() {
        BaseResult result = new BaseResult();
        result.setCode(BaseResultEnum.SUCESS.getCode());
        result.setMessage(BaseResultEnum.SUCESS.getMessage());
        return result;
    }

    //失败返回的对象
    public static BaseResult error() {
        BaseResult result = new BaseResult();
        result.setCode(BaseResultEnum.ERROR.getCode());
        result.setMessage(BaseResultEnum.ERROR.getMessage());
     return result;
    }

    public BaseResult(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public BaseResult() {
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public String toString() {
        return "BaseResult [code=" + code + ", message=" + message + "]";
    }
}
<insert id="goodsCategorySave" parameterType="GoodsCategory">
    insert into t_goods_category (name, parent_id, level)
    values (#{name}, #{parentId}, #{level});
</insert>
// 商品分类新增
@Override
public BaseResult goodsCategorySave(GoodsCategory goodsCategory) {
    int result = goodsCategoryMapper.goodsCategorySave(goodsCategory);
    return result > 0 ? BaseResult.success() : BaseResult.error();
}
/**
 * 商品分类新增
 *
 * @param goodsCategory
 * @return
 */
@PostMapping("/category/save")
@ResponseBody
public BaseResult categorySave(GoodsCategory goodsCategory) {
    return goodsCategoryService.goodsCategorySave(goodsCategory);
}

04.登录相关功能的设计与实现
package com.shsxt.util;

import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;

import com.tencentcloudapi.captcha.v20190722.CaptchaClient;

import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultRequest;
import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultResponse;
/** * 腾讯验证码工具类 */ 
public class DescribeCaptchaResult {
    public static DescribeCaptchaResultResponse check(String ticket, String randstr) {
        try {

            Credential cred = new Credential("AKID6z10Z9rJ1jFYcRDiMkk2skMT081f9Xmp", "nNvFJJCrGew98sIahcVGo8C6nAHNjrjL");

            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("captcha.tencentcloudapi.com");

            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);

            CaptchaClient client = new CaptchaClient(cred, "ap-shanghai", clientProfile);

            String params = "{\"CaptchaType\":9,\"Ticket\":\"" + ticket + "\",\"UserIp\":\"127.0.0.1\",\"Randstr\":\"" + randstr + "\",\"CaptchaAppId\":2034243261,\"AppSecretKey\":\"0NMM2K9E-LGH21uBzQJ5MEw**\"}";
            DescribeCaptchaResultRequest req = DescribeCaptchaResultRequest.fromJsonString(params, DescribeCaptchaResultRequest.class);

            return client.DescribeCaptchaResult(req);
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
        }
        return null;
    }

}
package com.shsxt.util;

import org.apache.tomcat.util.codec.binary.Base64;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * MD5加密工具类
 */
public class Md5Util {

    public static String encode(String password, String salt) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("md5");
            return Base64.encodeBase64String(messageDigest.digest((password + salt).getBytes()));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        System.out.println(encode("123456", "ac2d"));
    }

}
package com.mrhelloworld.manager.controller;
import com.google.code.kaptcha.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
/**
* @description(功能介绍) : 生成图形验证码
* @version(版本号) : 1.0
* @author(创建人) : Mrhelloworld
* @since : JDK 1.8
*/
@Controller
@RequestMapping("/kaptcha")
public class KaptchaController {
 @Autowired
 private Producer kaptchaProducer;
 @RequestMapping("/getKaptchaImage")
 public void getKaptchaImage(HttpServletRequest request,
HttpServletResponse response)
 throws IOException {
 // 生成验证码文本内容
 String code = kaptchaProducer.createText();
 System.out.println("验证码:" + code);
 // 将验证码存入 session
 request.getSession().setAttribute("code", code);
// 根据验证码文本内容创建图形验证码
 BufferedImage bi = kaptchaProducer.createImage(code);
 try (ServletOutputStream out = response.getOutputStream()) {
 // 写出图形验证码格式为 jpg
 ImageIO.write(bi, "jpg", out);
 }
 }
}

/**
* 用户登录
*
* @param request
* @param response
* @param code
* @param username
* @param password
* @return
*/
BaseResult selectUserByUsername(HttpServletRequest request, HttpServletResponse response,
 String code, String username, String password);
/**
* 用户登录
*
* @param request
* @param response
* @param code
* @param username
* @param password
* @return
*/
@Override
public BaseResult selectUserByUsername(HttpServletRequest request, HttpServletResponse
response,
 String code, String username, String password) {
 // 验证是否一致
 String sessionCode = (String) request.getSession().getAttribute("code");
 if (!sessionCode.equals(code))
 return new BaseResult(400, "验证码不一致");
 // 根据用户名查询用户
 User user = userMapper.selectUserByUsername(username);
 // 用户不存在返回错误信息
 if (null == user)
 return new BaseResult(400, "用户名不存在");
 // 用户存在校验密码是否一致
 if (!user.getPassword().equals(Md5Util.encode(password, user.getSalt())))
 return new BaseResult(400, "密码输入错误");
 // 用户名密码正确
 return BaseResult.success();
}
/**
* 用户登录
*
* @param request
* @param response
* @param code
* @param username
* @param password
* @return
*/
@PostMapping("/login")
@ResponseBody
public BaseResult userLogin(HttpServletRequest request, HttpServletResponse response,
 String code, String username, String password) {
 return userService.selectUserByUsername(request, response, code, username, password);
}
package com.mrhelloworld.manager.util;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
* @description(功能介绍) : Cookie 工具类
* @version(版本号) : 1.0
* @author(创建人) : Mrhelloworld
* @since : JDK 1.8
*/
public final class CookieUtil {
 /**
 * 得到 Cookie 的值, 不编码
 *
 * @param request
 * @param cookieName
 * @return
 */
 public static String getCookieValue(HttpServletRequest request, String
cookieName) {
 return getCookieValue(request, cookieName, false);
 }
 /**
 * 得到 Cookie 的值,
 *
 * @param request
 * @param cookieName
 * @return
 */
 public static String getCookieValue(HttpServletRequest request, String
cookieName, boolean isDecoder) {
 Cookie[] cookieList = request.getCookies();
 if (cookieList == null || cookieName == null) {
 return null;
 }
 String retValue = null;
 try {
 for (int i = 0; i < cookieList.length; i++) {
 if (cookieList[i].getName().equals(cookieName)) {
 if (isDecoder) {
 retValue = URLDecoder.decode(cookieList[i].getValue(), 
"UTF-8");
 } else {
 retValue = cookieList[i].getValue();
 }
 break;
 }
 }
 } catch (UnsupportedEncodingException e) {
 e.printStackTrace();
 }
 return retValue;
 }
 /**
 * 得到 Cookie 的值,
 *
 * @param request
 * @param cookieName
 * @return
 */
 public static String getCookieValue(HttpServletRequest request, String
cookieName, String encodeString) {
 Cookie[] cookieList = request.getCookies();
 if (cookieList == null || cookieName == null) {
 return null;
 }
 String retValue = null;
 try {
 for (int i = 0; i < cookieList.length; i++) {
 if (cookieList[i].getName().equals(cookieName)) {
 retValue = URLDecoder.decode(cookieList[i].getValue(),
encodeString);
 break;
 }
 }
 } catch (UnsupportedEncodingException e) {
 e.printStackTrace();
 }
 return retValue;
 }
 /**
 * 设置 Cookie 的值 不设置生效时间默认浏览器关闭即失效,也不编码
 */
 public static void setCookie(HttpServletRequest request, HttpServletResponse
response, String cookieName,
 String cookieValue) {
 setCookie(request, response, cookieName, cookieValue, -1);
 }
 /**
 * 设置 Cookie 的值 在指定时间内生效,但不编码
 */
 public static void setCookie(HttpServletRequest request, HttpServletResponse
response, String cookieName,
 String cookieValue, int cookieMaxage) {
 setCookie(request, response, cookieName, cookieValue, cookieMaxage,
false);
 }
 /**
 * 设置 Cookie 的值 不设置生效时间,但编码
 */
 public static void setCookie(HttpServletRequest request, HttpServletResponse
response, String cookieName,
 String cookieValue, boolean isEncode) {
 setCookie(request, response, cookieName, cookieValue, -1, isEncode);
 }
 /**
 * 设置 Cookie 的值 在指定时间内生效, 编码参数
 */
 public static void setCookie(HttpServletRequest request, HttpServletResponse
response, String cookieName,
 String cookieValue, int cookieMaxage, boolean
isEncode) {
 doSetCookie(request, response, cookieName, cookieValue, cookieMaxage,
isEncode);
 }
 /**
 * 设置 Cookie 的值 在指定时间内生效, 编码参数(指定编码)
 */
 public static void setCookie(HttpServletRequest request, HttpServletResponse
response, String cookieName,
 String cookieValue, int cookieMaxage, String
encodeString) {
 doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, 
encodeString);
 }
 /**
 * 删除 Cookie 带 cookie 域名
 */
 public static void deleteCookie(HttpServletRequest request,
HttpServletResponse response,
 String cookieName) {
 doSetCookie(request, response, cookieName, "", -1, false);
 }
 /**
 * 设置 Cookie 的值,并使其在指定时间内生效
 *
 * @param cookieMaxage cookie 生效的最大秒数
 */
 private static final void doSetCookie(HttpServletRequest request,
HttpServletResponse response,
 String cookieName, String cookieValue, int
cookieMaxage, boolean isEncode) {
 try {
 if (cookieValue == null) {
 cookieValue = "";
 } else if (isEncode) {
 cookieValue = URLEncoder.encode(cookieValue, "utf-8");
 }
 Cookie cookie = new Cookie(cookieName, cookieValue);
 if (cookieMaxage > 0)
 cookie.setMaxAge(cookieMaxage);
 if (null != request) {// 设置域名的 cookie
 String domainName = getDomainName(request);
 System.out.println(domainName);
 if (!"localhost".equals(domainName)) {
 cookie.setDomain(domainName);
 }
 }
 cookie.setPath("/");
 response.addCookie(cookie);
 } catch (Exception e) {
 e.printStackTrace();
 }
 }
 /**
 * 设置 Cookie 的值,并使其在指定时间内生效
 *
 * @param cookieMaxage cookie 生效的最大秒数
 */
 private static final void doSetCookie(HttpServletRequest request,
HttpServletResponse response,
 String cookieName, String cookieValue, int
cookieMaxage, String encodeString) {
 try {
 if (cookieValue == null) {
 cookieValue = "";
 } else {
 cookieValue = URLEncoder.encode(cookieValue, encodeString);
 }
 Cookie cookie = new Cookie(cookieName, cookieValue);
 if (cookieMaxage > 0)
 cookie.setMaxAge(cookieMaxage);
 if (null != request) {// 设置域名的 cookie
 String domainName = getDomainName(request);
 System.out.println(domainName);
 if (!"localhost".equals(domainName)) {
 cookie.setDomain(domainName);
 }
 }
 cookie.setPath("/");
 response.addCookie(cookie);
 } catch (Exception e) {
 e.printStackTrace();
 }
 }
 /**
 * 得到 cookie 的域名
 */
 private static final String getDomainName(HttpServletRequest request) {
 String domainName = null;
 // 通过 request 对象获取访问的 url 地址
 String serverName = request.getRequestURL().toString();
 if (serverName == null || serverName.equals("")) {
 domainName = "";
 } else {
 // 将 url 地下转换为小写
 serverName = serverName.toLowerCase();
 // 如果 url 地址是以 http://开头 将 http://截取
 if (serverName.startsWith("http://")) {
 serverName = serverName.substring(7);
 }
 int end = serverName.length();
 // 判断 url 地址是否包含"/"
 if (serverName.contains("/")) {
 //得到第一个"/"出现的位置
 end = serverName.indexOf("/");
 }
 // 截取
 serverName = serverName.substring(0, end);
 // 根据"."进行分割
 final String[] domains = serverName.split("\\.");
 int len = domains.length;
 if (len > 3) {
 // www.xxx.com.cn
 domainName = domains[len - 3] + "." + domains[len - 2] + "." +
domains[len - 1];
 } else if (len <= 3 && len > 1) {
 // xxx.com or xxx.cn
 domainName = domains[len - 2] + "." + domains[len - 1];
 } else {
 domainName = serverName;
 }
 }
 if (domainName != null && domainName.indexOf(":") > 0) {
 String[] ary = domainName.split("\\:");
 domainName = ary[0];
 }
 return domainName;
 }
}
05.单点登录功能的设计与实现
public BaseResult userLogin(String ticket, String randstr,
                            HttpServletRequest request, HttpServletResponse response,
                            String remember, String code, String username, String password) {
    // 旧版本的登录方法
    //return userService.userLogin(ticket, randstr, request, response, remember, code, username, password);

    // 单点登录的方法
    // 构建请求参数
    MultiValueMap<String, Object> postData = new LinkedMultiValueMap<String, Object>();
    postData.add("username", username);
    postData.add("password", password);
    // 请求服务器地址,请求参数,返回值类型
    // 登录成功返回票据信息
    String userTicket = restTemplate.postForObject("http://localhost:9092/sso/login", postData, String.class);
    // 将票据信息存入 cookie
    if (null == userTicket) return new BaseResult(400, "系统错误,请刷新页面重新登录或联系管理员");
    CookieUtil.setCookie(request, response, "USERTICKET", userTicket);
    return BaseResult.success();
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值