• SpringMVC(二)




    一、RestFul


    REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的。Fielding是一个非常重要的人,他是HTTP协议(1.0版和1.1版)的主要设计者、Apache服务器软件的作者之一、Apache基金会的第一任主席。所以,他的这篇论文一经发表,就引起了关注,并且立即对互联网开发产生了深远的影响。


    他这样介绍论文的写作目的:

    “本文研究计算机科学两大前沿----软件和网络----的交叉点。长期以来,软件研究主要关注软件设计的分类、设计方法的演化,很少客观地评估不同的设计选择对系统行为的影响。而相反地,网络研究主要关注系统之间通信行为的细节、如何改进特定通信机制的表现,常常忽视了一个事实,那就是改变应用程序的互动风格比改变互动协议,对整体表现有更大的影响。我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。”

    RESTful 是一种设计风格。它不是一种标准,也不是一种软件,而是一种思想。


    特点:


    每一个URI(请求地址)代表1种资源;

    • 以前我们认为url地址它是一个动作: 增删改查的动作

      • localhost:8080/项目名/findAllUser

      • lolcahost:8080/项目名/deleteUser?id=3

    • rest设计风格认为地址是一种资源,体现的只有名词,而没有动词。

      • localhost:8080/项目名/user/3 : 删除id为3

      • localhost:8080/项目名/user/3 : 查询id为3

    客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;、

    • 由于地址不能体现出来动作,包含的都是名词,没有动词,那么服务端如何区分出来客户端想要执行的是什么操作呢?

    • 采用请求方式来区分 localhost:8080/项目名/user/3

      • 新增 ----- post请求

      • 查询 ----- get请求

      • 删除 ----- delete请求

      • 更新 ----- put请求

    客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息


    接口结构


    如何设计接口


    域名

    应该尽量将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:获取信息,关于资源的哪些属性是客户端可以改变的
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    示例说明


    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方法,用户新增


    小结

    1. RESTful 是一种设计风格 , 可以用,也可以不用!

    2. 每一个URI代表1种资源,地址里面只能出现名词,不能出现动词。

    3. 客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;


    基本实现


    在postman工具里面测试


    User

    package com.execise.bean;
    
    import lombok.Data;
    
    @Data
    public class User {
        private String username;
        private String password;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    UserController

    package com.execise.controller;
    
    import com.execise.bean.User;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.*;
    
    /*
        这是用来处理一切与用户有关请求的controller
     */
    @Controller
    public class UserController {
    
        /*
            新增:
                以前:  localhost:82/addUser        GET|POST
                restFul :  localhost:82/user       POST
         */
    //    @RequestMapping(value = "/user", method = RequestMethod.POST)
    
        @ResponseBody
        @PostMapping("/user")
        public String add(User user ){
            System.out.println("add..." + user);
            return "add success...";
        }
    
    
        /*
            删除:
                以前: localhost:82/deleteUser?id=1         GET
                restFul: localhost:82/user/1               DELETE
         */
        @ResponseBody
        @DeleteMapping("/user/{id}")
        public String delete(@PathVariable int id){
            System.out.println("delete...id=" + id);
            return "delete success...";
        }
    
    
        /*
            修改:
                 以前: localhost:82/updateUser            GET|POST
                restFul: localhost:82/user                 PUT
    
            更新的操作比较特殊一些:
                springmvc不会从put请求里面拿请求体的数据出来,赋值给方法参数。
                所以看到的都是null!
         */
        @ResponseBody
        @PutMapping("/user")
        public String update(User user){
            System.out.println("update..." + user);
            return "update success...";
        }
    
    
        /*
            根据id来查询用户:
                  以前: localhost:82/findUserById?id=1            GET
                restFul: localhost:82/user/1                       GET
         */
        @ResponseBody
        @GetMapping("/user/{id}")
        public String findById(@PathVariable int id){
            System.out.println("findById..." + id);
            return "findById success...";
        }
    
    
        /*
            查询所有:
                 以前: localhost:82/findAll                        GET
                restFul: localhost:82/user                         GET
         */
        @ResponseBody
        @GetMapping("/user")
        public String findAll(){
            System.out.println("findAll..." );
            return "findAll success...";
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    小结

    1. 创建Maven web工程

    2. 创建Pojo

    3. 创建Controller ,定义增删改查方法

    4. 分别使用 get | post | put | delete 来指定方法请求方式

    二、表现层数据封装


    1 表现层响应数据的问题


    问题:我们表现层增删改方法返回true或者false表示是否成功,getById()方法返回一个json对象,getAll()方法返回一个json对象数组,这里就出现了三种格式的响应结果,极其不利于前端解析。


    在这里插入图片描述


    解决:我们需要统一响应结果的格式


    2 定义Result类封装响应结果


    Result类封装响应结果

    public class Result {
        //描述统一格式中的数据
        private Object data;
        //描述统一格式中的编码,用于区分操作,可以简化配置0或1表示成功失败
        private Integer code;
        //描述统一格式中的消息,可选属性
        private String msg;
    
        public Result() {
        }
        public Result(Integer code,Object data) {
            this.data = data;
            this.code = code;
        }
        public Result(Integer code, Object data, String msg) {
            this.data = data;
            this.code = code;
            this.msg = msg;
        }
         //同学们自己添加getter、setter、toString()方法
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    注意事项:

    Result类中的字段并不是固定的,可以根据需要自行增减


    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    注意事项:

    Code类的常量设计也不是固定的,可以根据需要自行增减,例如将查询再进行细分为GET_OK,GET_ALL_OK,GET_PAGE_OK


    3 表现层数据封装返回Result对象


    @RestController
    @RequestMapping("/books")
    public class BookController {
    
        @Autowired
        private BookService bookService;
    
        @PostMapping
        public Result save(@RequestBody Book book) {
            boolean flag = bookService.save(book);
            return new Result(flag ? Code.SAVE_OK:Code.SAVE_ERR,flag);
        }
    
        @PutMapping
        public Result update(@RequestBody Book book) {
            boolean flag = bookService.update(book);
            return new Result(flag ? Code.UPDATE_OK:Code.UPDATE_ERR,flag);
        }
    
        @DeleteMapping("/{id}")
        public Result delete(@PathVariable Integer id) {
            boolean flag = bookService.delete(id);
            return new Result(flag ? Code.DELETE_OK:Code.DELETE_ERR,flag);
        }
    
        @GetMapping("/{id}")
        public Result getById(@PathVariable Integer id) {
            Book book = bookService.getById(id);
            Integer code = book != null ? Code.GET_OK : Code.GET_ERR;
            String msg = book != null ? "" : "数据查询失败,请重试!";
            return new Result(code,book,msg);
        }
    
        @GetMapping
        public Result getAll() {
            List<Book> bookList = bookService.getAll();
            Integer code = bookList != null ? Code.GET_OK : Code.GET_ERR;
            String msg = bookList != null ? "" : "数据查询失败,请重试!";
            return new Result(code,bookList,msg);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    三、异常处理器


    程序开发过程中不可避免的会遇到异常现象,我们不能让用户看到这样的页面数据


    在这里插入图片描述


    出现异常现象的常见位置与常见诱因如下:

    • 框架内部抛出的异常:因使用不合规导致

    • 数据层抛出的异常:因外部服务器故障导致(例如:服务器访问超时)

    • 业务层抛出的异常:因业务逻辑书写错误导致(例如:遍历业务书写操作,导致索引异常等)

    • 表现层抛出的异常:因数据收集、校验等规则导致(例如:不匹配的数据类型间导致异常)

    • 工具类抛出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)


    编写异常处理器

    @RestControllerAdvice  //用于标识当前类为REST风格对应的异常处理器
    public class ProjectExceptionAdvice {
    
        //统一处理所有的Exception异常
        @ExceptionHandler(Exception.class)
        public Result doOtherException(Exception ex){
            return new Result(666,null);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用异常处理器之后的效果


    在这里插入图片描述


    @RestControllerAdvice注解介绍

    • 名称:@RestControllerAdvice

    • 类型:类注解

    • 位置:Rest风格开发的控制器增强类定义上方

    • 作用:为Rest风格开发的控制器类做增强

    • 说明:此注解自带@ResponseBody注解与@Component注解,具备对应的功能


    @ExceptionHandler注解介绍

    • 名称:@ExceptionHandler

    • 类型:方法注解

    • 位置:专用于异常处理的控制器方法上方

    • 作用:设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原始控制器执行,并转入当前方法执行

    • 说明:此类方法可以根据处理的异常不同,制作多个方法分别处理对应的异常


    项目异常处理方案


    项目当前异常的分类以及对应类型异常该如何处理?


    1 项目异常分类


    业务异常(BusinessException)

    • 规范的用户行为产生的异常

    • 不规范的用户行为操作产生的异常

    系统异常(SystemException)

    • 项目运行过程中可预计且无法避免的异常

    其他异常(Exception)

    • 编程人员未预期到的异常

    2 项目异常处理方案


    业务异常(BusinessException)

    • 发送对应消息传递给用户,提醒规范操作

    系统异常(SystemException)

    • 发送固定消息传递给用户,安抚用户

    发送特定消息给运维人员,提醒维护

    • 记录日志

    其他异常(Exception)

    • 发送固定消息传递给用户,安抚用户

    • 发送特定消息给编程人员,提醒维护(纳入预期范围内)

    • 记录日志


    3 项目异常处理代码实现


    根据异常分类自定义异常类


    自定义项目系统级异常

    //自定义异常处理器,用于封装异常信息,对异常进行分类
    public class SystemException extends RuntimeException{
        private Integer code;
    
        public Integer getCode() {
            return code;
        }
    
        public void setCode(Integer code) {
            this.code = code;
        }
    
        public SystemException(Integer code, String message) {
            super(message);
            this.code = code;
        }
    
        public SystemException(Integer code, String message, Throwable cause) {
            super(message, cause);
            this.code = code;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    自定义项目业务级异常

    //自定义异常处理器,用于封装异常信息,对异常进行分类
    public class BusinessException extends RuntimeException{
        private Integer code;
    
        public Integer getCode() {
            return code;
        }
    
        public void setCode(Integer code) {
            this.code = code;
        }
    
        public BusinessException(Integer code, String message) {
            super(message);
            this.code = code;
        }
    
        public BusinessException(Integer code,String message,Throwable cause) {
            super(message, cause);
            this.code = code;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    自定义异常编码(持续补充)

    public class Code {
    
    	//之前其他状态码省略没写,以下是新补充的状态码,可以根据需要自己补充
        
        public static final Integer SYSTEM_ERR = 50001;
        public static final Integer SYSTEM_TIMEOUT_ERR = 50002;
        public static final Integer SYSTEM_UNKNOW_ERR = 59999;
        public static final Integer BUSINESS_ERR = 60002;
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    触发自定义异常

    @Service
    public class BookServiceImpl implements BookService {
        @Autowired
        private BookDao bookDao;
    
    	//在getById演示触发异常,其他方法省略没有写进来
        public Book getById(Integer id) {
            //模拟业务异常,包装成自定义异常
            if(id <0){
                throw new BusinessException(Code.BUSINESS_ERR,"请不要使用你的技术挑战我的耐性!");
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在异常通知类中拦截并处理异常

    @RestControllerAdvice //用于标识当前类为REST风格对应的异常处理器
    public class ProjectExceptionAdvice {
        //@ExceptionHandler用于设置当前处理器类对应的异常类型
        @ExceptionHandler(SystemException.class)
        public Result doSystemException(SystemException ex){
            //记录日志
            //发送消息给运维
            //发送邮件给开发人员,ex对象发送给开发人员
            return new Result(ex.getCode(),null,ex.getMessage());
        }
    
        @ExceptionHandler(BusinessException.class)
        public Result doBusinessException(BusinessException ex){
            return new Result(ex.getCode(),null,ex.getMessage());
        }
    
        //除了自定义的异常处理器,保留对Exception类型的异常处理,用于处理非预期的异常
        @ExceptionHandler(Exception.class)
        public Result doOtherException(Exception ex){
            //记录日志
            //发送消息给运维
            //发送邮件给开发人员,ex对象发送给开发人员
            return new Result(Code.SYSTEM_UNKNOW_ERR,null,"系统繁忙,请稍后再试!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    测试:在postman中发送请求访问getById方法,传递参数-1,得到以下结果:


    在这里插入图片描述


    四、拦截器


    问题1:拦截器拦截的对象是谁?

    问题2:拦截器和过滤器有什么区别?


    拦截器概念和作用


    在这里插入图片描述


    拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行

    作用:

    1. 在指定的方法调用前后执行预先设定的代码

    2. 阻止原始方法的执行

    3. 总结:增强

    核心原理:AOP思想


    拦截器和过滤器的区别

    归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术

    拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强


    在这里插入图片描述


    拦截器代码实现


    【第一步】定义拦截器

    做法:定义一个类,实现HandlerInterceptor接口即可


    @Component //注意当前类必须受Spring容器控制
    //定义拦截器类,实现HandlerInterceptor接口
    public class ProjectInterceptor implements HandlerInterceptor {
        @Override
        //原始方法调用前执行的内容
        //返回值类型可以拦截控制的执行,true放行,false终止
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle..."+contentType);
            return true;
        }
    
        @Override
        //原始方法调用后执行的内容
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle...");
        }
    
        @Override
        //原始方法调用完成后执行的内容
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("afterCompletion...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    【第二步】配置加载拦截器

    @Configuration
    public class SpringMvcSupport extends WebMvcConfigurationSupport {
        @Autowired
        private ProjectInterceptor projectInterceptor;
    
        @Override
        protected void addInterceptors(InterceptorRegistry registry) {
            //配置拦截器
            registry.addInterceptor(projectInterceptor)
                .addPathPatterns("/books","/books/*");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    使用标准接口WebMvcConfigurer简化开发(注意:侵入式较强)

    @Configuration
    @ComponentScan({"com.execise.controller"})
    @EnableWebMvc
    //实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
    public class SpringMvcConfig implements WebMvcConfigurer {
        @Autowired
        private ProjectInterceptor projectInterceptor;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            //配置多拦截器
            registry.addInterceptor(projectInterceptor)
                .addPathPatterns("/books","/books/*");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    拦截器流程分析


    在这里插入图片描述


    拦截器参数


    postHandle()和afterCompletion()方法都是处理器方法执行之后执行,有什么区别?


    前置处理

    //原始方法调用前执行的内容
    //返回值类型可以拦截控制的执行,true放行,false终止
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle..."+contentType);
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    参数

    1. request:请求对象

    2. response:响应对象

    3. handler:被调用的处理器对象,本质上是一个方法对象,对反射技术中的Method对象进行了再包装

    返回值为false,被拦截的处理器将不执行。


    后置处理

    //原始方法调用后执行的内容
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle...");
    }
    
    • 1
    • 2
    • 3
    • 4

    参数

    modelAndView:如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息,并进行跳转


    注意:如果处理器方法出现异常了,该方法不会执行


    完成后处理

    //原始方法调用完成后执行的内容
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion...");
    }
    
    • 1
    • 2
    • 3
    • 4

    参数

    ex:如果处理器执行过程中出现异常对象,可以针对异常情况进行单独处理


    注意:无论处理器方法内部是否出现异常,该方法都会执行。


    拦截器链配置


    什么是拦截器链?


    多个拦截器配置


    定义第二个拦截器

    @Component
    public class ProjectInterceptor2 implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle...222");
            return false;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle...222");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("afterCompletion...222");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    配置第二个拦截器

    @Configuration
    @ComponentScan({"com.execise.controller"})
    @EnableWebMvc
    //实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
    public class SpringMvcConfig implements WebMvcConfigurer {
        @Autowired
        private ProjectInterceptor projectInterceptor;
        @Autowired
        private ProjectInterceptor2 projectInterceptor2;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            //配置多拦截器
            registry.addInterceptor(projectInterceptor)
                .addPathPatterns("/books","/books/*");
            registry.addInterceptor(projectInterceptor2)
                .addPathPatterns("/books","/books/*");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    多个连接器工作流程分析

    • 当配置多个拦截器时,形成拦截器链

    • 拦截器链的运行顺序参照拦截器添加顺序为准

    • 当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行

    • 当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作


    在这里插入图片描述


    五、整合SSM


    SSM整合流程

    1. 创建数据库,创建Maven工程【javaweb】,添加依赖

    2. 添加页面

    3. SSM整合

      • Spring

        • applicationContext.xml
      • MyBatis

        • db.properties
      • SpringMVC

        • springmvc.xml

        • web.xml

    4. 功能模块

      • 表与实体类

      • 工具类(Result、Code)

      • dao(接口+自动代理)

      • service(接口+实现类)

        • 业务层接口测试(整合JUnit)
      • controller

        • 表现层接口测试(PostMan)

    SSM整合配置


    创建工程,添加依赖和插件


      
      <properties>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <maven.compiler.source>1.8maven.compiler.source>
        <maven.compiler.target>1.8maven.compiler.target>
      properties>
    
      
      <dependencies>
        
        <dependency>
          <groupId>junitgroupId>
          <artifactId>junitartifactId>
          <version>4.12version>
          <scope>testscope>
        dependency>
        
        <dependency>
          <groupId>org.springframeworkgroupId>
          <artifactId>spring-webmvcartifactId>
          <version>5.1.2.RELEASEversion>
        dependency>
        
        <dependency>
          <groupId>org.aspectjgroupId>
          <artifactId>aspectjweaverartifactId>
          <version>1.9.4version>
        dependency>
    
        
        
        <dependency>
          <groupId>mysqlgroupId>
          <artifactId>mysql-connector-javaartifactId>
          <version>5.1.47version>
        dependency>
        
        <dependency>
          <groupId>com.alibabagroupId>
          <artifactId>druidartifactId>
          <version>1.1.23version>
        dependency>
        
        <dependency>
          <groupId>org.mybatisgroupId>
          <artifactId>mybatisartifactId>
          <version>3.5.6version>
        dependency>
        
        
        <dependency>
          <groupId>org.mybatisgroupId>
          <artifactId>mybatis-springartifactId>
          <version>2.0.6version>
        dependency>
        
        <dependency>
          <groupId>org.springframeworkgroupId>
          <artifactId>spring-jdbcartifactId>
          <version>5.1.2.RELEASEversion>
        dependency>
    
        
        
        <dependency>
          <groupId>org.slf4jgroupId>
          <artifactId>slf4j-apiartifactId>
          <version>1.7.20version>
        dependency>
        
        <dependency>
          <groupId>ch.qos.logbackgroupId>
          <artifactId>logback-classicartifactId>
          <version>1.2.3version>
        dependency>
        
        <dependency>
          <groupId>ch.qos.logbackgroupId>
          <artifactId>logback-coreartifactId>
          <version>1.2.3version>
        dependency>
        
        <dependency>
          <groupId>com.fasterxml.jackson.coregroupId>
          <artifactId>jackson-databindartifactId>
          <version>2.9.6version>
        dependency>
        
        <dependency>
          <groupId>org.projectlombokgroupId>
          <artifactId>lombokartifactId>
          <version>1.18.18version>
          <scope>providedscope>
        dependency>
        
        <dependency>
          <groupId>javax.servletgroupId>
          <artifactId>javax.servlet-apiartifactId>
          <version>3.1.0version>
          <scope>providedscope>
        dependency>
      dependencies>
    
      <build>
          <plugins>
            <plugin>
              <groupId>org.apache.tomcat.mavengroupId>
              <artifactId>tomcat7-maven-pluginartifactId>
              <version>2.2version>
              <configuration>
                
                <port>80port>
                
                <path>/path>
              configuration>
            plugin>
          plugins>
      build>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118

    Spring整合Mybatis


    创建数据库和表

    -- 创建ssm_db数据库
    CREATE DATABASE IF NOT EXISTS day35_ssm CHARACTER SET utf8;
    
    -- 使用ssm_db数据库
    USE day35_ssm;
    
    -- 创建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+');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    db.properties属性文件


    db.driverClass=com.mysql.jdbc.Driver
    db.url=jdbc:mysql://localhost:3306/day35_ssm
    db.username=root
    db.password=root
    
    • 1
    • 2
    • 3
    • 4

    Spring整合MyBatis

    定义 spring-mybatis.xml


    
    <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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    
        
       
    
        
        
        <context:property-placeholder location="classpath:db.properties"/>
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="${db.driverClass}"/>
            <property name="url" value="${db.url}"/>
            <property name="username" value="${db.username}"/>
            <property name="password" value="${db.password}"/>
        bean>
    
        
        <bean class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
    
            <property name="typeAliasesPackage" value="com.execise.bean"/>
        bean>
    
        
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.execise.dao"/>
        bean>
    
        
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        bean>
    
        
        <tx:annotation-driven transaction-manager="transactionManager"/>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    Spring整合SpringMVC

    定义springmvc.xml


    
    <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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
        
        <context:component-scan base-package="com.execise"/>
    
        
        <mvc:annotation-driven/>
    
        
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/"/>
            <property name="suffix" value=".jsp"/>
        bean>
    
        
        <mvc:default-servlet-handler/>
    
        
        <import resource="spring-mybatis.xml"/>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    web.xml

    
    <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">
    
    	
    		<servlet>
    			<servlet-name>dispatcherservlet-name>
    			<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    
    			<init-param>
    				<param-name>contextConfigLocationparam-name>
    				<param-value>classpath:springmvc.xmlparam-value>
    			init-param>
    
    			<load-on-startup>1load-on-startup>
    		servlet>
    
    		<servlet-mapping>
    			<servlet-name>dispatcherservlet-name>
    			<url-pattern>/url-pattern>
    		servlet-mapping>
    web-app>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    功能模块开发


    查询所有


    页面

    //添加
    handleAdd() {
    
        //1. 提交请求
        axios.post("/books", this.formData).then(response=>{
            console.log("添加的结果:");
            console.log(response);
    
            //2. 判定
            this.dialogFormVisible = false;
            if(response.data.code  === 20001){
                //提示
                this.$message.success(response.data.msg);
    
                //添加成功了,需要重新载入数据
                this.getAll();
            }else{
                this.$message.error(response.data.msg);
            }
        })
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    controller

    package com.execise.controller;
    
    /*
        所有关于书籍的增删改查的操作,都交给这个类处理
     */
    
    import com.execise.bean.Book;
    import com.execise.bean.Result;
    import com.execise.constant.Code;
    import com.execise.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 {
    
        @Autowired
        private BookService bs;
    
        /*
            查询所有
         */
        @GetMapping
        public Result findAll(){
            Result result = null;
    
            try {
                //1. 调用service
                List<Book> list = bs.findAll();
    
                //成功
                result = new Result(Code.GET_ALL_BOOK_SUCCESS, list , "查询所有书籍成功");
            } catch (Exception e) {
                e.printStackTrace();
    
                //失败
                result = new Result(Code.GET_ALL_BOOK_FAILED,  "查询所有书籍失败");
            }
    
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    service

    package com.execise.service;
    
    import com.execise.bean.Book;
    
    import java.util.List;
    
    public interface BookService {
    
        List<Book> findAll();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    package com.execise.service.impl;
    
    import com.execise.bean.Book;
    import com.execise.dao.BookDao;
    import com.execise.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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    dao

    package com.execise.dao;
    
    import com.execise.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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    添加图书


    页面

     //添加
    handleAdd() {
    
        //1. 提交请求
        axios.post("/books", this.formData).then(response=>{
            console.log("添加的结果:");
            console.log(response);
    
            //2. 判定
            this.dialogFormVisible = false;
            if(response.data.code  === 20001){
                //提示
                this.$message.success(response.data.msg);
    
                //添加成功了,需要重新载入数据
                this.getAll();
            }else{
                this.$message.error(response.data.msg);
            }
        })
    },	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    controller

    @RequestMapping("/books")
    @RestController
    public class BookController {
    
        @PostMapping
        public Result add(@RequestBody Book book){
    
            //1. 调用service干活
            int row = bs.add(book);
    
            //2. 响应
            Result result = null;
            if(row > 0 ){
                result = new Result(Code.ADD_SUCCESS , "添加书籍成功!");
            }else{
                result = new Result(Code.ADD_FAILED , "添加书籍失败!");
            }
            return result;
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    service

    package com.execise.service;
    
    import com.execise.bean.Book;
    
    import java.util.List;
    
    public interface BookService {
    
        int add(Book book);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    package com.execise.service.impl;
    
    import com.execise.bean.Book;
    import com.execise.dao.BookDao;
    import com.execise.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);
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    dao

    package com.execise.dao;
    
    import com.execise.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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    更新图书


    页面

    //弹出编辑窗口
    handleUpdate(row) {
    
        //1. 弹出编辑的对话框
        this.dialogFormVisible4Edit = true;
    
        //2. 回显数据
        //this.formData = row;
        this.formData = JSON.parse(JSON.stringify(row));
    
    },
    
    //编辑
    handleEdit() {
        //1. 发起请求
        axios.put("/books" , this.formData).then(response=>{
            console.log("更新结果:");
            console.log(response);
    
            //不管成功或者失败,都要让对话框消失
            this.dialogFormVisible4Edit = false;
    
            if(response.data.code === 20002){
                this.$message.success(response.data.msg);
                //重新载入数据
                this.getAll();
            }else{
                this.$message.error(response.data.msg);
            }
        });
    
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    controller

    package com.execise.controller;
    
    /*
        所有关于书籍的增删改查的操作,都交给这个类处理
     */
    
    import com.execise.bean.Book;
    import com.execise.bean.Result;
    import com.execise.constant.Code;
    import com.execise.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 {
        @PutMapping
        public Result update(@RequestBody Book book){
            System.out.println("book = " + book);
    
            //1. 交代service干活
            int row = bs.update(book);
    
            //2. 响应
            Result result = null;
            if(row > 0){
                result = new Result(Code.UPDATE_SUCCESS , "更新图书成功" );
            }else{
                result = new Result(Code.UPDATE_FAILED , "更新图书失败" );
            }
            return result;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    service

    package com.execise.service;
    
    import com.execise.bean.Book;
    
    import java.util.List;
    
    public interface BookService {
    
        int update(Book book);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    @Service
    @Transactional
    public class BookServiceImpl implements BookService {  
    	@Override
        public int update(Book book) {
            return dao.update(book);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    dao

    package com.execise.dao;
    
    import com.execise.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);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    删除图书


    页面

    // 删除
    handleDelete(row) {
    
        this.$confirm('确定删除该图书吗?', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
        }).then(() => {
    
            //点击确定就来到这里了。
            //axios.get("请求地址?id="+row.id)
            axios.delete("/books/"+row.id).then(response=>{
                console.log("删除结果:");
                console.log(response);
    
                if(response.data.code === 20003){
                    this.$message.success(response.data.msg);
                    this.getAll();
                }else{
                    this.$message.error(response.data.msg);
                }
            });
    
        }).catch(() => {
            this.$message({
                type: 'info',
                message: '已取消删除'
            });
        });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    controller

    package com.execise.controller;
    
    /*
        所有关于书籍的增删改查的操作,都交给这个类处理
     */
    
    import com.execise.bean.Book;
    import com.execise.bean.Result;
    import com.execise.constant.Code;
    import com.execise.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 {
        @DeleteMapping("/{id}")
        public Result delete(@PathVariable int id){
    
            //1. 调用service
            int row = bs.delete(id);
    
            //2. 响应
            Result result = null;
            if(row > 0){
                result = new Result(Code.DELETE_SUCCESS , "删除图书成功" );
            }else{
                result = new Result(Code.DELETE_FAILED , "删除图书失败" );
            }
            return result;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    service

    package com.execise.service;
    
    import com.execise.bean.Book;
    
    import java.util.List;
    
    public interface BookService {
        int delete(int id );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    @Service
    @Transactional
    public class BookServiceImpl implements BookService {
       	@Override
        public int delete(int id) {
            return dao.delete(id);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    dao

     package com.execise.dao;
    
    import com.execise.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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    IDEA中 tomcat 控制台中文乱码解决
    机器学习(第二章)—— 模型评估
    面试必备:虾皮服务端15连问
    Java面试题(每天10题)-------连载(31)
    前端知识记录
    5. computed 和 watch 的区别?
    go-cqhttp环境配置
    华为OD机试真题-计算误码率-2023年OD统一考试(B卷)
    【HarmonyOS】鸿蒙中如何获取用户相册图片?photoAccessHelper.PhotoViewPicker
    Redis 中的事务分析,Redis 中的事务可以满足ACID属性吗?
  • 原文地址:https://blog.csdn.net/m0_67559541/article/details/126710904