实例一:实现注册和登录功能
首页:
Title
工程首页
注册
登录
注册页面:
Title
注册页面
登录页面:
Title
登录页面
功能实现类;
@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;//代表用户名不存在
}
}
mapper类:
@Mapper
public interface UserMapper {
//如果返回值为一个对象而非List集合 要求查询回来的结果必须是0条或者1条
//如果出现了大于1条的情况会报错
@Select("select *from user where username=#{username}")
User selectByUsername(String username);
@Insert("insert into user values(null,#{username},#{password},#{nick})")
void insert(User user);
}
User类:
后端的MVC设计模式
- 把实现一个业务的代码划分为三部分,分别是: 页面相关(V),业务逻辑相关(C),数据相关(M)
- M:Model 数据模型, 对应的代码是数据库相关的Mapper部分
- V:View 视图, 对应所有页面相关内容
- C:Controller 控制器,对应的是Controller相关代码
- 实现一个业务的顺序: V页面相关代码->C Controller相关代码->M 数据库Mapper相关代码
- 排错时也是从这三部分代码中找问题
- 后端MVC涉及模式中的V页面相关,前端工程师将页面又划分为了MVC三部分
前后端分离
如果前后端不分离, 后端服务器需要两套代码来应对 手机客户端和浏览器客户端, 因为不同的客户端的需求内容是不一样的,这样后端的开发效率就会受影响.
前后端分离:指在Controller中不再处理页面相关内容, 浏览器客户端需要先请求页面,页面加载完之后从页面中再次发出请求获取数据, 得到数据后把数据展示在页面中,这个过程属于页面的局部刷新, 同步请求只能实现页面的整体刷新无法实现局部刷新, 所以以后不再使用同步请求, 全部使用异步请求,因为以后工作基本全是前后端分离思想.
JSON
- JSON是一种轻量级的数据交换格式(数据封装格式)
- 客户端和服务器之间需要互相传递数据,当需要传递复杂数据时需要按照特定的格式将数据进行封装,JSON就是这样一个通用格式.
登录成功
用户名已存在
密码错误
1
2
3
"id=1, title=手机 , price=1000, saleCount=500"
[{"id":1,"title":"阿迪袜子","price":10.0,"saleCount":1000},{"id":3,"title":"裤子","price":50.0,"saleCount":400},{"id":4,"title":"袜子","price":5.0,"saleCount":100}]
服务器和客户端之间如何传递复杂数据
商品管理添加商品步骤:
1、创建工程 3个打钩 修改application.properties配置文件, 启动工程测试是否成功
2、创建index.html首页 和 insert.html页面
3、在insert.html页面中添加三个文本框和一个添加按钮, 通过Vue对页面内容进行管理,此时需要把之前工程中的js文件夹复制到新工程, 当点击添加按钮时向/insert地址发出异步post请求把用户输入的商品信息提交
4、创建controller.ProductController 添加insert方法处理/insert请求 创建Product实体类 在insert方法中声明用来接收传递过来的参数(此参数需要通过@RequestBody注解进行修饰
5、创建ProductMapper 在里面添加insert方法通过@Insert注解修饰
6、在Controller中将ProductMapper装配进来, 在insert方法中调用mapper的insert方法把接收到的Product对象传递过去
商品管理商品列表步骤:
1、在index.html页面中添加商品列表超链接 请求地址为/list.html页面
2、创建list.html页面, 在页面中添加表格,并且通过Vue进行管理,在Vue的created方法中发出异步的get请求,把请求回来的数据交给一个数组变量, 然后让页面中表格的内容和数据变量进行绑定, 当数组有值时页面会自动显示数据
3、在ProductController中添加select方法 处理/select请求,方法中调用mapper的select方法 把得到的List集合直接返回给客户端
4、实现 mapper里面的select方法
商品管理删除商品步骤:
1、在商品列表页面中添加删除的超链接 ,废掉超链接的跳转功能添加点击事件,调用del方法, 在方法中向/delete发出异步get请求并且把商品的id传递过去
2、在ProductController中 添加delete方法处理/delete请求在方法中调用mapper的deleteById方法把接收到的id传递进去
3、实现mapper里面的deleteById方法
商品管理修改商品步骤:
1、给列表页面添加 修改超链接 往/update.html页面跳转 并且传递过去商品id
2、创建update.html页面 在Vue的created方法中得到传递过来的id 然后向/selectById 发出异步的get请求 把id传递过去 把服务返回的数据用一个product对象接收, 并且页面内容和此对象进行绑定 这样对象有值页面就能跟着显示
3、在ProductController里面添加selectById方法 处理/selectById请求, 在方法中调用Mapper的selectById方法
4、实现mapper里面的selectById方法
5、给update.html页面中的修改按钮添加点击事件, 点击时向/update地址发出异步的post请求把商品的信息一起提交
6、在ProductController里面添加update方法处理/update请求,在方法中掉用mapper的update方法
7、实现mapper里面的update方法 .
实例二:商品管理实例
首页:
Title
商品管理首页
添加商品
商品列表
添加商品页面:
Title
添加商品
商品列表页面:
Title
商品列表
| 商品id | 商品标题 | 商品价格 | 商品销量 | 操作 |
|---|---|---|---|---|
| {{p.id}} | {{p.title}} | {{p.price}} | {{p.saleCount}} | 删除 修改 |
修改商品页面:
Title
修改商品页面
ProductController功能实现类:
import java.util.List;
@RestController
public class ProductController {
@Autowired
ProductMapper mapper;
@RequestMapping("/insert")
public void insert(@RequestBody Product product){
System.out.println(product.toString());
mapper.insert(product);
}
@RequestMapping("/select")
public List select(){
// SpringMVC框架当发现返回值类型为集合或自定义的对象类型时,
//会将集合或对象转成JSON格式的字符串,然后再将JSON格式字符串转成二进制数据进行网络传输
//[{"id":1,"title":"阿迪袜子","price":10.0,"saleCount":1000},{"id":3,"title":"裤子","price":50.0,"saleCount":400},{"id":4,"title":"袜子","price":5.0,"saleCount":100}]
List list = mapper.select();
return list;
}
@RequestMapping("/delete")
public void delete(int id){
System.out.println("id = "+id);
mapper.deleteById(id);
}
@RequestMapping("/selectById")
public Product selectById(int id){
System.out.println("id = "+id);
//当SpringMVC框架发现返回的是一个自定义对象会自动转成JSDN格式的字符串
return mapper.selectById(id);
}
@RequestMapping("/update")
public void update(@RequestBody Product product){
mapper.update(product);
}
}
Product类:
mapper类:
import java.util.List;
@Mapper
public interface ProductMapper {
@Insert("insert into product values(null,#{title},#{price},#{saleCount})")
void insert(Product product);
@Select("select *from product")
@Result(property = "saleCount",column = "sale_count")
List select();
@Delete("delete from product where id=#{id}")
void deleteById(int id);
@Select("select *from product where id=#{id}")
@Result(property = "saleCount",column = "sale_count")
Product selectById(int id);
@Update("update product set title=#{title},price=#{price},sale_count=#{saleCount} where id=#{id}")
void update(Product product);
}
实例三:实现文件上传功能
首页:
@RestController
public class UploadController {
@RequestMapping("/upload")
public String upload(MultipartFile picFile) throws IOException {
System.out.println("picFile = " + picFile);
//得到文件原始文件名 a.jpg
String fileName = picFile.getOriginalFilename();
//得到后缀名 从最后一个.出现的位置截取到最后
String suffix = fileName.substring(fileName.lastIndexOf("."));
//得到唯一文件名 UUID.randomUUID()得到一个唯一标识符
fileName = UUID.randomUUID()+suffix;
System.out.println("文件名:"+fileName);
//准备保存图片的文件夹路径
String dirPath = "F:/files";
File dirFile = new File(dirPath);
//如果该文件夹不存在 则创建此文件夹
if (!dirFile.exists()){
dirFile.mkdirs();//创建文件夹
}
//得到文件的完整路径
String filePath = dirPath+"/"+fileName;
//把文件保存到此路径 异常抛出
picFile.transferTo(new File(filePath));
System.out.println("文件保存完成! 请去此路径检查文件是否存在 "+filePath);
return fileName;
}
@RequestMapping("/remove")
public void remove(String name){
String dirPath = "F:/files";
String filePath = dirPath+"/"+name;
new File(filePath).delete();//删除文件
}
}
微博练习步骤
1、创建boot5-1工程 3个打钩
2、配置文件中添加以下内容(empdb改成weibo) ,并启动工程检查是否能够成功运行
spring.datasource.username=root spring.datasource.password=root spring.datasource.url=jdbc:mysql://localhost:3306/weibo?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false spring.servlet.multipart.max-file-size=10MB
3、创建数据库和表
create database weibo charset=utf8;
use weibo;
create table user(id int primary key auto_increment,username varchar(50),password varchar(50),nick varchar(50))charset=utf8;
4、在工程中添加首页index.html 在工程中添加js和css文件夹(从4-2工程中复制),添加完之后 Buil->ReBuild
5、创建微博表
use weibo;
create table weibo(id int primary key auto_increment,content varchar(100),url varchar(255),nick varchar(50),created timestamp,user_id int)charset=utf8;
会话管理
1、客户端和服务器之间进行数据传输遵循的是HTTP协议,此协议属于无状态协议(一次请求对应一次响应,响应完之后链接就会断开) 服务器是无法跟踪客户端的请求.通过Cookie服务器可以给客户端添加一个标识,当客户端再次发出请求时会带着这个Cookie这样服务器就能识别此客户端了, 但是由于Cookie是保存在客户端的存在被篡改的风险,Session的出现解决了此问题
2、Cookie: 打孔式会员卡, 数据保存在客户端
- 只能保存字符串数据
- 默认数据是保存在浏览器内存中,当会话结束(浏览器关闭)数据会删除, 也可以设置自定义的保存时长,设置完之后数据会保存在磁盘中时间到了之后清除.
- 应用场景: 需要长时间保存的数据,比如:记住用户名和密码
3、Session:相当于银行卡, 数据保存在服务器内存中(工程重新启动会清空所有Session)
- 可以保存任意对象类型的数据
- 默认数据只能保存半小时左右,而且不建议修改保存时长,因为数据是保存在服务器的内存中的, 服务器只有一个所以不能占用太多的内存.
- 应用场景: 保存登录状态,涉及敏感数据,因为数据保存在服务器会更安全
如何通过Session对象记住登录状态
1、在登录成功时把当前客户端登录的user用户对象保存到当前客户端所对应的Session对象里面,
2、每个客户端进入到首页index.html时会立即发请求获取当前客户端登录的用户对象, 服务器接收到请求后会从当前客户端所对应的Session对象里面获取曾经保存过的用户对象(前提是登陆过),如果没有登录直接获取得到的是null返回给客户端,此时客户端得到的是""空字符串, 客户端判断是否是空字符来表示是否登录过, 通过给isLogin赋值true或false来控制页面显示的内容
实例:微博练习:
微博首页:
Title
微博首页
欢迎{{user.nick}}回来!
发布微博
登出
注册
登录
注册页面:
Title
注册页面
登录页面:
Title
登录
实现注册登录功能的功能类:
@RestController
public class UserController {
@Autowired
UserMapper mapper;
@RequestMapping("/reg")
public int reg(@RequestBody User user){
System.out.println("user="+user.toString());
User u = mapper.selectByUsername(user.getUsername());
if(u!=null){
return 2;
}
mapper.insert(user);
return 1;
}
//在参数列表里面声明session 即可得到当前客户端所对应的Session
@RequestMapping("/login")
public int login(@RequestBody User user, HttpSession session){
User u = mapper.selectByUsername(user.getUsername());
if(u!=null){
if(u.getPassword().equals(user.getPassword())){
//把当前登录的用户对象保存到会话对象中
//user代表用户输入的信息包括:用户名和密码
//u代表从数据库中查询到的信息 包括:id 用户名 密码 昵称
session.setAttribute("user",u);
return 1;
}
return 2;
}
return 3;
}
@RequestMapping("/currentUser")
public User currentUser(HttpSession session){
//从会话对象中得到登陆成功是保存的用户对象
User u = (User) session.getAttribute("user");
return u;
}
@RequestMapping("/logout")
public void logout(HttpSession session){
//把登陆成功是保存的user对象删除
session.removeAttribute("user");
}
}
UserMapper类:
@Mapper
public interface UserMapper {
@Insert("insert into user values(null,#{username},#{password},#{nick})")
void insert(User user);
@Select("select *from user where username=#{username}")
User selectByUsername(String username);
}
发布微博页面:
发布微博页面
实现文件上传及删除的功能类:
@RestController
public class UploadController {
@RequestMapping("/upload")
public String upload(MultipartFile picFile) throws IOException {
System.out.println("picFile = " + picFile);
//得到文件原始文件名 a.jpg
String fileName = picFile.getOriginalFilename();
//得到后缀名 从最后一个.出现的位置截取到最后
String suffix = fileName.substring(fileName.lastIndexOf("."));
//得到唯一文件名 UUID.randomUUID()得到一个唯一标识符
fileName = UUID.randomUUID()+suffix;
System.out.println("文件名:"+fileName);
//准备保存图片的文件夹路径
String dirPath = "F:/files";
File dirFile = new File(dirPath);
//如果该文件夹不存在 则创建此文件夹
if (!dirFile.exists()){
dirFile.mkdirs();//创建文件夹
}
//得到文件的完整路径
String filePath = dirPath+"/"+fileName;
//把文件保存到此路径 异常抛出
picFile.transferTo(new File(filePath));
System.out.println("文件保存完成! 请去此路径检查文件是否存在 "+filePath);
return fileName;
}
@RequestMapping("/remove")
public void remove(String name){
String dirPath = "F:/files";
String filePath = dirPath+"/"+name;
new File(filePath).delete();//删除文件
}
}
实现发布微博功能类:
@RestController
public class WeiboController {
@Autowired
WeiboMapper mapper;
@RequestMapping("/insert")
public int insert(@RequestBody Weibo weibo, HttpSession session){
//得到当前登录的的用户对象
User u = (User)session.getAttribute("user");
if(u==null){
return 2;//代表未登录
}
//new Date()得到当前的系统时间
weibo.setCreated(new Date());
//把当前登录的用户信息 添加到weibo对象中
weibo.setUserId(u.getId());
weibo.setNick(u.getNick());
System.out.println("weibo="+weibo);
mapper.insert(weibo);
return 1;//代表微博发布成功
}
}
WeiboMapper类:
@Mapper
public interface WeiboMapper {
@Insert("insert into weibo values(null,#{content},#{url},#{nick},#{created},#{userId})")
void insert(Weibo weibo);
}



