SpringMVC
第一章-响应数据和视图
知识点-返回页面视图
1.目标
- 掌握Controller返回页面视图
2.路径
- 请求转发
- 返回页面文件名字符串 success 逻辑视图
- 返回字符串关键字forward:物理视图
- 返回ModelAndView 对象
- 重定向
- 返回字符串关键字redirect:
- 转发与重定向的区别
3.详解
3.1 返回页面文件名
controller方法返回的字符串会被解析成页面视图(即:页面的地址路径)
3.1.1. 返回逻辑视图名称
- 方法返回的字符串,和视图解析器里的前缀、后缀拼接得到真实路径,再进行跳转
- 不管是物理视图(完整的写法)还是逻辑视图(简写),默认采用的都是请求转发跳转
3.1.2. 返回带前缀的物理视图
- 请求转发:
forward:/success.jsp
- 重定向:
redirect:/success.jsp
- 注意:如果带有
forward
或者redirect
,那么路径必须是完整的真实路径 , 不受视图解析器影响
使用示例
package com.mingye.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/*
在这里演示,返回视图【跳转页面】
1. 只要是不带前缀的跳转方式,都是采用请求转发的方式来跳转
2. 而且这种不带前缀的跳转方式,会受到视图解析器的影响
3. 如果希望作出重定向的跳转或者是不想受到视图解析器的约束,
那么可以使用带前缀的写法:
return "前缀+物理视图";
return "forward:/success.jsp"; // 请求转发跳转
return "redirect:/success.jsp"; // 重定向跳转
*/
@Controller
public class Controller01 {
//采用物理视图写法来跳转页面:
@RequestMapping("/page01")
public String page01(){
System.out.println("page01...");
return "/success.jsp";
}
//采用逻辑视图写法来跳转页面:
@RequestMapping("/page02")
public String page02(){
System.out.println("page02...");
return "success";
}
//采用带前缀的方式跳转页面: 请求转发方式跳转
@RequestMapping("/page03")
public String page03(){
System.out.println("page03...");
return "forward:/success.jsp";
}
//采用带前缀的方式跳转页面: 重定向方式跳转
@RequestMapping("/page04")
public String page04(){
System.out.println("page04...");
return "redirect:/success.jsp";
}
}
3.2 请求转发并传递数据【重点】
ModelAndView
是SpringMVC提供的组件之一,其中Model
,模型,用于封装数据(Springmvc会把数据放到了request域中)View
,视图,就是页面,用于展示数据
- 如果我们设置了视图名称,并且封装了数据模型,SpringMVC会:
- 把Model的数据放到request域对象中,然后请求转发到指定的视图(页面)
- 我们可以视图页面中获取数据显示出来
**使用示例 **
package com.mingye.web;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpSession;
/*
在这里演示,返回视图和数据【跳转页面的同时,也给页面带数据】
1. 在springmvc里面,要完成这个工作,需要modelandview对象
2. modelandview就表示数据和视图
model就是数据 : 数据会保存在request作用域里面
view就是视图 : 会采用请求转发的方式来跳转
*/
@Controller
public class Controller02 {
// 自己new出来modelandview对象
@RequestMapping("/page05")
public ModelAndView page05(){
System.out.println("page05...");
//1. 创建ModelAndView 对象
ModelAndView mv = new ModelAndView();
//2. 设置数据
mv.addObject("username" , "张三05");
//3. 设置视图: 这里的视图名字受视图解析器的影响
//如果不希望受视图解析器的影响,就可以加上前缀
//mv.setViewName("forward:/success.jsp");
mv.setViewName("success");
//4. 返回modelandview对象
return mv;
}
// 方法参数传递进来ModelAndView对象
@RequestMapping("/page06")
public ModelAndView page06(ModelAndView mv){
System.out.println("page06...");
//1. 创建ModelAndView 对象
//ModelAndView mv = new ModelAndView();
//2. 设置数据
mv.addObject("username" , "张三06");
//3. 设置视图: 这里的视图名字受视图解析器的影响
//如果不希望受视图解析器的影响,就可以加上前缀
//mv.setViewName("forward:/success.jsp");
mv.setViewName("success");
//4. 返回modelandview对象
return mv;
}
// 拆开来写! 方法参数传递进来Model对象,方法的返回值,就返回视图
@RequestMapping("/page07")
public String page07(Model model){
System.out.println("page07...");
//1. 设置数据
model.addAttribute("username" , "张三07");
//2. 直接返回视图
return "success";
}
//======================使用session作用域来存值===============
@RequestMapping("/page08")
public String page08(HttpSession session){
System.out.println("page08...");
//1. 设置数据
session.setAttribute("username" , "张三08");
//2. 直接返回视图
return "redirect:/success.jsp";
}
}
- 在index.jsp视图页面中,取出数据显示出来
<h2>这是成功的页面 ${username}</h2>
4.小结
-
返回页面文件名
- 返回逻辑视图
- 方法返回的字符串,和视图解析器里的前缀、后缀拼接得到真实路径,再进行跳转
- 是请求转发跳转
- 返回带前缀的物理视图 (不受视图解析器的影响)
- 请求转发:
forward:/success.jsp
- 重定向:
redirect:/success.jsp
- 请求转发:
- 返回逻辑视图
-
方法返回
ModelAndView
public ModelAndView jump(){
ModelAndView mav = new ModelAndView();
mav.setViewName("视图名称");
mav.addObject("数据名称", "值");
return mav;
}
public ModelAndView jump(ModelAndView mav){
mav.setViewName("视图名称");
mav.addObject("数据名称", "值");
return mav;
}
- 方法返回String:视图名称
public String jump(Model model){
model.addAttribute("数据名称", "值");
return "视图名称";
}
知识点-返回数据【重要】
1.目标
- 掌握给客户端返回数据
2.路径
- 直接返回字符串
- 返回json数据【重点】
3. 详解
3.1 直接响应字符串【了解】
- 两种方式
- 使用Servlet原生的
response
对象,返回响应数据 response.getWrite().write(“xxxx”); - 方法上使用
@ResponseBody
注解,springmvc就会把方法的返回值当成字符串来看待,不会再识别成页面的地址路径
- 使用Servlet原生的
3.1.1 使用示例
/*
在这里演示,返回数据【纯字符串】
1. 有两种写法:
1.1 在参数上要求springmvc 传递进来response对象,然后使用原始的写法来返回字符串
1.2 方法直接返回字符串即可,springmvc,默认会把方法的返回值看成是 页面的路径地址
所以需要在方法上加上注解: @ResponseBody
*/
@Controller
public class Controller03 {
// 使用原始的response对象来写字符串给客户端
@RequestMapping("/returnStr01")
public void returnStr01(HttpServletResponse resp) throws IOException {
System.out.println("returnStr01...");
resp.getWriter().write("returnStr01...");
}
// 使用@ResponseBody注解返回字符串
@ResponseBody
@RequestMapping("/returnStr02")
public String returnStr02() {
System.out.println("returnStr02...");
return "returnStr02...";
}
}
3.2 返回json数据【重要】
- 两种方式介绍
- 自己把JavaBean对象转换成json格式的字符串,响应给客户端
- 方法返回JavaBean对象,使用
@ResponseBody
注解Springmvc帮我们转换成json格式 【推荐】
3.2.1 前提条件
- 在pom.xml中导入依赖:
jackson-databind
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
- springmvc.xml中开启mvc注解开关
<mvc:annotation-driven/>
3.2.2 使用示例
package com.mingye.web;
import com.alibaba.fastjson.JSON;
import com.mingye.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/*
在这里演示,返回数据【纯字符串】
1. 有两种写法:
1.1 在参数上要求springmvc 传递进来response对象,然后使用原始的写法来返回字符串
1.2 方法直接返回字符串即可,springmvc,默认会把方法的返回值看成是 页面的路径地址
所以需要在方法上加上注解: @ResponseBody
*/
@Controller
public class Controller03 {
/*
自己手动转化对象成json字符串,然后返回
*/
@ResponseBody
@RequestMapping("/returnJson01")
public String returnJson01() {
System.out.println("returnJson01...");
//1. 构建对象
User u = new User("admin" , "123456");
//2. 手动转化
String json = JSON.toJSONString(u);
return json;
}
/*
采用springmvc的标准来返回JSON数据
1. 直接返回对象即可
2. 要求:
2.1 需要引入 jackson-databind 依赖 引入这个依赖,它在背后才能帮助我们转化对象成json字符串
2.2 方法上打注解 @ResponseBody
*/
@ResponseBody
@RequestMapping("/returnJson02")
public User returnJson02() {
System.out.println("returnJson02...");
//1. 构建对象
User u = new User("admin" , "123456");
return u;
}
}
4.小结
- 如果要直接响应数据,使用response对象
public void method1(HttpServletResponse response){
//如果响应普通文本数据
//response.setContentType("text/html;charset=utf-8");
//如果响应json格式的字符串
response.setContentType("application/json;charset=utf-8");
response.getWriter().print("xxxx");
}
- 如果要bean对象 , 使用注解@ResponseBody
如果返回的是json数据,需要添加jackson-databind的依赖!
@RequestMapping("/method2")
@ResponseBody
public User method2(){
return new User();
}
第二章-表现层数据封装
1 表现层响应数据的问题
问题:我们表现层增删改方法返回true或者false表示是否成功,getById()方法返回一个json对象,getAll()方法返回一个json对象数组,这里就出现了三种格式的响应结果,极其不利于前端解析。
解决:我们需要统一响应结果的格式
2 定义Result类封装响应结果
2.1 Result类封装响应结果
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private int code; // 请求成功或者失败的代号: 1 表示成功, 0 表示失败
private Object data; // 数据,查询的时候得到的数据都封装在这个属性,并且增删改的结果也封装在这个位置
private String msg; // 查询成功或者失败 附加的一句话
public Result(int code, Object data) {
this.code = code;
this.data = data;
}
}
注意事项:
Result类中的字段并不是固定的,可以根据需要自行增减
2.2 Code类封装响应码
//状态码
public class Code {
public static final Integer SAVE_OK = 20011;
public static final Integer DELETE_OK = 20021;
public static final Integer UPDATE_OK = 20031;
public static final Integer GET_OK = 20041;
public static final Integer SAVE_ERR = 20010;
public static final Integer DELETE_ERR = 20020;
public static final Integer UPDATE_ERR = 20030;
public static final Integer GET_ERR = 20040;
}
注意事项:
Code类的常量设计也不是固定的,可以根据需要自行增减,例如将查询再进行细分为GET_OK,GET_ALL_OK,GET_PAGE_OK
3 表现层数据封装返回Result对象
/*
在这里演示,表现层的数据封装,也就是给客户端返回一种统一的数据格式。
*/
@Controller
public class Controller04 {
//使用lombok 提供的构建者模式来构建result对象
@ResponseBody
@RequestMapping("/add03")
public Result add03(int number){
//模拟成功或者失败! 真实的情况,肯定要和数据库打交道的。
Result result = null;
if(number == 1){
result = Result.builder().code(1).data("添加成功").build();
}else{
result = Result.builder().code(0).data("添加失败").build();
}
return result;
}
//使用自己动手创建的有参构造方法来构建Result对象
@ResponseBody
@RequestMapping("/add02")
public Result add02(int number){
//模拟成功或者失败! 真实的情况,肯定要和数据库打交道的。
Result result = null;
if(number == 1){
result = new Result(1, "添加成功");
}else{
result = new Result(0, "添加失败");
}
return result;
}
//===============================================
@ResponseBody
@RequestMapping("/add")
public Result add(int number){
//模拟成功或者失败! 真实的情况,肯定要和数据库打交道的。
Result result = null;
if(number == 1){
result = new Result(1, "添加成功" , null);
}else{
result = new Result(0, "添加失败" , null);
}
return result;
}
@ResponseBody
@RequestMapping("/delete")
public Result delete(int number){
//模拟成功或者失败! 真实的情况,肯定要和数据库打交道的。
Result result = null;
if(number == 1){
result = new Result(1, "删除成功" , null);
}else{
result = new Result(0, "删除失败" , null);
}
return result;
}
@ResponseBody
@RequestMapping("/update")
public Result update(int number){
//模拟成功或者失败! 真实的情况,肯定要和数据库打交道的。
Result result = null;
if(number == 1){
result = new Result(1, "更新成功" , null);
}else{
result = new Result(0, "更新失败" , null);
}
return result;
}
@ResponseBody
@RequestMapping("/findById")
public Result findById(int number){
//模拟成功或者失败! 真实的情况,肯定要和数据库打交道的。
Result result = null;
if(number == 1){
//假设对象是从数据库查询出来的
User u = new User("zhangsan" , "123456");
result = new Result(1, u , "查询成功!");
}else{
result = new Result(0, null , "查询失败!");
}
return result;
}
}
第三章-异常处理器
1 异常介绍
-
程序开发过程中不可避免的会遇到异常现象,我们不能让用户看到这样的页面数据,用户也看不懂,所以我们要捕捉异常,根据异常的类型把报错信息修改成用户能够看懂的信息。
-
出现异常现象的常见位置与常见诱因如下:
- 框架内部抛出的异常:因使用不合规导致
- 数据层抛出的异常:因外部服务器故障导致(例如:服务器访问超时)
- 业务层抛出的异常:因业务逻辑书写错误导致(例如:遍历业务书写操作,导致索引异常等)
- 表现层抛出的异常:因数据收集、校验等规则导致(例如:不匹配的数据类型间导致异常)
- 工具类抛出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)
2 异常处理器
2.2.1 编写异常处理器
- controller 模拟抛出异常
package com.mingye.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/*
演示: 使用springmvc 提供的全局异常处理机制来处理这些不断向上抛或者是我们没有捕捉到的异常!
*/
@Controller
public class Controller01 {
@RequestMapping("/show")
public String show(int number){
if(number ==1 ){
throw new NullPointerException();
}else if(number == 2 ){
throw new ClassCastException();
}else{
throw new RuntimeException();
}
}
}
- 全局异常处理器
package com.mingye.exception;
import com.mingye.bean.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/*
@ControllerAdvice : 表示对所有的controller进行增强,其实背后就是采用了AOP的思想,进行了异常增强
注意:
1. @ResponseBody 是可以写在方法上,也可以写在类上,如果标记在类上,即表示对所有的方法都生效!
2. 同样在controller类里面,上面打的是注解 @Controller, 如果所有的方法都返回json数据
同样也可以把@ResponseBody移动到类上面来写
@ResponseBody
@Controller
public class Controller01{
}
3. springmvc 针对这两个组合做出来一套 二合一的注解: @RestController = @Controller + @ResponseBody
4. 同样在异常处理机制里面也有这样的技巧:
@ControllerAdvice + @ResponseBody = @RestControllerAdvice
*/
//@ResponseBody
//@ControllerAdvice
//@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* @ExceptionHandler :
* 用来表示捕捉什么异常,一旦某一个controller方法出现了这种异常那么这个方法将会被调用。
* @ResponseBody :
* 用来描述方法的返回值是一个字符串,这个方法一旦被调用,它的返回值将会直接返回给客户端。
* @return
*/
//@ResponseBody
@ExceptionHandler(NullPointerException.class)
public Result handleNullPointerException(){
System.out.println("全局异常处理方法捕捉到空指针异常了!");
return new Result(0 , "出现空指针了~!");
}
//@ResponseBody
@ExceptionHandler(ClassCastException.class)
public Result handleClassCastException(){
return new Result(0 , "出现类型转换异常了~!");
}
//@ResponseBody
@ExceptionHandler(Exception.class)
public Result handleException(){
return new Result(0 , "出现异常了~!");
}
}
2.2.2 动态返回异常信息
- 自定义异常类
package com.mingye.exception;
// 自定义异常类
public class UniqueException extends Exception{
//定义异常的错误代号
private int code ;
public int getCode() {
return code;
}
public UniqueException(String message, int code) {
super(message);
this.code = code;
}
}
- controller模拟抛出异常
package com.mingye.web;
import com.mingye.exception.UniqueException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/*
演示: 使用springmvc 提供的全局异常处理机制来处理这些不断向上抛或者是我们没有捕捉到的异常!
*/
@Controller
public class Controller02 {
@RequestMapping("/show02")
public String show(int number) throws UniqueException {
if(number ==1 ){
throw new NullPointerException("空空空空空~!");
}else if(number == 2 ){
throw new ClassCastException("转转转转转!@");
}else if(number == 3 ){
throw new UniqueException("用户名已存在!" , 10086);
}else{
throw new RuntimeException("运行时异常~");
}
}
}
- 全局异常处理
package com.mingye.exception;
import com.mingye.bean.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler02 {
/**
*
* @param e 出现的空指针异常!
* @return
*/
@ExceptionHandler(NullPointerException.class)
public Result handleNullPointerException(NullPointerException e){
//1. 记录异常信息到文件
//2. 发邮件|发短信给具体的运维人员
return new Result(0 , e.getMessage());
}
@ExceptionHandler(ClassCastException.class)
public Result handleNullPointerException(ClassCastException e){
//1. 记录异常信息到文件
//2. 发邮件|发短信给具体的运维人员
return new Result(0 , e.getMessage());
}
@ExceptionHandler(RuntimeException.class)
public Result handleNullPointerException(RuntimeException e){
//1. 记录异常信息到文件
//2. 发邮件|发短信给具体的运维人员
return new Result(0 , e.getMessage());
}
@ExceptionHandler(UniqueException.class)
public Result handleNullPointerException(UniqueException e){
//1. 记录异常信息到文件
//2. 发邮件|发短信给具体的运维人员
return new Result(e.getCode() , e.getMessage());
}
}
第四章-拦截器
1 拦截器简介
问题导入
问题1:拦截器拦截的对象是谁?
问题2:拦截器和过滤器有什么区别?
1.1 拦截器概念和作用
- 拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行
- 作用:
- 在指定的方法调用前后执行预先设定的代码
- 阻止原始方法的执行
- 总结:增强
- 核心原理:AOP思想
1.2 拦截器和过滤器的区别
-
作用区域不同
-
归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
-
拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强
2 入门案例
问题导入
定义拦截器需要实现什么接口?
2.1 拦截器代码实现
【第一步】定义拦截器
做法:定义一个类,实现HandlerInterceptor接口即可
/*
自定义拦截器:
1. 定义类,实现接口 HandlerInterceptor
2. 实现里面方法
3. 登记|注册拦截器
*/
public class MyInterceptor implements HandlerInterceptor {
/*
拦截到请求的时候调用
1. springmvc根据方法的返回值来决定是否拦截请求 , true :表示放行请求, false: 表示拦截请求
2. 如果拦截了请求,那么在方法里面也一样需要对这次请求作出响应|回应,否则客户端收不到任何信息
2.1 以前的时候,可以跳转到某一个页面
2.2 现在更多的是返回一份JSON字符串
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor::preHandle...");
//作出回应
Result r = new Result(0 , "权限不足,禁止访问!" );
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(JSON.toJSONString(r));
return false;
}
//controller方法执行之后调用
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor::postHandle...");
}
//一切准备就绪,要返回给页面的时候调用。
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor::afterCompletion...");
}
}
【第二步】配置加载拦截器
在springmvc 里面配置拦截器
<!--5. 配置拦截器-->
<mvc:interceptors>
<!--配置一个拦截器-->
<mvc:interceptor>
<!--什么样的请求地址过来,拦截器就会工作-->
<!--<mvc:mapping path="/show"/>-->
<!--如果希望拦截所有的请求,那么就写 /** 。 这个所有的请求,最大是大到DispatcherServlet能捕捉到的请求-->
<mvc:mapping path="/**"/>
<!--指定拦截器-->
<bean class="com.mingye.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
2.2 拦截器流程分析
3 拦截器参数
问题导入
postHandle()和afterCompletion()方法都是处理器方法执行之后执行,有什么区别?
3.1 前置处理
//原始方法调用前执行的内容
//返回值类型可以拦截控制的执行,true放行,false终止
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle...");
return true;
}
-
参数
- request:请求对象
- response:响应对象
- handler:被调用的处理器对象,本质上是一个方法对象,对反射技术中的Method对象进行了再包装
-
返回值
返回值为false,被拦截的处理器将不执行。
3.2 后置处理
//原始方法调用后执行的内容
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...");
}
- 参数
modelAndView:如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息,并进行跳转
注意:如果处理器方法出现异常了,该方法不会执行
3.3 完成后处理
//原始方法调用完成后执行的内容
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
- 参数
ex:如果处理器执行过程中出现异常对象,可以针对异常情况进行单独处理
注意:无论处理器方法内部是否出现异常,该方法都会执行。
4 拦截器链配置
问题导入
什么是拦截器链?
4.1 多个拦截器配置
- 第一个拦截器
package com.mingye.interceptor;
import com.alibaba.fastjson.JSON;
import com.mingye.bean.Result;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor01 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor01::preHandle...");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor01::postHandle...");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor01::afterCompletion...");
}
}
- 第二个拦截器
package com.mingye.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor02 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor02::preHandle...");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor02::postHandle...");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor02::afterCompletion...");
}
}
- 第三个拦截器
package com.mingye.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor03 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor03::preHandle...");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor03::postHandle...");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor03::afterCompletion...");
}
}
- 配置拦截器
<!--配置拦截器链-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/show"/>
<bean class="com.mingye.interceptor.MyInterceptor01"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/show"/>
<bean class="com.mingye.interceptor.MyInterceptor02"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.mingye.interceptor.MyInterceptor03"/>
</mvc:interceptor>
</mvc:interceptors>
4.2 多个连接器工作流程分析
- 当配置多个拦截器时,形成拦截器链
- 拦截器链的运行顺序参照拦截器添加顺序为准
- 当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
- 当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作
第五章-RestFul
知识点-介绍
1.目标
- 能够理解什么是RestFul
2.路径
- RestFul 历史
- 接口结构
3.详解
3.1 RestFul介绍
3.1.1 概述
REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的。Fielding是一个非常重要的人,他是HTTP协议(1.0版和1.1版)的主要设计者、Apache服务器软件的作者之一、Apache基金会的第一任主席。所以,他的这篇论文一经发表,就引起了关注,并且立即对互联网开发产生了深远的影响。
他这样介绍论文的写作目的:
“本文研究计算机科学两大前沿----软件和网络----的交叉点。长期以来,软件研究主要关注软件设计的分类、设计方法的演化,很少客观地评估不同的设计选择对系统行为的影响。而相反地,网络研究主要关注系统之间通信行为的细节、如何改进特定通信机制的表现,常常忽视了一个事实,那就是改变应用程序的互动风格比改变互动协议,对整体表现有更大的影响。我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。”
RESTful 是一种设计风格。它不是一种标准,也不是一种软件,而是一种思想。
3.1.2 特点
- 每一个URI(请求地址)代表1种资源;
- 以前我们认为url地址它是一个动作: 增删改查的动作
- localhost:8080/项目名/findAllUser
- lolcahost:8080/项目名/deleteUser?id=3
- rest设计风格认为地址是一种资源,体现的只有名词,而没有动词。
- localhost:8080/项目名/user/3 : 删除id为3
- localhost:8080/项目名/user/3 : 查询id为3
- 以前我们认为url地址它是一个动作: 增删改查的动作
- 客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;、
- 由于地址不能体现出来动作,包含的都是名词,没有动词,那么服务端如何区分出来客户端想要执行的是什么操作呢?
- 采用请求方式来区分 localhost:8080/项目名/user/3
- 新增 ----- post请求
- 查询 ----- get请求
- 删除 ----- delete请求
- 更新 ----- put请求
- 客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息
3.2 接口结构
3.2.1 如何设计接口
-
域名
应该尽量将API部署在专用域名之下。 第三方SDK来说,比较有用。
http://api.example.com 或者 http://www.example.com/api/
-
版本
将API的版本号放在url中:http://www.example.com/api/v1.0
-
路径
在RESTful架构中,每个地址代表一种资源(resource),所以地址中不能有动词,只能有名词,而且所用的名词往往与数据库的表名对应。
-
具体操作
对于资源的具体操作类型,由HTTP动词表示。常用的HTTP动词有下面四个(括号里是对应的SQL命令)
GET(SELECT):从服务器取出资源(一项或多项)。 POST(CREATE):在服务器新建一个资源。 PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。 DELETE(DELETE):从服务器删除资源。 还有三个不常用的HTTP动词。 PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。 HEAD:获取资源的元数据。 OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的
3.2.2 示例说明
-
示例
GET /user:列出所有用户
POST /user:新建一个用户
GET /user/{id}:获取某个指定用户的信息
PUT /user:更新某个指定用户的信息(提供该用户的全部信息)
DELETE /user/{id}:删除某个用户
-
原来的方式
http://127.0.0.1/user/find?id=3 GET方法,根据用户id获取数据
http://127.0.0.1/user/update POST方法,用户修改
http://127.0.0.1/user/add POST方法,用户新增
http://127.0.0.1/user/deleteUser?id=3 GET/POST方法,用户根据id删除 -
RestFul方式
http://127.0.0.1/user/{id} GET方法,根据用户id获取数据
http://127.0.0.1/user/{id} DELETE方法,用户根据id删除http://127.0.0.1/user/ GET 方法 查询所有的用户
http://127.0.0.1/user/ PUT方法,用户修改
http://127.0.0.1/user/ POST方法,用户新增
4.小结
- RESTful 是一种设计风格 , 可以用,也可以不用!
- 每一个URI代表1种资源,地址里面只能出现名词,不能出现动词。
- 客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;
案例-最佳实践
1. 需求
- 使用RestFul 设计增删改查用户接口
2. 分析
- 创建Maven web工程
- 创建Pojo
- 创建Controller ,定义增删改查方法
- 分别使用 get | post | put | delete 来指定方法请求方式
3. 实现
3.1 基本实现
在postman工具里面测试
- User
package com.mingye.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String username;
private String password;
}
- UserController
package com.mingye.web;
import com.mingye.bean.Result;
import com.mingye.bean.User;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
@RestController
public class UserController {
/*
添加用户:
以前: localhost:82/aa/addUser GET|POST
restFul: localhost:82/aa/users POST
*/
//@RequestMapping(value = "/users" , method = RequestMethod.POST)
@PostMapping("/users")
public Result addUser(User user){
System.out.println("addUser:: user = " + user);
return new Result(1 , "添加成功");
}
/*
删除用户:
以前: localhost:82/aa/deleteUser?id=1 GET|POST
restFul: localhost:82/aa/users/1 delete
*/
@DeleteMapping("/users/{id}")
public Result deleteUser(@PathVariable int id){
System.out.println("deleteUser:: id = " + id);
return new Result(1 , "删除成功");
}
/*
更新用户:
以前: localhost:82/aa/updateUser POST
restFul: localhost:82/aa/users PUT
*/
@PutMapping("/users")
public Result updateUser(User user){
System.out.println("updateUser:: user = " + user);
return new Result(1 , "更新成功");
}
/*
根据id查询用户:
以前: localhost:82/aa/findById?id=1 GET|POST
restFul: localhost:82/aa/users/1 GET
*/
@GetMapping("/users/{id}")
public Result findById(@PathVariable int id){
System.out.println("findById:: id = " + id);
return new Result(1 , "根据id查询成功");
}
/*
查询所有:
以前: localhost:82/aa/findAll GET|POST
restFul: localhost:82/aa/users GET
*/
@GetMapping("/users")
public Result findAll(){
System.out.println("findAll... = ");
return new Result(1 , "查询所有成功");
}
}
4. 小结
- 创建Maven web工程
- 创建Pojo
- 创建Controller ,定义增删改查方法
- 分别使用 get | post | put | delete 来指定方法请求方式
第六章 - 整合SSM
一、SSM整合
1 SSM整合配置
1.1 SSM整合流程
- 创建工程
- SSM整合
- Spring
- MyBatis
- SpringMVC
- 功能模块
- 表与实体类
- dao(接口+自动代理)
- service(接口+实现类)
- 业务层接口测试(整合JUnit)
- controller
- 表现层接口测试(PostMan)
1.2 SSM整合配置
1.2.1 创建工程,添加依赖和插件
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.2</version>
</dependency>
</dependencies>
<!--2. 追加tomcat7 插件-->
<build>
<plugins>
<!--Tomcat 插件-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>82</port>
<path>/aa</path>
</configuration>
</plugin>
</plugins>
</build>
1.2.2 Spring整合Mybatis
- 创建数据库和表
-- 创建ssm_db数据库
CREATE DATABASE IF NOT EXISTS ssm_db CHARACTER SET utf8;
-- 使用ssm_db数据库
USE ssm_db;
-- 创建tbl_book表
CREATE TABLE tbl_book(
id INT PRIMARY KEY AUTO_INCREMENT, -- 图书编号
TYPE VARCHAR(100), -- 图书类型
NAME VARCHAR(100), -- 图书名称
description VARCHAR(100) -- 图书描述
);
-- 添加初始化数据
INSERT INTO tbl_book VALUES(NULL,'计算机理论','Spring实战 第5版','Spring入门经典教材,深入理解Spring原理技术内幕');
INSERT INTO tbl_book VALUES(NULL,'计算机理论','Spring 5核心原理与30个类手写实战','十年沉淀之作,手写Spring精华思想');
INSERT INTO tbl_book VALUES(NULL,'计算机理论','Spring 5设计模式','深入Spring源码剖析,Spring源码蕴含的10大设计模式');
INSERT INTO tbl_book VALUES(NULL,'市场营销','直播就该这么做:主播高效沟通实战指南','李子柒、李佳琦、薇娅成长为网红的秘密都在书中');
INSERT INTO tbl_book VALUES(NULL,'市场营销','直播销讲实战一本通','和秋叶一起学系列网络营销书籍');
INSERT INTO tbl_book VALUES(NULL,'市场营销','直播带货:淘宝、天猫直播从新手到高手','一本教你如何玩转直播的书,10堂课轻松实现带货月入3W+');
- jdbc.properties属性文件
db.driverClassName=com.mysql.jdbc.Driver
db.url=jdbc:mysql:///day35?useSSL=false
db.username=root
db.password=root
- Spring整合MyBatis
定义 applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--以下属于spring的配置-->
<context:component-scan base-package="com.mingye"/>
<!--以下属于mybatis的配置-->
<context:property-placeholder location="classpath:db.properties"/>
<!--1. 数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${db.driverClassName}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
<!--2. 配置SqlSessionFactoryBean-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.mingye.bean"/>
</bean>
<!--3. 配置MapperScannerConfigurer-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.mingye.dao"/>
</bean>
<!--4. 配置事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
- Spring整合SpringMVC
定义springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--导入applicationContext.xml-->
<import resource="applicationContext.xml"/>
<!--1. 扫描包-->
<!-- <context:component-scan base-package="com.mingye"/>-->
<!--2. 打开注解驱动-->
<mvc:annotation-driven/>
<!-- 3. 视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--4.静态资源的处理-->
<mvc:default-servlet-handler/>
</beans>
- web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!--配置过滤器-->
<filter>
<filter-name>char</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!--告诉过滤器,使用utf-8的编码-->
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>char</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
2 功能模块开发
2.1 查询所有
- 页面
//列表
getAll() {
//发请求获取所有书本
axios.get("../books").then(resp=>{
console.log("查询所有的结果:");
console.log(resp);
this.dataList = resp.data.data;
});
},
- controller
package com.mingye.web;
import com.mingye.bean.Book;
import com.mingye.bean.Result;
import com.mingye.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RequestMapping("/books")
@RestController
public class BookController {
// localhost:82/aa/books ==== GET
@Autowired
private BookService bs;
/**
* 查询所有的书籍
* @return
*/
@GetMapping
public Result findAll(){
List<Book> list = bs.findAll();
return new Result(1, list);
}
}
- service
package com.mingye.service;
import com.mingye.bean.Book;
import java.util.List;
public interface BookService {
List<Book> findAll();
}
package com.mingye.service.impl;
import com.mingye.bean.Book;
import com.mingye.dao.BookDao;
import com.mingye.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@Transactional
public class BookServiceImpl implements BookService {
@Autowired
private BookDao dao;
@Override
public List<Book> findAll() {
return dao.findAll();
}
}
- dao
package com.mingye.dao;
import com.mingye.bean.Book;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
public interface BookDao {
@Select("select * from tbl_book")
List<Book> findAll();
}
2.1 添加图书
- 页面
//添加
handleAdd () {
//发起请求 , 传递参数: this.formData
axios.post("../books" , this.formData) .then(resp=>{
console.log("新增结果:");
console.log(resp);
if(resp.data.code){
//1. 提示
this.$message.success(resp.data.data);
//2. 关闭对话框
this.dialogFormVisible = false;
//3. 重新刷新数据
this.getAll();
}else{
//1. 提示
this.$message.error(resp.data.data);
//2. 关闭对话框
this.dialogFormVisible = false;
}
});
},
- controller
@RequestMapping("/books")
@RestController
public class BookController {
/**
* 新增书籍
* @param book
* @return
*/
@PostMapping
public Result add(@RequestBody Book book){
//1. 调用service
int row = bs.add(book);
//2. 响应结果
if(row > 0){
return new Result(1, "添加成功!");
}else{
return new Result(0, "添加失败!");
}
}
}
- service
package com.mingye.service;
import com.mingye.bean.Book;
import java.util.List;
public interface BookService {
int add(Book book);
}
package com.mingye.service.impl;
import com.mingye.bean.Book;
import com.mingye.dao.BookDao;
import com.mingye.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
//@Transactional
public class BookServiceImpl implements BookService {
@Autowired
private BookDao dao;
@Override
public int add(Book book) {
return dao.add(book);
}
- dao
package com.mingye.dao;
import com.mingye.bean.Book;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
public interface BookDao {
@Insert("insert into tbl_book values (null ,#{type}, #{name} , #{description} )")
int add(Book book);
}
2.1 更新图书
- 页面
//弹出编辑窗口
handleUpdate(row) {
//1. 设置数据,回显数据
//this.updateData = row;
this.updateData = JSON.parse(JSON.stringify(row));
//2. 让对话框展示出来
this.dialogFormVisible4Edit = true;
},
//编辑
handleEdit() {
//发起请求
axios.put("../books" , this.updateData).then(resp=>{
console.log("更新结果:");
console.log(resp);
if(resp.data.code){
//1. 提示
this.$message.success(resp.data.data);
//2. 关闭对话框
this.dialogFormVisible4Edit = false;
//3. 刷新数据
this.getAll();
}else{
//1. 提示
this.$message.error(resp.data.data);
//2. 关闭对话框
this.dialogFormVisible4Edit = false;
}
});
},
- controller
package com.mingye.controller;
/*
所有关于书籍的增删改查的操作,都交给这个类处理
*/
import com.mingye.bean.Book;
import com.mingye.bean.Result;
import com.mingye.constant.Code;
import com.mingye.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RequestMapping("/books")
@RestController
public class BookController {
/**
* 更新书籍
* @param book
* @return
*/
@PutMapping
public Result update(@RequestBody Book book){
//1. 调用service
int row = bs.update(book);
//2. 响应结果
if(row > 0){
return new Result(1, "更新成功!");
}else{
return new Result(0, "更新失败!");
}
}
}
- service
package com.mingye.service;
import com.mingye.bean.Book;
import java.util.List;
public interface BookService {
int update(Book book);
}
@Service
@Transactional
public class BookServiceImpl implements BookService {
@Override
public int update(Book book) {
return dao.update(book);
}
}
- dao
package com.mingye.dao;
import com.mingye.bean.Book;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
public interface BookDao {
@Update("update tbl_book set type=#{type} , name=#{name} , description=#{description} where id = #{id}")
int update(Book book);
}
2.1 删除图书
- 页面
// 删除
handleDelete(row) {
this.$confirm('确定删除该书籍吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//发请求
axios.delete("../books/"+row.id).then(resp=>{
console.log("删除的结果:");
console.log(resp);
if(resp.data.code){
this.$message.success(resp.data.data);
this.getAll();
}else{
this.$message.error(resp.data.data);
}
})
});
}
- controller
package com.mingye.controller;
/*
所有关于书籍的增删改查的操作,都交给这个类处理
*/
import com.mingye.bean.Book;
import com.mingye.bean.Result;
import com.mingye.constant.Code;
import com.mingye.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RequestMapping("/books")
@RestController
public class BookController {
/**
* 删除书籍
* @param id
* @return
*/
@DeleteMapping("/{id}")
public Result delete(@PathVariable int id){
//1. 调用service
int row = bs.delete(id);
//2. 响应结果
if(row > 0){
return new Result(1, "删除成功!");
}else{
return new Result(0, "删除失败!");
}
}
}
- service
package com.mingye.service;
import com.mingye.bean.Book;
import java.util.List;
public interface BookService {
int delete(int id );
}
@Service
@Transactional
public class BookServiceImpl implements BookService {
@Override
public int delete(int id) {
return dao.delete(id);
}
}
- dao
package com.mingye.dao;
import com.mingye.bean.Book;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
public interface BookDao {
@Delete("delete from tbl_book where id = #{id}")
int delete(int id);
}