网站怎么办,航班网站开发设计说明书,螺蛳粉的软文推广,济南网络推广公司排名#x1f9f8;安清h#xff1a;个人主页 #x1f3a5;个人专栏#xff1a;【计算机网络】【Mybatis篇】
#x1f6a6;作者简介#xff1a;一个有趣爱睡觉的intp#xff0c;期待和更多人分享自己所学知识的真诚大学生。 目录
#x1f3af;项目基本介绍
#x1f6a6;项… 安清h个人主页 个人专栏【计算机网络】【Mybatis篇】
作者简介一个有趣爱睡觉的intp期待和更多人分享自己所学知识的真诚大学生。 目录
项目基本介绍
项目功能
开发顺序
模块的开发
项目的开发环境 搭建项目 用户注册
1.选中数据表
2.创建t_user表
3.创建用户实体类 ✨创建BaseEntity ✨创建实体类User
4.注册-持久层
✨规划需要执行的sql语句
✨设计接口和抽象方法
✨编写映射
5.注册-业务层
✨5.1规划异常
5.1.1RuntimeException异常
5.1.2用户名被占用异常
5.1.3数据插入异常
✨ 5.2设计接口和抽象方法
6.注册-控制层
✨6.1创建响应
✨6.2设计请求
✨6.3处理请求
✨6.4控制层优化设计
7.注册-前端页面 项目基本介绍
项目功能
本项目主要实现功能为登录注册热销商品用户管理密码个人信息头像收货地址购物车展示增加删除订单模块。
开发顺序
注册登录用户管理购物车商品订单模块。
模块的开发
持久层开发依据前端页面的设置规划相关的SQL语句以及进行配置。业务层开发核心功能的控制业务的操作以及异常的处理。控制层开发接受请求处理响应。前端开发JS,QUERY,AJAX等技术连接后台
项目的开发环境 1.JDK1.8及以上版本 2.maven:配置到idea3.6.1版本 3.数据库Mysql要求5.1及以上版本 4.开发的平台idea开发 搭建项目
1.项目的名称store表示商城
2.结构com.cy.store
3.资源文件resources文件夹下static、templates)
4.单元测试test.com.cy.store
5.
6.点击next后先选择以下三个jar包。
1WEBSpring Web用于前后端连接
2SQLMybatis Framework
3SQLMySQL Driver用于mysql数据库驱动
7.在properties文件中配置数据库的连接源信息
spring.datasource.urljdbc:mysql://localhost:3306/store?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/Shanghai
spring.datasource.usernameroot
spring.datasource.passwordroot
8.创建一个store数据库
create database store character set utf8;
9.测试连接
启动SpringBoot主类是否有对应的Spring图形输出
在src-main-java-com.cy.store-StoreApplication启动main方法得到如下图形即为启动成功
在单元测试类中测试数据库的连接是否可以正常加载
如果出现了以下图片中的Hikari则代表成功。Hikari是用来管理数据库的连接对象。 10.访问项目的静态资源是否可以正常加载。所有的静态资源复制static目录下。 注意idea对于JS代码的兼容性较差编写了js代码但是有时候不能够正常去加载。 idea缓存清理clear-install双击clean后再次install rebuild重新构建重启idea和操作系统 用户注册
1.选中数据表
use store
2.创建t_user表
CREATE TABLE t_user (uid INT AUTO_INCREMENT COMMENT 用户id,username VARCHAR(20) NOT NULL UNIQUE COMMENT 用户名,password CHAR(32) NOT NULL COMMENT 密码,salt CHAR(36) COMMENT 盐值,phone VARCHAR(20) COMMENT 电话号码,email VARCHAR(30) COMMENT 电子邮箱,gender INT COMMENT 性别:0-女1-男,avatar VARCHAR(50) COMMENT 头像,is_delete INT COMMENT 是否删除0-未删除1-已删除,created_user VARCHAR(20) COMMENT 日志-创建人,created_time DATETIME COMMENT 日志-创建时间,modified_user VARCHAR(20) COMMENT 日志-最后修改执行人,modified_time DATETIME COMMENT 日志-最后修改时间,PRIMARY KEY (uid)
) ENGINEInnoDB DEFAULT CHARSETutf8; salt盐值在用户注册时对其密码进行加密操作重要性别用阿拉伯数字0和1来表示性别原因在于前端不太好用文字来展示一个人的性别性别是单选框一半给一个整数好去操作和判断。is_delete大部分厂商都没有实现真正的删除只是在登录的时候做一个校验来检测是否为0如果不为0就表示已经删除了。四个基础字段任何一张表都有的将其作为整个实体类。 created_user VARCHAR(20) COMMENT ‘创建人’, created_time DATETIME COMMENT ‘创建时间’, modified_user VARCHAR(20) COMMENT ‘修改人’, modified_time DATETIME COMMENT ‘修改时间’, 3.创建用户实体类 ✨创建BaseEntity
实体基类里面存放的为所有表的公共字段。
public class BaseEntity implements Serializable {private String createdUser;private Date createdTime;private String modifiedUser;private Date modifiedTime;
}//get和set方法、equals和hashCode()方法、toString方法 ✨创建实体类User
public class User extends BaseEntity implements Serializable {private Integer uid;private String username;private String password;private String salt;private String phone;private String email;private Integer gender;private String avatar;private Integer isDelete;//get和set方法、equals和hashCode()方法、toString方法
}
4.注册-持久层
通过Mybatis来操作数据库。在做mybatis开发的流程。
✨规划需要执行的sql语句
1.用户的注册功能相当于在做数据的插入操作。
insert into t_user(username,password) values(值列表)
2.在用户注册时首先要去查询当前的用户名是否存在如果存在则不能进行注册。相当于是一条查询语句。
select * from t_user where username?
✨设计接口和抽象方法
1.定义Mapper接口。在项目的目录结构下首先创建一个mapper包在这个包下再根据不同的功能模块来创建mapper接口。创建一个UserMapper的接口。要在接口中定义这两个SQL语句的抽象方法。
public interface UserMapper {
// 插入用户的数据
// param user 用户的数据
// return 受影响的行数增删改都受影响的行数作为返回值可以根据返回值来判断是否执行成功Integer insert(User user);// 根据用户名来查询用户的数据
// param username 用户名
// return 如果找到对应的用户则返回这个用户的数据如果没有找到则返回null值User findByUsername(String username);
}
2.在启动类配置mapper接口文件的位置
//MapperScan注解指定当前项目中的Mapper接口路径的位置在项目启动时会自动加载所有的接口
MapperScan(com.cy.store.mapper)
✨编写映射
1.定义xml映射文件与对应的接口进行关联。所有的映射文件需要放置在resources目录下在这个目录下创建一个mapper文件夹然后在这个文件夹存放Mapper的映射文件。
2.创建接口对应的映射文件遵循和接口的名称保持一致即可。创建一个UserMapper.xml的文件。
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
!--namespace属性用于指定当前的映射文件和哪个接口进行映射需要指定接口的文件路径需要标注包的完整路径接口--
mapper namespacecom.cy.store.mapper.UserMapper/mapper 3.配置接口中的方法对应上SQL语句。需要借助标签来完成insert/update/delete/select对应的是SQL语句的增删改查操作。
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
!--namespace属性用于指定当前的映射文件和哪个接口进行映射需要指定接口的文件路径需要标注包的完整路径接口--
mapper namespacecom.cy.store.mapper.UserMapper
!-- resultMap标签来完成映射规则的定义--resultMap idUserEntityMap typecom.cy.store.entity.User
!-- 配合完成名称不一致的映射column表中的字段名称property类中的属性名称
--
!-- 在定义映射规则时主键是不可以省略的--id columnuid propertyuid/idresult columnis_delete propertyisDelete/resultresult columncreated_user propertycreatedUser/resultresult columncreated_time propertycreatedTime/resultresult columnmodified_user propertymodifiedUser/resultresult columnmodified_time propertymodifiedTime/result/resultMap!-- id属性表示映射的接口中方法的名称直接在标签的内部来编写SQL语句--
!-- useGeneratedKeys:开启某个字段的值递增主键设为递增--
!-- keyProperty将表中那个字段作为主键进行递增--insert idinsert useGeneratedKeystrue keyPropertyuidinsert into t_user(username,password,salt,phone,email,gender,avatar,is_delete,created_user,created_time,modified_user,modified_time)values (#{username},#{password},#{salt},#{phone},#{email},#{gender},#{avatar},#{isDelete},#{createdUser},#{createdTime},#{modifiedUser},#{modifiedTime})/insertselect idfindByUsername resultMapUserEntityMapselect * from t_user where username#{username}/select
/mapper
4.将mapper文件的位置注册到properties对应的配置文件中在application.properties文件中添加如下代码
mybatis.mapper-locationsclasspath:mapper/*.xml5.单元测试每个独立的层编写完毕后需要编写单元测试方法来测试当前功能。在test包接口下创建一个mapper包在这个包下创建一个持久层的测试。
//SpringBootTest标注当前的类是一个测试类不会随同项目一块打包
SpringBootTest
public class UserMapperTests {Autowiredprivate UserMapper userMapper;
// 单元测试方法可以单独独立运行不用启动整个项目提高了代码运行效率
// 1.必须被Test注解修饰
// 2.返回值类型必须是void
// 3.方法的参数类型不指定任何类型
// 4.方法的访问修饰符必须是publicTestpublic void insert(){User usernew User();user.setUsername(tim);user.setPassword(123);Integer rowsuserMapper.insert(user);System.out.println(rows);}Testpublic void findByUsername(){User useruserMapper.findByUsername(tim);System.out.println(user);}
}
5.注册-业务层
✨5.1规划异常
5.1.1RuntimeException异常
作为这异常的子类然后再去定义具体的异常类型来继承这个异常。业务层异常的基类ServiceException异常。这个异常继承RuntimeException异常。异常机制的建立。
//业务层异常的基类
public class ServiceException extends RuntimeException{public ServiceException() {super();}public ServiceException(String message) {super(message);}public ServiceException(String message, Throwable cause) {super(message, cause);}public ServiceException(Throwable cause) {super(cause);}protected ServiceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);}
}
根据业务层不同的功能来详细定义具体的异常的类型统一的去继承ServiceException异常类。
5.1.2用户名被占用异常
用户在进行注册时可能会产生用户名被占用的错误抛出一个异常UsernameDuplicatedException异常。
//用户名被占用的异常
public class UsernameDuplicatedException extends ServiceException{public UsernameDuplicatedException() {super();}public UsernameDuplicatedException(String message) {super(message);}public UsernameDuplicatedException(String message, Throwable cause) {super(message, cause);}public UsernameDuplicatedException(Throwable cause) {super(cause);}protected UsernameDuplicatedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);}
}
altinsert打开快捷方式选中前五个如图 5.1.3数据插入异常
正在执行数据插入操作的时候服务器数据库宕机。处于正在执行插入的过程中所产生的异常InsertException异常。
//数据在插入过程中产生的异常
public class InsertException extends ServiceException{public InsertException() {super();}public InsertException(String message) {super(message);}public InsertException(String message, Throwable cause) {super(message, cause);}public InsertException(Throwable cause) {super(cause);}protected InsertException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);}
}
✨ 5.2设计接口和抽象方法
1.在service包下创建一个IUserService接口。
//用户模块业务层接口
public interface IUserService {void reg(User user);
}2.创建一个实现类UserServiceImpl类需要实现这个接口并且实现抽象的方法。
//用户模块业务层的实现类
Service
public class UserServiceImpl implements IUserService {Autowiredprivate UserMapper userMapper;Overridepublic void reg(User user) {
// 通过user参数来获取传递过来的usernameString username user.getUsername();//调用findByUsername(username)判断用户是否被注册过User result userMapper.findByUsername(username);
// 判断结果集是否不为null则抛出用户名被占用的异常if(result !null){throw new UsernameDuplicatedException(用户名被占用);}
// 密码加密处理的实现md5算法的形式
// 串password串------md5算法进行加密连续加载三次
// 盐值password盐值------盐值就是一个随机的字符串String oldPassword user.getPassword();
// 获取盐值随机生成一个盐值String salt UUID.randomUUID().toString().toUpperCase();
// 补全数据盐值的记录user.setSalt(salt);
// 将密码和盐值作为一个整体进行加密处理忽略原有密码的强度提升了数据的安全性String md5Password getMD5Password(oldPassword,salt);
// 将加密之后的密码重新补全设置到user对象中user.setPassword(md5Password);// 补全数据is_delete设置成0user.setIsDelete(0);
// 补全数据四个日志字段信息user.setCreatedUser(user.getUsername());user.setModifiedUser(user.getUsername());Date datenew Date();user.setCreatedTime(date);user.setModifiedTime(date);// 执行注册业务功能的实现(rows1)Integer rowsuserMapper.insert(user);if(rows!1){throw new InsertException(在用户注册过程中产生了未知的异常);}}
// 定义一个md5算法的加密处理private String getMD5Password(String password,String salt){
// md5加密算法方法的调用进行三次加密for(int i0;i3;i){passwordDigestUtils.md5DigestAsHex((saltpasswordsalt).getBytes()).toUpperCase();}
// 返回加密之后的密码return password;}
}3.在单元测试包下创建一个UserServiceTests类在这个类中添加单元测试的功能。
//SpringBootTest标注当前的类是一个测试类不会随同项目一块打包
SpringBootTest
public class UserServiceTests {Autowiredprivate IUserService userService;
// 单元测试方法可以单独独立运行不用启动整个项目提高了代码运行效率
// 1.必须被Test注解修饰
// 2.返回值类型必须是void
// 3.方法的参数类型不指定任何类型
// 4.方法的访问修饰符必须是publicTestpublic void reg(){try {User usernew User();user.setUsername(yuanxin01);user.setPassword(123);userService.reg(user);System.out.println(OK);} catch (ServiceException e) {
// 获取类的对象再获取类的名称System.out.println(e.getClass().getSimpleName());
// 获取异常的具体描述信息System.out.println(e.getMessage());}}}
6.注册-控制层
✨6.1创建响应
状态码、状态描述信息、数据。这部分功能封装一个类中将这类作为方法返回值返回给前端浏览器。
//Json格式的数据进行响应
public class JsonResultE implements Serializable {
// 状态码private Integer state;
// 描述信息private String message;
// 数据private E data;public JsonResult(Integer state) {this.state state;}public JsonResult(Throwable e) {this.message e.getMessage();}public JsonResult(Integer state, E data) {this.state state;this.data data;}public Integer getState() {return state;}public void setState(Integer state) {this.state state;}public String getMessage() {return message;}public void setMessage(String message) {this.message message;}public E getData() {return data;}public void setData(E data) {this.data data;}
}✨6.2设计请求 依据当前的业务功能模块进行请求设计。
请求路径/users/reg
请求参数user user
请求类型POST
响应结果JsonResultvoid
✨6.3处理请求
1.创建一个控制层对应的类UserController类。依赖于业务层的接口。
RestController //ControllerRequestBody
RequestMapping(users)
public class UserController {Autowiredprivate IUserService userService;RequestMapping(reg)// RequestBody //表示此方法的响应结果以json格式进行数据的响应给到前端public JsonResultVoid reg(User user){JsonResultVoid resultnew JsonResult();try {userService.reg(user);result.setState(200);result.setMessage(用户注册成功);} catch (UsernameDuplicatedException e) {result.setState(4000);result.setMessage(用户名被占用);}catch (InsertException e) {result.setState(5000);result.setMessage(注册时产生未知的异常);}return result;}
}
✨6.4控制层优化设计
在控制层抽离一个父类在这个父类中统一的去处理关于异常的操作。编写一个BaseController类统一处理异常。
//控制层类的基类
public class BaseController{
// 操作成功的状态码public static final int OK200;
// 充当请求处理方法这个方法的返回值就是需要传递给前端的数据
// 自动将异常对象传递给此方法的参数列表上
// 当项目中产生了异常会被统一的拦截到此方法中这个方法此时就充当请求处理方法方法的返回值直接给到前端ExceptionHandler(ServiceException.class) //用于统一处理抛出的异常public JsonResultVoid handleException(Throwable e){JsonResultVoid resultnew JsonResult(e);if(e instanceof UsernameDuplicatedException){result.setState(4000);result.setMessage(用户名已经被占用);}else if(e instanceof InsertException){result.setState(5000);result.setMessage(注册时产生未知的异常);}return result;}
} 重新构建了reg()方法。
RestController //ControllerRequestBody
RequestMapping(users)
public class UserController extends BaseController{Autowiredprivate IUserService userService;RequestMapping(reg)public JsonResultVoid reg(User user){userService.reg(user);return new JsonResult(OK);}
}
7.注册-前端页面
1.在register页面中编写发送请求的方法点击事件来完成。选中对应的按钮$(选择器))再去添加点击的事件$.ajax()函数发送异步请求。
2.JQuery封装了一个函数称之为$.ajax()函数通过对象调用ajax可以异步加载相关的请求。ajax可以把某一部分的局部看做成一个独立的整体。依靠的是javascript提供的一个对象XHR(XmlHttpResponse)封装了这个对象。
3..ajax()使用方式。需要传递一个方法作为方法的参数使用一对大括号称之为方法体。ajax接收多个参数参数与参数之间要使用,分割每一组参数之间使用“”进行分割参数的组成部分一个是参数的名称不能随意定义是参数的值参数的值要求用字符串来表示。参数的声明顺序没有要求。语法结构
$.ajax({url:,type:,data:,dataType:,success:function(){},error:function(){}
});
4.ajax()函数参数的含义
参数功能描述url标识请求的地址url地址不能包含参数列表部分的内容。例如url:localhost:8080/users/regtype请求类型GET和POST请求的类型。例如type:POSTdata向指定的请求url地址提交的数据。例如data:usernametompwd123dataType提交的数据类型。数据的类型一般指定为json类型。dataType:jsonsuccess当服务器正常响应客户端时会自动调用success参数方法并且将服务器返回的数据以参数的形式传递给这个方法的参数上error当服务器未正常响应客户端时会自动调用error参数的方法并且将服务器返回的数据以参数的形式传递给这个方法的参数上
5.js代码可以独立声明在一个js文件里或者声明在一个script标签中。
script//1.监听注册按钮是否被点击如果被点击可以执行一个方法$(#btn-reg).click(function () {// 2.发送ajax()的异步请求来完成用户的注册功能$.ajax({url: /users/reg,type: POST,data: $(#form-reg).serialize(),dataType: JSON,success: function (json) { if (json.state 200) {alert(注册成功)} else {alert(注册失败)}},error: function (xhr) { alert(注册时产生未知的错误!xhr.status);}});});/script 6.js代码无法正常被服务器解析执行体现在点击页面中的按钮没有任何响应。解决方案
在项目的maven下clear清理项目-install重新部署在项目的file选项下-cash清理缓存重新的去构建项目build选项下-rebuild选项重启idea重启电脑