外星人公司(狗头)委托我开发一个一个专门的外星人商城(模仿京东、天猫),出售外星人电子产品以及周边,实现了以下功能。
本项目已经搭载了服务器,网址给定:
链接: 外星人官方网站.
持久层:依据业务要求规划相关的SQL语句,以及进行配置
业务层:核心功能控制、业务操作以及异常处理
控制层:接受请求,处理响应
前端开发:JS、JQuery、Ajax
单元测试:junit
规划内容,编写sql语句
首先,查询用户是否存在
/**
* 根据用户名查询用户数据
* @param username 用户名
* @return 匹配的用户数据,如果没有匹配的数据,则返回null
*/
User findByUsername(String username);
/**
* 根据uid更新用户的密码
* @param uid 用户的id
* @param password 新密码
* @param modifiedUser 最后修改执行人
* @param modifiedTime 最后修改时间
* @return 受影响的行数
*/
Integer updatePasswordByUid(
@Param("uid") Integer uid,
@Param("password") String password,
@Param("modifiedUser") String modifiedUser,
@Param("modifiedTime") Date modifiedTime);
/*
Integer updatePasswordByUid(
Integer uid,
String password,
String modifiedUser,
Date modifiedTime); */
<!-- 根据用户名查询用户数据:User findByUsername(String username) -->
<select id="findByUsername" resultMap="UserEntityMap">
SELECT
*
FROM
compution.t_user
WHERE
username = #{username}
</select>
<!-- 根据uid更新用户的密码:
Integer updatePasswordByUid(
@Param("uid") Integer uid,
@Param("password") String password,
@Param("modifiedUser") String modifiedUser,
@Param("modifiedTime") Date modifiedTime) -->
<update id="updatePasswordByUid">
UPDATE
compution.t_user
SET
password = #{password},
modified_user = #{modifiedUser},
modified_time = #{modifiedTime}
WHERE
uid = #{uid}
</update>
/**
* 修改密码
* @param uid 当前登录的用户id
* @param username 用户名
* @param oldPassword 原密码
* @param newPassword 新密码
*/
public void changePassword(Integer uid, String username, String oldPassword, String newPassword);
@Override
public void changePassword(Integer uid, String username, String oldPassword, String newPassword) {
// 调用userMapper的findByUid()方法,根据参数uid查询用户数据
User result = userMapper.findByUid(uid);
// 检查查询结果是否为null
if (result == null) {
// 是:抛出UserNotFoundException异常
throw new UserNotFoundException("用户数据不存在");
}
// 检查查询结果中的isDelete是否为1
if (result.getIsDelete().equals(1)) {
// 是:抛出UserNotFoundException异常
throw new UserNotFoundException("用户数据不存在");
}
// 从查询结果中取出盐值
String salt = result.getSalt();
// 将参数oldPassword结合盐值加密,得到oldMd5Password
String oldMd5Password = getMd5Password(oldPassword, salt);
// 判断查询结果中的password与oldMd5Password是否不一致
if (!result.getPassword().contentEquals(oldMd5Password)) {
// 是:抛出PasswordNotMatchException异常
throw new PasswordNotMatchException("原密码错误");
}
// 将参数newPassword结合盐值加密,得到newMd5Password
String newMd5Password = getMd5Password(newPassword, salt);
// 创建当前时间对象
Date now = new Date();
// 调用userMapper的updatePasswordByUid()更新密码,并获取返回值
Integer rows = userMapper.updatePasswordByUid(uid, newMd5Password, username, now);
// 判断以上返回的受影响行数是否不为1
if (rows != 1) {
// 是:抛出UpdateException异常
throw new UpdateException("更新用户数据时出现未知错误,请联系系统管理员");
}
}
异常处理
} else if (e instanceof InsertException) {
result.setState(5000);
} else if (e instanceof UpdateException) {
result.setState(5001);
@GetMapping("get_by_uid")
public JsonResult<User> getByUid(HttpSession session) {
// 从HttpSession对象中获取uid
Integer uid = getUidFromSession(session);
// 调用业务对象执行获取数据
User data = userService.getByUid(uid);
// 响应成功和数据
return new JsonResult<User>(OK, data);
}
// public JsonResult changePassword(String oldPassword, String newPassword, HttpSession session) {
public String changePassword(String oldPassword, String newPassword, HttpSession session) {
// 调用session.getAttribute("")获取uid和username
Integer uid = getUidFromSession(session);
String username = getUsernameFromSession(session);
// 调用业务对象执行修改密码
userService.changePassword(uid, username, oldPassword, newPassword);
// 返回成功
// return new JsonResult(OK);
return "redirect:/web/login.html";
}
<form id="form-change-password" class="form-horizontal" role="form">
@RequestMapping("change_password")
<!--修改密码表单开始-->
<form id="form-change-password" class="form-horizontal" role="form">
<div class="form-group">
<label class="col-md-2 control-label">原密码:</label>
<div class="col-md-8">
<input name="oldPassword" type="text" class="form-control" placeholder="请输入原密码">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">新密码:</label>
<div class="col-md-8">
<input name="newPassword" type="text" class="form-control" placeholder="请输入新密码">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">确认密码:</label>
<div class="col-md-8">
<input type="text" class="form-control" placeholder="请再次输入新密码">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input id="btn-change-password" type="button" class="btn btn-primary" value="修改" />
</div>
</div>
</form>
ajax
<!--页脚结束-->
<script type="text/javascript">
$("#btn-change-password").click(function() {
$.ajax({
url: "/users/change_password",
type: "POST",
data: $("#form-change-password").serialize(),
dataType: "json",
success: function(json) {
if (json.state == 200) {
alert("修改成功!");
} else {
alert("修改失败!" + json.message);
}
},
error: function (xhr) {
alert("您的登录信息已经过期,请重新登录!HTTP响应码:" + xhr.status);
location.href = "login.html";
}
});
});
</script>
这里发现我对于mybatis中的判断这种不懂,需要回顾
<!-- 根据uid更新用户个人资料:Integer updateInfoByUid(User user) -->
<update id="updateInfoByUid">
UPDATE
compution.t_user
SET
<if test="phone != null">phone = #{phone},
<if test="email != null">email = #{email},
<if test="gender != null">gender = #{gender},
modified_user = #{modifiedUser},
modified_time = #{modifiedTime}
WHERE
uid = #{uid}
</update>
/**
* 根据uid更新用户资料
* @param user 封装了用户id和新个人资料的对象
* @return 受影响的行数
*/
Integer updateInfoByUid(User user);
@Override
public void changeInfo(Integer uid, String username, User user) {
// 调用userMapper的findByUid()方法,根据参数uid查询用户数据
User result = userMapper.findByUid(uid);
// 判断查询结果是否为null
if (result == null) {
// 是:抛出UserNotFoundException异常
throw new UserNotFoundException("用户数据不存在");
}
// 判断查询结果中的isDelete是否为1
if (result.getIsDelete().equals(1)) {
// 是:抛出UserNotFoundException异常
throw new UserNotFoundException("用户数据不存在");
}
// 向参数user中补全数据:uid
user.setUid(uid);
// 向参数user中补全数据:modifiedUser(username)
user.setModifiedUser(username);
// 向参数user中补全数据:modifiedTime(new Date())
user.setModifiedTime(new Date());
// 调用userMapper的updateInfoByUid(User user)方法执行修改,并获取返回值
Integer rows = userMapper.updateInfoByUid(user);
// 判断以上返回的受影响行数是否不为1
if (rows != 1) {
// 是:抛出UpdateException异常
throw new UpdateException("更新用户数据时出现未知错误,请联系系统管理员");
}
}
这里要进行异常处理
} else if (e instanceof UpdateException) {
result.setState(5001);
@RequestMapping("change_info")
public JsonResult<Void> changeInfo(User user, HttpSession session) {
// 从HttpSession对象中获取uid和username
Integer uid = getUidFromSession(session);
String username = getUsernameFromSession(session);
// 调用业务对象执行修改用户资料
userService.changeInfo(uid, username, user);
// 响应成功
return new JsonResult<Void>(OK);
}
<!--修改资料表单开始-->
<form id="form-change-info" class="form-horizontal" role="form">
<div class="form-group">
<label class="col-md-2 control-label">用户名:</label>
<div class="col-md-8">
<input id="username" type="text" class="form-control" value="孙悟空" readonly="readonly">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">电话号码:</label>
<div class="col-md-8">
<input id="phone" name="phone" type="text" class="form-control" placeholder="请输入电话号码" value="13311311313">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">电子邮箱:</label>
<div class="col-md-8">
<input id="email" name="email" type="text" class="form-control" placeholder="请输入电子邮箱" value="[email protected]">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">性别:</label>
<div class="col-md-8">
<label class="radio-inline">
<input id="gender-male" type="radio" name="gender" value="1" >男
</label>
<label class="radio-inline">
<input id="gender-female" type="radio" name="gender" value="0">女
</label>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input id="btn-change-info" type="button" class="btn btn-primary" value="修改" />
</div>
</div>
</form>
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
url: "/users/get_by_uid",
type: "GET",
dataType: "json",
success: function(json) {
if (json.state == 200) {
console.log("username=" + json.data.username);
console.log("phone=" + json.data.phone);
console.log("email=" + json.data.email);
console.log("gender=" + json.data.gender);
$("#username").val(json.data.username);
$("#phone").val(json.data.phone);
$("#email").val(json.data.email);
let radio = json.data.gender == 0 ? $("#gender-female") : $("#gender-male");
radio.prop("checked", "checked");
} else {
alert("获取用户信息失败!" + json.message);
}
}
});
});
$("#btn-change-info").click(function() {
$.ajax({
url: "/users/change_info",
type: "POST",
data: $("#form-change-info").serialize(),
dataType: "json",
success: function(json) {
if (json.state == 200) {
alert("修改成功!");
location.href = "login.html";
} else {
alert("修改失败!" + json.message);
}
},
error: function(xhr) {
alert("您的登录信息已经过期,请重新登录!HTTP响应码:" + xhr.status);
location.href = "login.html";
}
});
});
</script>
老样子,接口和sql语句
/**
* 根据uid更新用户的头像
* @param uid 用户的id
* @param avatar 新头像的路径
* @param modifiedUser 修改执行人
* @param modifiedTime 修改时间
* @return 受影响的行数
*/
Integer updateAvatarByUid(
@Param("uid") Integer uid,
@Param("avatar") String avatar,
@Param("modifiedUser") String modifiedUser,
@Param("modifiedTime") Date modifiedTime);
<!-- 根据uid更新用户的头像
Integer updateAvatarByUid(
@Param("uid") Integer uid,
@Param("avatar") String avatar,
@Param("modifiedUser") String modifiedUser,
@Param("modifiedTime") Date modifiedTime) -->
<update id="updateAvatarByUid">
UPDATE
compution.t_user
SET
avatar = #{avatar},
modified_user = #{modifiedUser},
modified_time = #{modifiedTime}
WHERE
uid = #{uid}
</update>
avatar:/upload/9c8dacd6-9f73-4c60-87ad-270eba65f24c.png
/**
* 修改用户头像
* @param uid 当前登录的用户的id
* @param username 当前登录的用户名
* @param avatar 用户的新头像的路径
*/
void changeAvatar(Integer uid, String username, String avatar);
@Override
public void changeAvatar(Integer uid, String username, String avatar) {
// 调用userMapper的findByUid()方法,根据参数uid查询用户数据
User result = userMapper.findByUid(uid);
// 检查查询结果是否为null
if (result == null) {
// 是:抛出UserNotFoundException
throw new UserNotFoundException("用户数据不存在");
}
// 检查查询结果中的isDelete是否为1
if (result.getIsDelete().equals(1)) {
// 是:抛出UserNotFoundException
throw new UserNotFoundException("用户数据不存在");
}
// 创建当前时间对象
Date now = new Date();
// 调用userMapper的updateAvatarByUid()方法执行更新,并获取返回值
Integer rows = userMapper.updateAvatarByUid(uid, avatar, username, now);
// 判断以上返回的受影响行数是否不为1
if (rows != 1) {
// 是:抛出UpdateException
throw new UpdateException("更新用户数据时出现未知错误,请联系系统管理员");
}
}
@PostMapping("change_avatar")
public JsonResult<String> changeAvatar(@RequestParam("file") MultipartFile file, HttpSession session) {
// 判断上传的文件是否为空
if (file.isEmpty()) {
// 是:抛出异常
throw new FileEmptyException("上传的头像文件不允许为空");
}
// 判断上传的文件大小是否超出限制值
if (file.getSize() > AVATAR_MAX_SIZE) { // getSize():返回文件的大小,以字节为单位
// 是:抛出异常
throw new FileSizeException("不允许上传超过" + (AVATAR_MAX_SIZE / 1024) + "KB的头像文件");
}
// 判断上传的文件类型是否超出限制
String contentType = file.getContentType();
// boolean contains(Object o):当前列表若包含某元素,返回结果为true;若不包含该元素,返回结果为false
if (!AVATAR_TYPES.contains(contentType)) {
// 是:抛出异常
throw new FileTypeException("不支持使用该类型的文件作为头像,允许的文件类型:" + AVATAR_TYPES);
}
// 获取当前项目的绝对磁盘路径
String parent = session.getServletContext().getRealPath("upload");
System.out.println(parent);
// 保存头像文件的文件夹
File dir = new File(parent);
if (!dir.exists()) {
dir.mkdirs();
}
// 保存的头像文件的文件名
String suffix = "";
String originalFilename = file.getOriginalFilename();
int beginIndex = originalFilename.lastIndexOf(".");
if (beginIndex > 0) {
suffix = originalFilename.substring(beginIndex);
}
String filename = UUID.randomUUID().toString() + suffix;
// 创建文件对象,表示保存的头像文件
File dest = new File(dir, filename);
// 执行保存头像文件
try {
file.transferTo(dest);
} catch (IllegalStateException e) {
// 抛出异常
throw new FileStateException("文件状态异常,可能文件已被移动或删除");
} catch (IOException e) {
// 抛出异常
throw new FileUploadIOException("上传文件时读写错误,请稍后重新尝试");
}
// 头像路径
String avatar = "/upload/" + filename;
// 从Session中获取uid和username
Integer uid = getUidFromSession(session);
String username = getUsernameFromSession(session);
// 将头像写入到数据库中
userService.changeAvatar(uid, username, avatar);
// 返回成功头像路径
return new JsonResult<String>(OK, avatar);
}
<!--上传头像表单开始-->
<form id="form-change-avatar" class="form-horizontal" role="form">
<div class="form-group">
<label class="col-md-2 control-label">选择头像:</label>
<div class="col-md-5">
<img id="img-avatar" src="../images/index/user.jpg" class="img-responsive" />
</div>
<div class="clearfix"></div>
<div class="col-md-offset-2 col-md-4">
<input type="file" name="file">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input id="btn-change-avatar" type="button" class="btn btn-primary" value="上传" />
</div>
</div>
</form>
<script type="text/javascript">
$(document).ready(function () {
console.log("cookie中的avatar=" + $.cookie("avatar"));
$("#img-avatar").attr("src", $.cookie("avatar"));
});
$("#btn-change-avatar").click(function() {
$.ajax({
url: "/users/change_avatar",
type: "POST",
data: new FormData($("#form-change-avatar")[0]),
dataType: "JSON",
processData: false, // processData处理数据
contentType: false, // contentType发送数据的格式
success: function(json) {
if (json.state == 200) {
$("#img-avatar").attr("src", json.data);
$.cookie("avatar", json.data, {expires: 7});
} else {
alert("修改失败!" + json.message);
}
},
error: function(xhr) {
alert("您的登录信息已经过期,请重新登录!HTTP响应码:" + xhr.status);
location.href = "login.html";
}
});
});
</script>
第一部分 加入购物车
第二部分 显示购物车
第三部分 购物车商品数量
第四部分 勾选数据