SpringBoot实现restuful风格的CRUD
restuful风格:
百度百科:
RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。RESTFUL适用于移动互联网厂商作为业务使能接口的场景,实现第三方OTT调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源。
RESTFUL特点:
1、每一个URI代表1种资源;
2、客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;
3、通过操作资源的表现形式来操作资源;
4、资源的表现形式是XML或者HTML;
5、客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息。
规范列表:
由于采用的是thymeleaf+bootstarp(springBoot)的结构实现
所以对于一些公共片段的抽取必须得满足thymeleaf的语法规则:
抽取:
引入:
三种引入的效果:
工程结构:
登录拦截器:LoginHanderInterceptor
package com.zyb.webdemo.handlerInterceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 登陆拦截器 */ public class LoginHanderInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object isLogin=request.getSession().getAttribute("isLogin"); //没有登陆直接进主页 if(isLogin==null){ request.setAttribute("msg","没有权限请登录"); request.getRequestDispatcher("/login").forward(request,response); return false; }else{ return true; } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
员工操作控制器代码:EmployeeController
package com.zyb.webdemo.controller; import com.zyb.webdemo.dao.DepartmentDao; import com.zyb.webdemo.dao.EmployeeDao; import com.zyb.webdemo.entities.Department; import com.zyb.webdemo.entities.Employee; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import java.util.Collection; import java.util.Collections; @Controller public class EmployeeController { @Autowired EmployeeDao employeeDao; @Autowired DepartmentDao departmentDao; //返回员工列表页面 @GetMapping("/emps") public String list(Model model){ //thymeleaf默认就会拼串 //前缀:classpath:/templates/ //后缀:.html Collection<Employee> all= employeeDao.getAll(); //放在请求域中 model.addAttribute("emps",all); return "emp/list"; } //来到员工添加页面 @GetMapping("/emp") public String toAddPage(Model model){ //查出所有部门 Collection<Department> departments = departmentDao.getDepartments(); model.addAttribute("depts",departments); //返回员工添加页面的映射 return "emp/add"; } //员工添加 //SpringMvc自动将请求和入参对象的属性一一绑定;要求请求参数的名字和javaBean入参对想想的属性名一致 @PostMapping("/emp") public String addEmp(Employee employee){ //redirect:重定向 //forword:转发 //System.out.println("员工信息:"+employee); //保存员工 employeeDao.save(employee); return "redirect:/emps"; } @GetMapping("/emp/{id}") public String toEditPage(@PathVariable("id") Integer id, Model model){ Employee employee = employeeDao.get(id); model.addAttribute("emp",employee); Collection<Department> departments = departmentDao.getDepartments(); model.addAttribute("depts",departments); //回到修改界面 return "emp/edit"; } //员工修改 @PutMapping("/emp") public String updateEmployee(Employee employee){ employeeDao.save(employee); return "redirect:/emps"; } @DeleteMapping("/emp/{id}") public String deleteEmployee(@PathVariable("id") Integer id){ employeeDao.delete(id); return "redirect:/emps"; } }
MySpringMvcConfig的配置:
package com.zyb.webdemo.config; import com.zyb.webdemo.component.MyLocaleResolver; import com.zyb.webdemo.handlerInterceptor.LoginHanderInterceptor; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration //2.0之后直接实现 WebMvcConfigurer就行 public class MySpringmvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("login"); registry.addViewController("/login").setViewName("login"); registry.addViewController("/main").setViewName("dashboard");//后面自动加html } //注册拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginHanderInterceptor()).addPathPatterns("/**") .excludePathPatterns("/login","/user/login","/","/assert/**","/webjars/**"); } @Bean//将组件注册在容器中 public LocaleResolver localeResolver(){ return new MyLocaleResolver(); } }
因为浏览器不直接支持put、delete的请求,所以需要post请求作为中间请求进行变换
edit.html:(修改页面)
<!DOCTYPE html> <!-- saved from url=(0052)http://getbootstrap.com/docs/4.0/examples/dashboard/ --> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="description" content=""> <meta name="author" content=""> <title>Dashboard Template for Bootstrap</title> <!-- Bootstrap core CSS --> <link href="../../static/asserts/css/bootstrap.min.css" th:href="@{/asserts/css/bootstrap.min.css}" rel="stylesheet"> <!-- Custom styles for this template --> <link href="../../static/asserts/css/dashboard.css" th:href="@{/asserts/css/dashboard.css}" rel="stylesheet"> <style type="text/css"> /* Chart.js */ @-webkit-keyframes chartjs-render-animation { from { opacity: 0.99 } to { opacity: 1 } } @keyframes chartjs-render-animation { from { opacity: 0.99 } to { opacity: 1 } } .chartjs-render-monitor { -webkit-animation: chartjs-render-animation 0.001s; animation: chartjs-render-animation 0.001s; } </style> </head> <body> <!-- 引入头部搜索栏--> <div th:replace="~{commons/common::topbar}"></div> <div class="container-fluid"> <div class="row"> <div th:replace="~{commons/common::#menu(activeUri='emplist')}"></div> <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4"> <form th:action="@{/emp}" method="post"> <!--发送put请求修改员工数据--> <!-- 1、SpringMVC中配置HiddenHttpMethodFilter;(SpringBoot自动配置好的) 2、页面创建一个post表单 3、创建一个input项,name="_method";值就是我们指定的请求方式 --> <input type="hidden" name="_method" value="put" /> <input type="hidden" name="id" th:value="${emp.id}"> <div class="form-group"> <label>LastName</label> <input name="lastName" type="text" class="form-control" placeholder="zhangsan" th:value="${emp.lastName}"> </div> <div class="form-group"> <label>Email</label> <input name="email" type="email" class="form-control" placeholder="zhangsan@atguigu.com" th:value="${emp.email}"> </div> <div class="form-group"> <label>Gender</label><br/> <div class="form-check form-check-inline"> <input class="form-check-input" type="radio" name="gender" value="1" th:checked="${emp.gender==1}"> <label class="form-check-label">男</label> </div> <div class="form-check form-check-inline"> <input class="form-check-input" type="radio" name="gender" value="0" th:checked="${emp.gender==0}"> <label class="form-check-label">女</label> </div> </div> <div class="form-group"> <label>department</label> <!--提交的是部门的id--> <select class="form-control" name="department.id"> <option th:selected="${dept.id == emp.department.id}" th:value="${dept.id}" th:each="dept:${depts}" th:text="${dept.departmentName}">1</option> </select> </div> <div class="form-group"> <label>Birth</label> <input name="birth" type="text" class="form-control" placeholder="zhangsan" th:value="${#dates.format(emp.birth, 'yyyy-MM-dd')}"> </div> <button type="submit" class="btn btn-primary" >修改</button> </form> </main> </div> </div> <!-- Bootstrap core JavaScript ================================================== --> <!-- Placed at the end of the document so the pages load faster --> <script type="text/javascript" src="../../static/asserts/js/jquery-3.2.1.slim.min.js" th:src="@{/asserts/js/jquery-3.2.1.slim.min.js}"></script> <script type="text/javascript" src="../../static/asserts/js/popper.min.js" th:src="@{/asserts/js/popper.min.js}"></script> <script type="text/javascript" src="../../static/asserts/js/bootstrap.min.js" th:src="@{/asserts/js/bootstrap.min.js}"></script> <!-- Icons --> <script type="text/javascript" src="../../static/asserts/js/feather.min.js" th:href="@{/asserts/js/feather.min.js}"></script> <script> feather.replace() </script> <!-- Graphs --> <script type="text/javascript" src="../../static/asserts/js/Chart.min.js" th:src="@{/asserts/js/Chart.min.js}"></script> <script> var ctx = document.getElementById("myChart"); var myChart = new Chart(ctx, { type: 'line', data: { labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], datasets: [{ data: [15339, 21345, 18483, 24003, 23489, 24092, 12034], lineTension: 0, backgroundColor: 'transparent', borderColor: '#007bff', borderWidth: 4, pointBackgroundColor: '#007bff' }] }, options: { scales: { yAxes: [{ ticks: { beginAtZero: false } }] }, legend: { display: false, } } }); </script> </body> </html>
相关实体类:
删除的实现技巧:
不能将delete按钮直接包含在form表单中:
通过js进行进行调用一个表单,不用为删除而创建多个表单
效果图:
修改页面:
不一样的烟火