知识点:Javase,Javaweb,html简单标签
实现功能:前端界面展示,增删改查,数据存储,本地服务器部署
代码解析:
后端接口:
//程序入口 @WebServlet("/student")//使用注解代替web.xml配置 public class MainStudents extends HttpServlet { /* doGet接口,实现功能为展示所有学生信息 */ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //从数据类Data中获得信息 ArrayList<Student> students=Data.input(); //创建一个Map对象存储返回值 Map<String,Object> map=new HashMap<>(); map.put("msg","查询成功"); map.put("code",200); map.put("data",students); //用jar包fastjson2-2.0.14.jar中的JSON.toJSONString()将map对象转化成String类型 String newMap= JSON.toJSONString(map); //设置文本格式和编码格式 resp.setContentType("application/json;charset=utf8"); //将数据发送给前端 resp.getWriter().write(newMap); System.out.println("展示完毕"); //设置请求头解决跨域问题 resp.setHeader("Access-Control-Allow-Origin","*"); } /* doPost接口:实现功能为增加新的学生 */ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //设置请求头 resp.setHeader("Access-Control-Allow-Origin","*"); //从Data类中拿到静态数据 ArrayList<Student> students=Data.students; //设置前端发送给的服务器的数据的编码格式为"utf8" req.setCharacterEncoding("utf8"); //利用时间戳生成不重复的id Long id=System.currentTimeMillis(); String name=req.getParameter("name"); Integer age=null; //防止空指针异常,要先判断文件是否为空(null) if (req.getParameter("age")!=null){ age=Integer.valueOf(req.getParameter("age")); } String sex=req.getParameter("sex"); //添加新的学生对象到集合中 students.add(new Student(id,name,age,sex)); //同样的,创建一个Map对象存储返回值 Map<String,Object> map=new HashMap<>(); map.put("msg","添加成功"); map.put("code",200); //发送数据到客户端(前端) String newMap= JSON.toJSONString(map); resp.setContentType("application/json;charset=utf8"); resp.getWriter().write(newMap); System.out.println("添加成功"); //数据保存 Data.output(); } /* doPut:功能为修改学生信息 */ @Override protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //设置请求头,解决跨域问题,但是PUT请求和DELET的请求不只是设置表头,下面还有操作 resp.setHeader("Access-Control-Allow-Origin","*"); ArrayList<Student> students=Data.students; req.setCharacterEncoding("utf8"); //获取前端数据,由于getParameter方法只能在GET方法和POST方法中才能获取到数据,所有这里使用系统封装好的getReader(),获取高效的字符输入流 BufferedReader reader=req.getReader(); //将字符流的首行转化为字符串 String string=reader.readLine(); //设置字符串的编码格式,防止乱码 String params= URLDecoder.decode(string,"utf8"); //changeIntoMap是我写在Data类里的将字符流转化成的字符串处理成map集合的方法 Map<String,String> mapNow=Data.changeIntoMap(params); /* 创建一个新集合用于存储传输数据,为了防止字符流中有不规范数据 */ Map<String,Object> map=new HashMap<>(); //为学号赋空值,防止数据异常,学号正常才可以修改,否则修改失败 Long id=null; if (mapNow.get("id")!=null){ id=Long.valueOf(mapNow.get("id")); //依次判断数据是否规范 for (Student student : students) { if (student.getId().equals(id)){ student.setName(mapNow.get("name")); Integer age=null; if (mapNow.get("age")!=null){ age=Integer.valueOf(mapNow.get("age")); } student.setAge(age); student.setSex(mapNow.get("sex")); System.out.println("修改成功"); break; } } map.put("msg","修改成功"); map.put("code","200"); }else { map.put("msg","修改失败"); map.put("code","500"); } //同样的,发射数据回前端并且保存数据到本地文件 String newMap= JSON.toJSONString(map); resp.setContentType("application/json;charset=utf8"); resp.getWriter().write(newMap); Data.output(); } /* doDelete:功能为删除学生信息 */ @Override protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //设置请求头,防止跨域,但还需要额外设置 resp.setHeader("Access-Control-Allow-Origin","*"); ArrayList<Student> students=Data.students; //同样的,设置输入字节流 BufferedReader reader=req.getReader(); String string=reader.readLine(); String params=URLDecoder.decode(string,"utf8"); Map<String,String> map1=Data.changeIntoMap(params); System.out.println(map1.get("id")); //判断前端发来的id的输入数据是否符合规范 Long id=null; if (map1.get("id")!=null){ id=Long.valueOf(map1.get("id")); System.out.println(id); } //同样的流程 Map<String,Object> map=new HashMap<>(); boolean flag=true; for (Student student : students) { if (student.getId().equals(id)){ students.remove(student); System.out.println("删除成功"); map.put("msg","删除成功"); map.put("code",200); System.out.println("删除成功"); flag=false; break; } } if (flag){ System.out.println("未找到学号"); map.put("msg","删除失败"); map.put("code",500); System.out.println("删除失败"); } String newMap= JSON.toJSONString(map); resp.setContentType("application/json;charset=utf8"); resp.getWriter().write(newMap); Data.output(); } //doOption:功能为设置请求对象,解决跨域问题 @Override protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setHeader("Access-Control-Allow-Origin", "http://localhost:63342"); //PUT,DELETE需要额外设置允许的请求方法 resp.setHeader("Access-Control-Allow-Methods", "PUT,DELETE"); resp.setHeader("Access-Control-Allow-Headers", "Content-Type"); resp.setHeader("Access-Control-Max-Age", "3600"); } } /* SearchByID:实现根据ID查找学生信息 */ @WebServlet("/student/search") public class SearchByID extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //从文件中取出数据 ArrayList<Student> students=Data.input(); //设置请求头 resp.setHeader("Access-Control-Allow-Origin","*"); Map<String,Object> map=new HashMap<>(); boolean flag=true;//判断是否查找成功 //设置前端发来的数据编码格式 req.setCharacterEncoding("utf8"); System.out.println(req.getParameter("id")); Long id=null; if (req.getParameter("id")!=null){ id=Long.valueOf(req.getParameter("id")); } System.out.println(id); for (Student student : students) { if (student.getId().equals(id)){ map.put("data",student); map.put("msg","查找成功"); map.put("code",200); System.out.println("查找成功"); flag=false; break; } } if (flag){ System.out.println("未找到学号"); map.put("msg","查找失败"); map.put("code",500); System.out.println("查找失败"); } String newMap= JSON.toJSONString(map); resp.setContentType("application/json;charset=utf8"); resp.getWriter().write(newMap); } }
Data和Student类:
//Data类 public class Data { //文件保存地址 private static File file=new File("D:\\桌面\\java38\\javaweb03\\1.txt"); //所有学生数据临时存在idea中的静态代码区 public static ArrayList<Student> students=null; //获取文件中的数据,输入到idea public static ArrayList<Student> input() throws IOException { //同样的,创建数据输入流对象,判断student是否为空,存入数据到静态区 ObjectInputStream objectInputStream=null; try { objectInputStream=new ObjectInputStream(new FileInputStream(file)); students=(ArrayList<Student>)objectInputStream.readObject(); } catch (EOFException e) { if (students==null){ students=new ArrayList<>(); } } catch (Exception e) { e.printStackTrace(); System.out.println("数据载入失败"); }finally { if (objectInputStream!=null){ objectInputStream.close(); System.out.println("数据输入流关闭成功"); }else { System.out.println("数据输入流关闭失败"); } return students; } } //数据从idea保存到本地文件中 public static void output() throws IOException { //同样的创建数据输出流 ObjectOutputStream outputStream=null; try { outputStream=new ObjectOutputStream(new FileOutputStream(file)); outputStream.writeObject(students); }catch (Exception e){ System.out.println("数据保存失败"); }finally { if (outputStream!=null){ outputStream.close(); System.out.println("数据保存成功"); }else { System.out.println("数据保存失败"); } } } //将前端传来的数据从String类型整理成键值对的map形式返回 public static Map<String,String> changeIntoMap(String s){ //先用split方法将数据分割成字符串数组 String[] strings=s.split("&"); Map<String,String> map=new HashMap<>(); //第二次以等号为分割符循环切割 for (String string : strings) { String[] strings1=string.split("="); map.put(strings1[0],strings1[1]); } return map; } }
//Student类 public class Student implements Serializable { private Long id; private String name; private Integer age; private String sex; public Student(Long id, String name, Integer age, String sex) { this.id = id; this.name = name; this.age = age; this.sex = sex; } public Student() { } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + '}'; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }
前端页面展示:
/* student.html:功能为展示所有学生信息,删除学生 连接的接口为:student的Get和Delete方法 */ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title>//首页标题 <style> //文件效果设置 body { font-family: Arial, sans-serif; margin: 0; padding: 20px; } h2 { margin-bottom: 20px; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ddd; padding: 10px; } th { background-color: #f5f5f5; } a { margin-right: 10px; } .add-link { display: block; margin-bottom: 20px; } </style> </head> <body> <!--<h2>标签,标题,自动大写--> <h2>学生信息</h2> <a href="add.html">添加学生</a>//添加跳转功能,可以跳转到添加的前端页面 <table border="1" cellpadding="20" cellspacing="0"> <tr> <th>ID</th> <th>姓名</th> <th>性别</th> <th>年龄</th> <th>操作</th> </tr> </table> <table> </table> <script> //设置一个参数接收获取后端传来的信息 var xhr = new XMLHttpRequest(); //使用GET方法打开,http://localhost:8080/web03_war_exploded/student接口 xhr.open("GET", "http://localhost:8080/web03_war_exploded/student"); //send()方法用于传输请求体,get方法没有请求体 xhr.send(); //onload方法会在事件完成以后立刻执行,这里后端信息一被接收就执行负责展示的代码块 xhr.onload = function () { //获取后端信息的纯文本值 var text = xhr.responseText //将文本值转化为json格式的代码 var data = JSON.parse(text); console.log(data) //document.querySelector('table')是找到文档中第一个“table”元素并且创建对象 var table = document.querySelector('table'); //设置一个参数为从json格式的后端数据中取出,键为“data”的值 var students = data.data; console.log(students) //通过循环将所有学生信息取出 for (var i = 0; i < students.length; i++) { //table.innerHTML会删除table处的所有子节点的内容,并加入新的节点内容 table.innerHTML += ` <tr> /* 依次添加学生的学号id,姓名name,性别sex,年龄age */ <td>${students[i].id}</td> <td>${students[i].name}</td> <td>${students[i].sex}</td> <td>${students[i].age}</td> //以及跳转到另一个前端页面,修改学生信息页面 <td> <a href="update.html?id=${students[i].id}">修改</a> //为了直观的表示,所以把删除功能内嵌到了首页 //通过给a,标签设置“#”的方式内嵌,当点击删除按钮时,会执行绑定的删除函数 deleteS(),并且传入一个参数学生的学号id <a href="#" οnclick="deleteS(${students[i].id})">删除</a> </td> </tr> ` } } //前端函数deleteS(id),需要参数为学号id function deleteS(id) { console.log(id) //同样的先设置一个参数来接收后端信息,xhr是局部变量,所以名字可以重复 var xhr=new XMLHttpRequest(); // open(),以delet的请求方式打开"http://localhost:8080/web03_war_exploded/student" xhr.open("DELETE","http://localhost:8080/web03_war_exploded/student") //设置请求体数据格式,delete请求的数据可以放在请求体里 xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); //``符号支持换行,也支持占位符${}直接表示参数 xhr.send(`id=${id}`) //同样的,当参数传入时执行代码块 function{} xhr.οnlοad=function () { //同样的数据转化 var text = xhr.responseText; console.log(text); var data = JSON.parse(text); console.log(data); //通过data.code判断后端是否删除成功 if (data.code == 200) { //alert("")功能是弹出一个弹窗 alert("删除成功") //location.href(),自动跳转到设置的网页,student.html是为了刷新 location.href = "student.html"; } else { alert("删除失败") } } } </script> </body> </html>
/* add.html:添加页面 连接接口:添加学生,student的post方法 */ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>添加学生</title> <style> //前端页面效果展示部分 body { font-family: Arial, sans-serif; margin: 0; padding: 20px; } h2 { margin-bottom: 20px; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ddd; padding: 10px; } th { background-color: #f5f5f5; } a { margin-right: 10px; } </style> </head> <body> //<h2></h2>标题标签,系统自动加粗 <h2>添加学生</h2> //<div></div>标签容器,支持流动数据类型 <div> //type:用于设置数据类型 id为数据设置一个唯一的标识符 姓名:<input type="text" id="name"> </div> <div> //<input>提供大量输入的数据类型,接收来自用户的数据 性别:<input type="text" id="sex"> </div> <div> 年龄:<input type="text" id="age"> </div> <div> //button, 提供一个可点击的按钮,这里还绑定了一个函数 <button οnclick="submit()">添加</button> </div> <script> function submit() { console.log("被点击了") //设置三个参数,分别接收用户传输的数据 var name=document.getElementById("name").value; var sex=document.getElementById("sex").value; var age=document.getElementById("age").value console.log(name+" "+sex+" "+age); //同样的设置参数接收后端数据 var xhr=new XMLHttpRequest(); xhr.open("POST","http://localhost:8080/web03_war_exploded/student") //post请求的参数在请求体,所以也要设置数据格式 xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xhr.send(`name=${name}&sex=${sex}&age=${age}`) //与删除方法相似 xhr.οnlοad=function () { var text=xhr.responseText; console.log(text); var data=JSON.parse(text); console.log(data); if (data.code==200){ alert("添加成功") location.href="student.html"; }else { alert("添加失败") } } } </script> </body>
/* update.html页面:实现学生信息的修改 连接接口:student的put方法和SerchByID类的update */ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>修改学生信息</title> </head> <body> //数据输入页面相同 <h2>修改学生信息</h2> <div> 姓名:<input type="text" id="name"> </div> <div> 性别:<input type="text" id="sex"> </div> <div> 年龄:<input type="text" id="age"> </div> <div> <button οnclick="submit()">修改</button> </div> <script> console.log(location.search) //设置一个参数接收上一个页面传过来的参数 location.search可以获得?之后的部分,通过spilt分割获得=右边的学号id var id=location.search.split("=")[1] console.log(id) //同样的连接路径,请求方式为get var xhr=new XMLHttpRequest(); xhr.open("GET","http://localhost:8080/web03_war_exploded/student/search?id="+id) xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xhr.send() console.log(xhr) //同样的,查询学号事件一旦完成就执行 xhr.οnlοad=function () { console.log(1) //同样的获取数据 var text = xhr.responseText; console.log(text); var data = JSON.parse(text); console.log(data); var students = data.data; //设置页面上的数据为查询到的数据 document.getElementById("name").value = students.name; document.getElementById("sex").value = students.sex; document.getElementById("age").value = students.age; console.log(name + " " + students.sex + " " + students.age); } //点击后执行函数 function submit() { //同样的获取后端信息 var xhl = new XMLHttpRequest(); xhl.open("PUT" ,"http://localhost:8080/web03_war_exploded/student") var name1=document.getElementById("name").value; var sex1=document.getElementById("sex").value; var age1=document.getElementById("age").value console.log(`id=${id}&name=${name1}&sex=${sex1}&age=${age1}`) xhl.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xhl.send(`id=${id}&name=${name1}&sex=${sex1}&age=${age1}`) xhl.οnlοad=function () { var text1=xhl.responseText; console.log(text1); var data1=JSON.parse(text1); console.log(data1); if (data1.code==200){ alert("修改成功") location.href="student.html"; }else { alert("修改失败") } } } </script> </body> </html>
不足:
-
部分输入异常没有捕获
-
没有登录界面,信息不安全
-
查询功能过于简陋
升级方向:
-
捕获异常
-
增加登录界面
-
增加模糊查询