实训项目–京东商城
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();
}