Mybatis
此框架是目前最流行的数据持久层框架 , 是对JDBC代码进行了封装 , 程序员只需要通过注解或配置文件的方式提供需要执行的SQL语句 , 框架会自动根据SQL语句生成出JDBC代码 , 从而提高执行效率
如何使用Mybatis框架?
创建boot2-2工程 , 创建工程时需要勾选3个依赖分别是:
a. Web —> Spring Web
b. SQL —> Mybatis Framework
c. SQL —> MySQL Driver
在application.properties配置文件中书写连接数据库的信息
spring.datasource.url =jdbc:mysql://localhost:3306/empdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false spring.datasource.username =root spring.datasource.password =root
User package cn.tedu.boot22.entity;public class User { private Integer id; private String username; private String password; private String nickname; public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } public String getPassword () { return password; } public void setPassword (String password) { this .password = password; } public String getNickname () { return nickname; } public void setNickname (String nickname) { this .nickname = nickname; } @Override public String toString () { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", nickname='" + nickname + '\'' + '}' ; } }
Hero package cn.tedu.boot22.entity;public class Hero { private Integer id; private String name; private Integer money; public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public Integer getMoney () { return money; } public void setMoney (Integer money) { this .money = money; } @Override public String toString () { return "Hero{" + "id=" + id + ", name='" + name + '\'' + ", money=" + money + '}' ; } }
创建index页面 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <h1 > 首页</h1 > <a href ="/add.html" > 添加英雄</a > <a href ="/delete.html" > 删除英雄</a > <a href ="/select" > 查询英雄</a > </body > </html >
创建add页面 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <h1 > 添加英雄页面</h1 > <form action ="/add" > <input type ="text" name ="name" placeholder ="英雄名" > <input type ="text" name ="money" placeholder ="英雄价格" > <input type ="submit" value ="添加" > </form > </body > </html >
创建delete页面 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <h1 > 请输入要删除的英雄名称</h1 > <form action ="/delete" > <input type ="text" name ="name" > <input type ="submit" value ="删除" > </form > </body > </html >
创建接口 HeroMapper package cn.tedu.boot22.mapper;import cn.tedu.boot22.entity.Hero;import org.apache.ibatis.annotations.*;import java.util.List;@Mapper public interface HeroMapper { @Insert("insert into hero values(null,#{name},#{money})") void insert (Hero hero) ; @Delete("delete from hero where name = #{name}") void deleteByName (String name) ; @Select("select * from hero") List<Hero> select () ; @Update("update hero set name = #{name},money = #{money} where id = #{id}") void update (Hero hero) ; }
创建update页面 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <h1 > 修改英雄页面</h1 > <form action ="/update" > <input type ="text" name ="id" placeholder ="请输入修改的id" > <input type ="text" name ="name" placeholder ="名字" > <input type ="text" name ="money" placeholder ="价格" > <input type ="submit" value ="修改" > </form > </body > </html >
创建HeroController package cn.tedu.boot22.controller;@Controller public class HeroController { @Autowired(required = false) HeroMapper mapper; @RequestMapping("add") @ResponseBody public String add (Hero hero) { System.out.println("hero:" +hero); mapper.insert(hero); return "添加完成" ; } @RequestMapping("delete") @ResponseBody public String delete (String name) { mapper.deleteByName(name); return "删除完成" ; } @RequestMapping("select") @ResponseBody public String select () { List<Hero> list = mapper.select(); return list.toString(); } @RequestMapping("update") @ResponseBody public String update (Hero hero) { mapper.update(hero); return "修改完成" ; } }
Mybatis框架添加英雄步骤:
创建boot2-2, 添加三个依赖
在application.properties配置文件中添加内容
停止之前工程, 运行新工程测试是否能正常运行
创建index.html 页面里面添加超链接 , 添加英雄 , 访问地址为add.html
创建add.html页面里面添加form表单 , 请求地址为 /add
创建controller.HeroController, 里面添加@Controller注解,添加@RequestMapping注解处理 /add请求并添加add方法,
创建entity.Hero实体类 并提供get和set方法 还有tostring方法
在HeroController的add方法参数列表中声明Hero对象 , 用来接收传递过来的参数 ,此时打桩输出hero对象 检查是否接收到了参数
创建mapper.HeroMapper接口, 里面添加@Mapper注解, 声明一个insert方法通过@Insert注解修饰,注解里面添加插入数据的SQL语句
在HeroController里面 通过@Autowired注解把HeroMapper装配进来, 在add方法里面调用mapper.insert方法把接收到的hero对象传递进去, 重启工程测试即可!
删除英雄步骤:
在首页中添加删除英雄超链接 访问地址为 delete.html
创建delete.html页面 在里面添加form表单 提交地址为/delete
在HeroController 中创建delete方法 处理路径为/delete 参数列表中声明name 接收页面传递过来的名字
在HeroMapper里面添加deleteByName方法 通过@Delete注解修饰,里面填写 删除的SQL语句
在HeroController里面的delete方法中调用mapper的deleteByName方法
修改英雄步骤:
在首页添加修改英雄超链接, 地址为update.html页面
创建update.html页面 并添加form表单 提交地址为/update
在Controller中添加update方法 处理/update请求
在HeroMapper里面添加update方法 通过@Update注解进行修饰,里面添加修改的SQL语句
在HeroController里面的update方法中调用mapper的update方法把接收到的hero对象传递到方法中
查询英雄步骤:
在首页添加查询的超链接,请求地址为/select
在HeroController中添加select方法处理/select请求
在HeroMapper里面添加select方法用@Select注解进行修饰,里面写查询的SQL语句
在HeroController的select方法中 调用mapper的select方法,把查询到的List集合返回给客户端展示
商品表的增删改查
use empdb; create table product(id int primary key auto_increment,title varchar (100 ),price double (10 ,2 ),sale_count int )charset= utf8;
创建boot3-1工程 , 添加三个依赖
从之前工程中复制application.properties配置文件的信息到新工程, 启动工程测试是否成功
创建index.html
<!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <h1 > 商品管理首页</h1 > <a href ="/insert.html" > 添加商品</a > <a href ="/select" > 查询商品</a > <a href ="/update.html" > 修改商品</a > <hr > <a href ="/helloAxios.html" > 异步请求测试</a > </body > </html >
创建insert.html
<!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <h1 > 添加商品页面</h1 > <form action ="/insert" > <input type ="text" name ="title" placeholder ="商品标题" > <input type ="text" name ="price" placeholder ="商品价格" > <input type ="text" name ="saleCount" placeholder ="商品销量" > <input type ="submit" value ="添加" > </form > </body > </html >
创建update.html
<!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <h1 > 修改商品页面</h1 > <form action ="/update" > <input type ="text" name ="id" placeholder ="请输入修改商品的id" > <input type ="text" name ="title" placeholder ="商品标题" > <input type ="text" name ="price" placeholder ="商品价格" > <input type ="text" name ="saleCount" placeholder ="商品销量" > <input type ="submit" value ="修改" > </form > </body > </html >
创建ProductController
package cn.tedu.boot31.controller;@RestController public class ProductController { @Autowired ProductMapper mapper; @RequestMapping("insert") public String insert (Product product) { mapper.insert(product); return "添加完成!<a href='/'>返回首页</a>" ; } @RequestMapping("select") public String select () { List<Product> list = mapper.select(); String html = "<table border=1>" ; html+="<caption>商品列表</caption>" ; html+="<tr><th>id</th><th>标题</th><th>价格</th><th>销量</th><th>操作</th></tr>" ; for (Product p : list) { html+="<tr>" ; html+="<td>" +p.getId()+"</td>" ; html+="<td>" +p.getTitle()+"</td>" ; html+="<td>" +p.getPrice()+"</td>" ; html+="<td>" +p.getSaleCount()+"</td>" ; html+="<td><a href='/delete?id=" +p.getId()+"'>删除</a></td>" ; html+="</tr>" ; } html+="</table>" ; return html; } @RequestMapping("delete") public String delete (int id) { mapper.deleteById(id); return "删除完成!<a href='/select'>返回列表页面</a>" ; } @RequestMapping("update") public String update (Product product) { mapper.update(product); return "修改完成<a href='/select'>返回列表页面</a>" ; } }
创建Product
package cn.tedu.boot31.entity;public class Product { private Integer id; private String title; private Double price; private Integer saleCount; public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public String getTitle () { return title; } public void setTitle (String title) { this .title = title; } public Double getPrice () { return price; } public void setPrice (Double price) { this .price = price; } public Integer getSaleCount () { return saleCount; } public void setSaleCount (Integer saleCount) { this .saleCount = saleCount; } @Override public String toString () { return "Product{" + "id=" + id + ", title='" + title + '\'' + ", price=" + price + ", saleCount=" + saleCount + '}' ; } }
创建ProductMapper
package cn.tedu.boot31.mapper;@Mapper public interface ProductMapper { @Insert("insert into product values(null,#{title},#{price},#{saleCount})") void insert (Product product) ; @Select("select * from product") @Result(column = "sale_count",property = "saleCount") List<Product> select () ; @Delete("delete from product where id = #{id}") void deleteById (int id) ; @Update("update product set title = #{title},price = #{price},sale_count=#{saleCount} where id = #{id}") void update (Product product) ; }
同步请求和异步请求
同步 : 指单线程依次做几件事
异步 : 指多线程同时做几件事
同步请求 : 指客户端浏览器只有一个主线程, 此线程负责页面的渲染和发出请求等操作, 如果此主线程发出请求的话则停止渲染而且会清空页面显示的内容 , 直到服务器响应了数据后才能再次显示, 由于主线程清空了原有显示的内容所以只能实现页面的整体刷新(整体改变)
异步请求 : 指客户端的主线程只负责页面渲染相关操作,发请求的事儿由新的子线程操作, 这样子线程发出请求时页面不需要清空 , 而且可以将查询回来的数据展示在原有页面基础之上, 这样实现的效果就叫做页面的局部刷新
客户端发出请求的几种方式
通过浏览器的地址栏中发出请求 同步请求
通过html页面中的超链接发出请求 同步请求
通过html页面中的form表单发出请求 同步请求
通过前端框架发出请求 异步请求
客户端如何发出异步请求
通过Axios框架发出异步请求
此框架就是一个普通的js文件 , 页面需要使用此框架时需要将此文件引入到页面中
axios框架地址 , 下载axios.min.js文件
<script src ="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js" > </script >
static目录下创建js目录 , 将axios.min.js和vue.js放入此目录中
<!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <div > <h1 > {{info}}</h1 > <input type ="button" value ="测试异步请求get" @click ="f1()" > <input type ="button" value ="测试异步请求post" @click ="f2()" > </div > <script src ="js/vue.js" > </script > <script src ="js/axios.min.js" > </script > <script > let v = new Vue ({ el :"div" , data :{ info :"测试Vue!" }, methods :{ f1 ( ){ axios.get ("/hello1Axios?info=tom" ).then (function (response ) { alert (response.data ); }) }, f2 ( ){ axios.post ("/hello2Axios" ,{info :"刘德华" }).then (function (response ) { alert (response.data ); }) } } }) </script > </body > </html >
AxiosController package cn.tedu.boot31.controller;@RestController public class AxiosController { @RequestMapping("hello1Axios") public String hello1 (String info) { return "请求成功! info=" +info; } @RequestMapping("hello2Axios") public String hello2 (@RequestBody String info) { return "请求成功! info=" +info; } }
Get请求和Post请求
从字面意思理解 , Get是向服务器要数据 , Post是给服务器传数据
Get : 请求参数写在请求地址的后面(可见) , 请求参数有大小限制只能传几k的数据(不能处理文件上传)
应用场景 : 查询请求一般都会使用get , 删除也会使用get请求
Post : 请求参数放在请求体里面(不可见) , 参数没有大小限制
应用场景 : 文件上传 , 带有敏感信息的请求(比如注册登录时有密码)
注册登录步骤 :
创建工程boot3-2 , 添加三个依赖
从之前工程中复制application.properties里面的连接数据库的信息 , 复制完之后立即启动工程 , 测试是否创建成功 , 如果工程启动不起来 , 检查报错是不是因为端口被占用 , 如果不是 , 刷新maven再次启动 , 如果还是启动不了 , 删除工程重新创建新工程 , 直至启动成功
创建index.html页面 , 在里面添加两个超链接访问注册和登录页面
创建reg.html页面 , 在页面中引入vue和axios两个框架文件 , 从之前工程中复制js文件夹(检查里面是不是包含这两个框架文件) , 在页面中点击按钮时向/reg发出异步请求 , 同时把用户输入的信息提交给服务器,然后在then方法里面判断返回的response.data值为1代表注册成功 , 显示首页 , 值为2代表用户名已存在
创建controller.UserController并且创建entity.User实体类
在Controller里面添加reg方法处理/reg请求 , 声明User变量用来接收传递过来的用户信息
创建mapper.UserMapper , 在里面提供两个方法 , 分别是 selectByUsername和insert两个方法
回到Controller里面把UserMapper通过@Autowired装配进来 , 在reg方法中先调用mapper里面的selectByUsername方法 , 判断返回值是否有值 , 如果有值则给客户端返回2代表用户名已存在 , 如果没有值 , 则调用mapper的insert方法 , 把用户信息保存到数据库 , 最后返回1代表注册成功
下一步开始实现登录功能 , 步骤类似注册 , 先创建login.html页面 , 然后在页面中通过Vue对内容进行管理 , 当点击登录按钮的时候向/login发出异步请求 , 同样把输入的用户信息提交给服务器 , 在then方法中判断response.data的值为1代表登录成功显示首页 , 值为2代表用户名不存在, 值为3代表密码错误
在Controller里面添加login方法处理/login请求 , 声明User对象接收传递过来的用户信息 , 在方法中调用mapper的selectByUsername 通过用户输入的用户名查询对应的用户信息 , 如果没有查询到 , 直接返回2代表用户名不存在 , 如果查询到了 , 继续通过输入的密码和查询到的密码比较如果一致返回1代表登录成功 , 如果不一致返回2 , 代表密码错误.
index.html <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <h1 > 工程首页</h1 > <a href ="/reg.html" > 注册</a > <a href ="/login.html" > 登录</a > </body > </html >
将上个项目中的js目录复制到新项目中的static目录下
reg.html <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <h1 > 注册页面</h1 > <div > <input type ="text" v-model ="user.username" placeholder ="请输入用户名" > <input type ="text" v-model ="user.password" placeholder ="请输入密码" > <input type ="text" v-model ="user.nickname" placeholder ="请输入昵称" > <input type ="button" value ="注册" @click ="reg()" > </div > <script src ="js/vue.js" > </script > <script src ="js/axios.min.js" > </script > <script > let v = new Vue ({ el :"div" , data :{ user :{ username :"" , password :"" , nickname :"" } }, methods :{ reg ( ){ axios.post ("/reg" ,v.user ).then (function (response ) { if (response.data == 1 ) { alert ("注册成功!" ); location.href ="/" ; }else { alert ("用户名已存在!" ) } }) } } }) </script > </body > </html >
login.html <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > <h1 > 登录页面</h1 > <div > <input type ="text" v-model ="user.username" placeholder ="用户名" > <input type ="text" v-model ="user.password" placeholder ="密码" > <input type ="button" value ="登录" @click ="login()" > </div > <script src ="js/vue.js" > </script > <script src ="js/axios.min.js" > </script > <script > let v = new Vue ({ el :"div" , data :{ user :{ username :"" , password :"" } }, methods : { login ( ) { axios.post ("/login" ,v.user ).then (function (response ) { if (response.data == 1 ) { alert ("登录成功!" ); location.href ="/" ; }else if (response.data == 2 ){ alert ("用户名不存在!" ) }else { alert ("密码错误!" ); } }) } } }) </script > </body > </html >
UserController package cn.tedu.boot32.controller;@RestController public class UserController { @Autowired UserMapper mapper; @RequestMapping("reg") public int reg (@RequestBody User user) { User u = mapper.selectByUsername(user.getUsername()); if (u != null ) { return 2 ; } mapper.insert(user); return 1 ; } @RequestMapping("login") public int login (@RequestBody User user) { User u = mapper.selectByUsername(user.getUsername()); if (u != null ) { if (user.getPassword().equals(u.getPassword())) { return 1 ; } return 3 ; } return 2 ; } }
User实体类 package cn.tedu.boot32.entity;public class User { private Integer id; private String username; private String password; private String nickname; public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } public String getPassword () { return password; } public void setPassword (String password) { this .password = password; } public String getNickname () { return nickname; } public void setNickname (String nickname) { this .nickname = nickname; } @Override public String toString () { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", nickname='" + nickname + '\'' + '}' ; } }
UserMapper package cn.tedu.boot32.mapper;@Mapper public interface UserMapper { @Select("select * from user where username = #{username}") User selectByUsername (String username) ; @Insert("insert into user values(null,#{username},#{password},#{nickname})") void insert (User user) ; }