后端开发:
前三部分已经可以通过接口传递给前端了,对于前端开发工程师而言,他们怎么把这个数据展示,咱们已经不用关注这个细节了。写到最后写到form表单就行了。前后端连接的技术。js或者query,Ajax。
导入基础jar包
5.在properties文件中配置数据库的连接源信息
创建实体类的基类
1.实现一个接口,再定义私有化的属性
2.私有属性的Getter和Setter部分
3.equals() and hashCode()方法自动生成出来
4.toString()方法
创建用户的实体类
需要继承BaseEntity基类
1.命名属性
2.get和set方法
3.equals和hashCode()方法
4.toString方法
3 注册-持久层
通过MyBatis来操作数据库。在做mybatis开发的流程。
3.1需要规划执行的SQL语句
1.用户的注册功能,相当于在做数据的插入操作
insert into t_user(username,password) values (值列表)
2.在用户注册时首先要去查询当前的用户名是否存在,如果存在则不能进行注册。相当于一条查询语句。(一旦检测select查询有结果的输出,在业务层提醒用户用户名被占用)
select *from t_user where username=?
3.2设计接口和抽象方法
1.定义Mapper接口 。在项目的目录结构下首先创建一个mapper包,在这个包下再根据不同的功能模块来创建mapper接口。创建一个UserMapper的接口。要在接口中定义这两个SQL语句抽象方法。
2.在启动类配置mapper接口文件的位置
//MapperScan注解指定当前项目中的Mapper接口路径的位置,在项目启动的时候会自动的加载所有的接口
@MapperScan("com.cy.mapper") //定义mapper的接口,包结构的完整路径放里面
3.3编写映射
1.定义xml映射文件,与对应的接口进行关联。所有的映射文件需要放置在resouces目录下,在这个目录下创建mapper文件夹,然后在这个文件夹存放Mapper的映射文件。
2.创建接口的映射文件,遵循和接口的名称保持一致。创建一个UserMapper.xml文件。
<?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">
<!--namespace属性:用于指定当前的映射文件和哪个接口进行映射,需要指定接口的文件路径,需要标注包的完整路径接口-->
<mapper namespace="com.cy.store.mapper.UserMapper">
</mapper>
3.配置接口中的方法对应上SQL语句上,需要借助标签来完成,insert、update、delete、select,对应的是SQL语句的增删改查操作。
3.将mapper文件的位置注册到properties对应的配置文件中
3.单元测试:每个独立的层编写完毕后需要编写单元测试方法,来测试当前的功能。在test包结构下创建一个mapper包,在这个包下再创建持久层的功能测试。
mybatis.mapper-locations=classpath:mapper/*.xml
4 注册-业务层
1.能够接收到前端,从控制器流转过来的数据
2.结合真实的注册业务,完成他功能业务逻辑的总体的调转和流程
不能只考虑真实的业务场景,不完整,在整个业务执行的过程,会出现很多的问题(异常)
4.1规划异常
在service这里实现三类:
1.类与其他层的调用,接口I
2.异常E
3.接口依赖于具体的实现类实现implements
创建ex(异常包)、impl(依赖包)、有接口的话,直接仍在最外层,即sevice下就可以了
1.RuntimeException异常(只能代表程序在运行过程中,产生了一个误操作,来触发了一个异常,可是不明确),作为这异常的子类,然后再去定义具体的异常类型来继承这个异常。业务层异常的基类,ServiceExxeption异常。这个异常继承RuntimeException异常。异常机制的建立。
package com.cy.store.service.ex;
/** 业务层异常的基类:throws new ServiceException() 第一个无参的用法,throws new ServiceException("业务层产生未知的异常") 第二个用法 ,第三个人家有可能只需要传递的是异常的对象 Throwable属于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
2.用户在进行注册的时候,可能会产生用户名被占用的错误,抛出一个异常: UsernameDuplicated Exception异常。
package com.cy.store.service.ex;
/**用户名被占用的异常*/
public class UsernameDuplicatedException extends ServiceException{ //继承ServiceException异常
//alt+ insert ----- override methods...
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);
}
}
3.正在执行数据插入操作的时候,服务器、数据库宕机。处于正在执行插入的过程中所产生的异常:InsertException
package com.cy.store.service.ex;
/**数据在插入过程中所产生的异常*/
public class InsertException extends ServiceException{//继承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);
}
}
4.2设计接口和抽象方法
1.在Service包下创建一个接口(I开头,然后后面再跟上业务的名称,如果是业务层的,然后再跟上Service)这里是:IUserService接口。接口直接放在sevice包上,里面的第一层。
package com.cy.store.service;
/**用户模块业务层接口*/
public interface IUserService {
//定义一个放法,完成注册的功能,在注册的时候需要返回值吗(在业务层是不需要的)
/**
* 用户注册方法
* @param user 用户的数据对象
*/
void reg(User user);//参数列表得看底层要什么样得数据,底层就是mapper层,执行插入得时候就是要一个对象
}
2.创建一个实现类UserServiceImpl类,需要实现这个接口,并且实现抽象的方法。
3.在单元测试包下创建一个UserServiceTests类,在这个类中添加单元测试的功能。
这时候需要在业务层添加@Service描述
登录验证的时候,用户名输入的密码进行拼接,然后三次加密后,再和数据库的密码进行比较
5 注册-控制层
5.1创建响应
状态码、状态描述信息、数据。 这部分功能封装一个类中,将这类作为方法返回值,返回给前端浏览器
/**
* Json格式的数据响应
* */
public class JsonResult<E> implements Serializable {//Serializable接口
/**状态码*/
private Integer state;
/**描述信息*/
private String message;
/**泛型数据*/
private E data;
}
5.5设计请求
依据当前的业务功能模块进行请求的设计。
请求路径:/user/reg
请求参数:user user
请求类型:POST(有敏感数据就用POST,没有就用get)
响应结果:JsonResult
5.3处理请求
1.创建一个控制层对应的类UserController类。依赖于业务层的接口。
package com.cy.store.Controller;
import com.cy.store.entity.User;
import com.cy.store.service.IUserService;
import com.cy.store.service.ex.InsertException;
import com.cy.store.service.ex.UsernameDuplicatedException;
import com.cy.store.util.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
//@Controller //当前类交给Spring来管理、
@RestController//等效于@Controller+@ResponseBody
@RequestMapping("users")
public class UserController {
@Autowired
private IUserService userService;//依赖于业务层的接口,即userService接口,然后交给Spring自动装配,最后什么样的请求被拦截在子类当中呢。
@RequestMapping("reg")
//@ResponseBody //表示此方法的响应结果以json格式进行数据的响应给到前端
//如果在这个类中编写了大量的请求处理方法,也就意味着每个类中都要编写一个ResponseBody,是很麻烦的,所以并不建议这样写,这里写组合注解
public JsonResult<Void> reg(User user){ //声明一个User对象,作为方法的参数列表,来接收前端的数据
//创建响应结果对象
JsonResult<Void> result = new JsonResult<>();
try {
userService.reg(user);//在调这个方法的时候,如果抛异常,在Code里面点Surround With 的try/catch
result.setState(200);
result.setMessage("用户名注册成功");
} catch (UsernameDuplicatedException e) { //抛的异常即我们在业务层所定义的异常,这里是两个
result.setState(4000);
result.setMessage("用户名被占用");
}
catch (InsertException e) { //抛的异常即我们在业务层所定义的异常,这里是两个
result.setState(5000);
result.setMessage("注册时产生未知的异常");
}
return result;
}
}
5.4控制层优化设计
在控制层抽离一个父类,在这个父类中统一的去处理关于异常的相关操作。编写一个BaseController类,统一处理异常。
@RequestMapping("reg")
//@ResponseBody //表示此方法的响应结果以json格式进行数据的响应给到前端
//如果在这个类中编写了大量的请求处理方法,也就意味着每个类中都要编写一个ResponseBody,是很麻烦的,所以并不建议这样写,这里写组合注解
public JsonResult<Void> reg(User user){ //声明一个User对象,作为方法的参数列表,来接收前端的数据
//创建响应结果对象
JsonResult<Void> result = new JsonResult<>();
try {
userService.reg(user);//在调这个方法的时候,如果抛异常,在Code里面点Surround With 的try/catch
result.setState(200);
result.setMessage("用户名注册成功");
} catch (UsernameDuplicatedException e) { //抛的异常即我们在业务层所定义的异常,这里是两个
result.setState(4000);
result.setMessage("用户名被占用");
}
catch (InsertException e) { //抛的异常即我们在业务层所定义的异常,这里是两个
result.setState(5000);
result.setMessage("注册时产生未知的异常");
}
return result;
}
重新构建了reg()方法。
@RequestMapping("reg")
//@ResponseBody //表示此方法的响应结果以json格式进行数据的响应给到前端
public JsonResult<Void> reg(User user){ //声明一个User对象,作为方法的参数列表,来接收前端的数据
userService.reg(user);
return new JsonResult<>(OK);
} //在这里不用考虑异常的处理,直接业务层的调用
6 注册-前端页面
1.在register页面中编写发送请求的方法,点击事件来完成。选中对应的按钮(JQuery下的)(
(
"
选
择
器
"
)
)
,
选
中
某
一
个
元
素
,
再
去
添
加
点
击
的
事
件
,
("选择器")),选中某一个元素,再去添加点击的事件,
("选择器")),选中某一个元素,再去添加点击的事件,.ajax()函数发送异步请求。
2.JQUery封装了一个函数,称之为$.ajax()函数,通过对象调用ajax()函数,可以异步加载相关的请求。依靠的是Javascript提供的一个对象XHR(XmlHttpResponse),封装了这个对象。
3.ajax()使用方式。需要传递一个方法体作为方法的参数来使用,一对大括号称之为方法体。ajax接收多个参数,参数与参数之间要求使用","进行分割,每一组参数之间使用“:”进行分割,参数的组成部分一个是参数的名称(不能随意的定义,必须要使用ajax提前为我们封装好的参数,比如说你要发送url请求,那你就发送url),是参数的值,参数的值要求使用字符串来标识。参数的声明顺序没有要求。语法结构:
$.ajax({
url:"",
type:"",
data:"",
dataType:"",
success:function(){
},
error:function(){
}
});
4.ajax()函数参数的含义:
参数: 功能描述:
url 表示请求的地址(url地址)。例如: url:“localhost:8080/users/reg”
注册网址:
http://localhost:8080/users/reg?username=test001&password=123456