restful风格设计API的特点:
1)使用JSON来进行传递数据
2)使用不同的HTTP方法来进行描述不同的操作
3)使用HTTP状态码来进行表示返回结果是否正确
4)使用路径表示要进行操作的资源是什么
1)创建一个SpringBoot项目
2)编写对应的配置文件,数据库的配置文件
3)编写对应的SQL语句:
当时我们工大有一家店叫做吉祥馄沌,老板还是使用手工记账的方式来进行记账,我就和老板商量了一下要做一个点餐系统出来
drop database if exists OrderDish; create database if not exists OrderDish; use OrderDish; drop table if exists User; create table User( userID int primary key auto_increment, userName varchar(50), passWord varchar(100), isAdmin int default 0 ); drop table if exists Dish; create table Dish( dishID int primary key auto_increment, dishName varchar(50), dishMoney int ); drop table if exists Order_User; create table Order_User( orderID int primary key auto_increment, userID int, isDown int, orderTime timeStamp, foreign key Order_User(userID) references User(userID) ); drop table if exists Order_Dish; create table order_Dish( orderID int, dishID int, foreign key(orderID) references Order_User(orderID), foreign key(dishID) references Dish(dishID) );
4)创建对应的实体类
@Data public class Dish { private int dishID; private String dishName; private String dishMoney; } @Data public class Order { private int orderID; private int userID; private List<Integer> dishList; private int isDown; private Timestamp timestamp; } @Data public class User { private int userID; private String userName; private String passWord; private int isAdmin; }
约定前后端交互的接口:
1){}表示一个JSON对象,他是一个键值对结构,里面包含了若干个键值对,键值对之间使用,进行分割,键和值之间使用:来进行分割,这里面的键必须是字符串
2.[]用来表示一个数组,里面包含了若干个元素,每一个元素可以是整数,字符串,或者是JSON对象
我们在这里面要用到11个API,需要约定前后端的接口;
1)用户管理:注册,登录,检测登陆状态,注销
2)菜品管理:新增菜品,查看菜品,删除菜品
3)订单管理:新增订单(用户在这里面点菜),查看指定订单,查看所有订单,修改状态
1)实现注册功能:
约定前后端交互的接口: POST /resigter HTTP/1.1 contentType:application/json; { "userName":"李佳伟", "passWord":"778896", "isAdmin":"0" } 注册成功的时候: { "data": 1, "message": "注册成功" } 注册失败的时候: { "data": -1, "message": "当前前段传递的用户名重复" }
2)后端代码:
@RestController @RequestMapping("/Java100") public class XMLController { @Autowired XMLMapper mapper; Logger logger= LoggerFactory.getLogger(XMLController.class); @RequestMapping("/resigter") public HashMap<String,Object> AddUser(@RequestBody User RequestUser){ //1.进行前端校验参数 String username=RequestUser.getUserName(); System.out.println(username); String password=RequestUser.getPassWord(); System.out.println(password); HashMap<String,Object> result=new HashMap<>(); int data=0; String message=""; if(username==null||username.equals("")||password==null||password.equals("")){ data=0; message="当前前端传递的用户名和密码有一个为空"; }else { //2.进行判断用户名是否重复 User user = mapper.selectUserByUserName(username); if (user!=null){ data=-1; message="当前前段传递的用户名重复"; }else { //3.进行密码加密操作; String finalPassword = encrypt.AddPassword(password); //4将加密之后的密码和用户名传入到数据库里面 RequestUser.setPassWord(finalPassword); int len = mapper.addUser(RequestUser); if (len == 1) { message = "注册成功"; data = 1; } else { message = "注册失败"; data = -1; } } } result.put("data",data); result.put("message",message); return result; } }
2)实现登陆功能:必须只有管理员才可以进行登录,这个是在后端根据用户名来进行查询的;
进行密码加密操作:
public class encrypt { public static String AddPassword(String password){ //进行参数校验 if(!StringUtils.hasLength(password)){ return ""; } //1.先得到盐值 String salt= IdUtil.simpleUUID(); //2.对密码进行加密 String finalPassWord= SecureUtil.md5(salt+password); //3.进行最终密码拼装 return salt+"@"+finalPassWord; } public static boolean SubPassword(String password,String finalPassword){ String[] strings=finalPassword.split("@"); System.out.println(finalPassword); String salt=strings[0]; String extPassWord=strings[1]; String linPassword=SecureUtil.md5(salt+password); System.out.println(linPassword); if(linPassword.equals(extPassWord)) return true; return false; } }
进行登录操作:
@RequestMapping("/login") public HashMap<String,Object> login(@RequestBody User user, HttpServletRequest req){ //1.进行用户名和密码的校验 String username=user.getUserName(); String password=user.getPassWord(); int data=-1; String message=""; //2.进行密码解迷和判断当前是否是管理员 User loginUser= mapper.selectUserByUserName(username); if(loginUser==null||loginUser.equals("")){ data=-1; message="当前没有这个用户"; }else{ //判断当前是不是管理员 if(loginUser.getIsAdmin()==0){ data=-1; message="您不是管理员"; }else{ //进行密码解密操作 boolean flag=encrypt.SubPassword(user.getPassWord(),loginUser.getPassWord()); if(flag==true){ data=1; message="登陆成功"; HttpSession httpSession=req.getSession(true); httpSession.setAttribute("user",loginUser); }else{ data=-1; message="登陆失败"; } } } HashMap<String,Object> result=new HashMap<>(); result.put("data",data); result.put("message",message); return result; } }
3)监测登录状态(通过拦截器已经进行实现)
4)实现注销功能:
@RequestMapping("/logout") public void logout(HttpServletRequest req){ //1.进行注销 HttpSession httpSession=req.getSession(false); //2.删除session对象 httpSession.removeAttribute("user"); }
5)新增菜品:只有管理员才可以进行新增菜品,普通用户不可以进行新增菜品
约定前后端交互的接口:
前端传递: { "dishMoney":"90", "dishName":"红烧茄子" } 后端接收: { "data": 1, "message": "新增菜品成功" }
6)菜品管理:删除菜品:还是只有管理员才可以进行删除菜品,普通用户不可以进行删除菜品
前端:POST 127.0.0.1:8080/Java100/deleteDish?dishID=1 HTTP/1.1 删除成功的时候: { "data": 1, "message": "删除菜品成功" } 删除失败的时候: { "data": -1, "message": "删除菜品失败" }
@RequestMapping("/deleteDish") public HashMap<String,Object> deleteDish(Integer dishID,HttpServletRequest req){ //1.进行前端参数校验 int data=-1; String message=""; if(dishID==null||dishID.equals("")){ data=-1; message="当前前段传递的message为空"; }else{ //判断当前登录的人是否是管理员 HttpSession httpSession=req.getSession(false); User user= (User) httpSession.getAttribute("user"); if(user.getIsAdmin()==0){ data=-1; message="您当前不是管理员,无法进行删除菜品操作"; }else{ int len= mapper.deleteDish(dishID); if(len==1){ data=1; message="删除菜品成功"; }else { data = -1; message = "删除菜品失败"; } } } HashMap<String,Object> hashMap=new HashMap<>(); hashMap.put("data",data); hashMap.put("message",message); return hashMap; }
7)查看菜品:普通用户和管理员都可以查看所有菜品
约定前后端交互的接口:
GET 127.0.0.1:8080/Java100/getAllDish HTTP/1.1 [ { "dishID": 2, "dishName": "红烧茄子", "dishMoney": "90" }, { "dishID": 3, "dishName": "红烧里脊", "dishMoney": "100" } ]
@RequestMapping("/getAllDish") public List<Dish> GetAllDish(){ return mapper.SelectAllDish(); }
之前用户表和菜品表的所有XML:
<!--下面是针对用户来进行操作的--> <insert id="addUser"> insert into User values(null,#{userName},#{passWord},#{isAdmin}); </insert> <select id="selectUserByUserName" resultType="com.example.demo.Model.User"> select * from User where userName=#{userName}; </select> <select id="SelectByUserID" resultType="com.example.demo.Model.User"> select * from User where userID=#{userID} </select> <!--下面是根据菜品来进行操作的--> <insert id="addDish"> insert into Dish values(null,#{dishName},#{dishMoney}); </insert> <delete id="deleteDish"> delete from Dish where dishID=#{dishID} </delete> <select id="SelectAllDish" resultType="com.example.demo.Model.Dish"> select * from Dish </select> <select id="SelectOne" resultType="com.example.demo.Model.Dish"> select * from Dish where dishID=#{dishID} </select> <update id="UpdateDish"> update set dishMoney=#{dishMoney} where dishID=#{dishID} </update>
8)新增订单:
约定前后端交互的接口: 前端用户是要进行点菜的,肯定要进行选中菜品,所以前端给后端传递过来的肯定是一大堆的菜品ID 我们的后端要根据这些菜品ID生成一个订单 前段传递的参数: { "list":"2,3,4,5" } { "data": 1, "message": "订单插入成功" }
后端代码:
@RequestMapping("/addOrder") @Transactional public HashMap<String,Object> addOrder(@RequestBody HashMap<String,String> hashMap,HttpServletRequest req){ //将前端传递的字符串转化成JSON数组 List<Integer> dishIDList=new ArrayList<>(); String list=hashMap.get("list"); System.out.println(list); String[] strings=list.split(","); for(String string:strings){ dishIDList.add(Integer.parseInt(string)); } //1.先进行插入订单用户表,拿到生成的订单ID HttpSession httpSession=req.getSession(false); User loginUser= (User) httpSession.getAttribute("user"); Order order=new Order(); order.setDishList(dishIDList); order.setIsDown(0); order.setTimeStamp(new Timestamp(System.currentTimeMillis())); order.setUserID(loginUser.getUserID()); mapper.addOrderUser(order); //2.再继续进行插入订单-菜品表 //我们在这里面要进行循环插入,因为有多个菜品 mapper.addOrderDish(dishIDList,order.getOrderID()); int data=1; String message="订单插入成功"; HashMap<String,Object> result=new HashMap<>(); result.put("data",data); result.put("message",message); return result; }
对应的XML的代码:
<!--下面是根据订单表来进行操作的--> <!--1.下面这个是新增订单--> <!--进行插入要有订单用户表,这里面可以返回主键--> <insert id="addOrderUser" useGeneratedKeys="true" keyProperty="orderID" keyColumn="orderID"> insert into order_user values(null,#{userID},#{timeStamp}); </insert> <!--下面是插入要有订单菜品表--> <insert id="addOrderDish" > insert into order_dish <foreach collection="list" item="dishID" separator="," open="values" > (#{orderID},#{dishID}) </foreach> </insert>
9)查看订单(管理员可以查看所有订单,用户可以查看指定用户的订单),但是从这方面来说无论是管理员和用户,看到的都是多个订单)
我们在这里面查询订单,只是看一下订单的大致信息,比如说订单下单时间,订单的是否完成状态,订单的ID,订单的UserID
约定前后端交互的接口:
GET 127.0.0.1:8080/Java100/SelectAllOrder HTTP/1.1 响应: [ { "orderID": 7, "userID": 1, "dishList": null, "isDown": 0, "timeStamp": null }, { "orderID": 8, "userID": 1, "dishList": null, "isDown": 0, "timeStamp": null } ]
//1)如果是管理员,那么可以看到所有用户的订单 //2)如果是普通用户,那么只能看到自己的订单 //3)我们可以根据HttpSession中的User对象,也就是里面的isAdmin来进行判断 @RequestMapping("/SelectAllOrder") public List<Order> SelectAllOrder(HttpServletRequest req){ //1.进行判断当前用户是管理员,还是普通用户,因为最终返回的肯定是一个订单列表 HttpSession httpSession=req.getSession(false); User user= (User) httpSession.getAttribute("user"); List<Order> list=null; if(user.getIsAdmin()==0){ list= mapper.SelectAllOrder(); }else{ list=mapper.SelectOneAllOrder(user.getUserID()); } //2.返回数据 return list; }
10)查看指定订单详情:我们之前给用户显示的是一个一个的订单列表,当我们想看某一个订单的时候,就会给后端传递一个订单ID
约定前后端交互的接口: GET 127.0.0.1:8080/Java100/GetDetailOrder?orderID=7 HTTP/1.1 返回响应: { "data": 1, "returnResult": [ { "dishID": 2, "dishName": "红烧茄子", "dishMoney": "90" }, { "dishID": 3, "dishName": "红烧里脊", "dishMoney": "100" }, { "dishID": 4, "dishName": "红烧牛肉", "dishMoney": "700" }, { "dishID": 5, "dishName": "牛肉干", "dishMoney": "70" } ], "message": "当前用户查询所有订单成功" }
@RequestMapping("/GetDetailOrder") public HashMap<String,Object> GetDetailOrder(Integer orderID){ //1.进行前端参数校验 HashMap<String, Object> result = new HashMap<>(); int data=-1; String message=""; List<Integer> list=null; List<Dish> dishList=null; if(orderID==null||orderID.equals("")){ data=-1; }else { //2.进行数据库查询 //2.1先根据orderID来进行查询到所有的菜品信息 list = mapper.SelectAllDishIDs(orderID); //2.2再根据里面所有的dishID查询所有的Dish dishList = mapper.SelectAllDishByDishIDTwo(list); //3.统一返回数据封装结果 data=1; message="当前用户查询所有订单成功"; } result.put("data",data); result.put("message",message); result.put("returnResult",dishList); return result; } }
11)修改订单状态:我们在这里面约定只有管理员才可以进行修改订单状态
约定前后端交互的接口:我们要给后端传递一个orderID和isDone,后端根据这个来进行修改
前端:GET /UpdateState?orderID=1?isDone=1 响应: { "OK":1, "message":"修改订单状态成功" }
@RequestMapping("/UpdateState") public HashMap<String,Object> UpdateState(@RequestBody HashMap<String,Integer> hashMap,HttpServletRequest req){ //1.先进行获取到前端的参数并进行校验 int data=1; String message=""; HashMap<String,Object> result=new HashMap<>(); Integer isDone=hashMap.get("isDone"); Integer orderID=hashMap.get("orderID"); if(isDone==null||isDone.equals("")||orderID==null||orderID.equals("")){ data=-1; message="前端传低参数有问题"; }else { //2.判断当前登录的人是不是管理员 HttpSession httpSession = req.getSession(false); User user = (User) httpSession.getAttribute("user"); if (user.getIsAdmin() == 0) { data = -1; message = "您当前并不是管理员请进行登录"; } else { int len = mapper.UpdateState(isDone, orderID); if (len == 1) { data = 1; message = "修改成功"; } else { data = -1; message = "修改失败"; } } } result.put("data",data); result.put("message",message); return result; } }