栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

ssm整合增删改查

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ssm整合增删改查

总体的ssm整合增删改查的思想:

1、一般我们做增删改查的项目的时候,我们可以先从数据层开始写,在数据层把增删改查的功能方法写好,然后再写业务逻辑层的逻辑,业务逻辑层接口的代码基本上和数据层的没什么区别,在业务层增删改查方法中加上和数据层的依赖关系,最后再在表现层加上和业务层的依赖,那么就是说当客户访问表现层的增删改查方法的时候,因为与业务层添加了依赖,那么就可以再调用业务层的增删改查方法,又因为业务层和数据层之间有依赖关系,所以最终就相当于调用了数据层的增删改查方法了~

(其实就是相互调用而已)

2、然后我们的增删改查功能返回的结果,前端肯定想要一眼就能知道访问增删改查的功能到底是否成功了,因此就需要我们把一些返回的数据封装到对象中然后响应给前端了(相当于说响应给前端POJO对象形式的数据),因此就用到了Code、Result类的作用了,下面代码有解释该两个类的作用

3、还要注意一点就是在增删改查功能的过程中,我们的项目难免会出现异常,但是出现异常后,我们不希望返回给前端的是一堆报错500然后一堆异常代码的数据,这样的话客户端就会蒙蔽了,我调用增删该查功能呢这返回的是什么玩意,因此就需要我们做异常的处理,下面代码有解释

4、还有就是客户端访问books.html的时候,因为我们tomcat服务器让客户端访问的路径全部交给springmvc处理了,而springmvc会把访问的books.html路径当成普通的get访问形式,因此在表现层找不到该路径资源,因此就报错了,所以我们希望走的是前端page包下的books.html 就需要我们设置拦截器了 (看restful笔记处理前端访问的那里)

项目总体布局格式如下所示:

 重点理解: 1、异常处理器 2、表现层返回到前端的数据形式(Code、Result类的作用) 3、拦截器
一、表现层代码

BookController:

package com.itheima.controller;

import com.itheima.domain.Book;
import com.itheima.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@RestController // 扫描bean的注解 and 响应给前端数据的注解之合
@RequestMapping("/books")   // 访问路径的注解
public class BookController {

    
    @Autowired  // 自动装配处理依赖关系注解
    private BookService bookService;

    // 增
    @PostMapping    // REST风格访问路径Post动作注解
    public Result save(@RequestBody Book book) {   // @RequestBody注解:json5数据格式封装到book实体类中  // 把返回值类型设定为Result对象

        // 调用业务层的增加方法
        Boolean flag =bookService.save(book);  // 因为BookServiceImpl的save方法中已经把返回的true/false等返回过来了,所以这里保存成功的话,接收业务层返回的true
        return new Result(flag ?Code.SAVE_OK:Code.SAVE_ERR,flag);  // true的话相当于返回的是:(20011,true) 【注:走的是Result两个参数的构造方法】
        // 三元运算符:if flag为true,调用Code的SAVE_OK状态码进行传参
        //return new Result(flag ?Code.SAVE_OK:Code.SAVE_ERR,flag); 就相当于返回Result对象,后面的参数就是为属性赋的值,就相当于响应POJO类型数据
    }

    // 删
    @DeleteMapping(value = "/{id}")
    public Result delete(@PathVariable Integer id) {  // @PathVariable 注解的作用是为id赋上{id}的值   返回类型是Result对象

        // 调用业务层的删除方法
        boolean b = bookService.delete(id);
        return new Result(b? Code.DELETE_OK:Code.DELETE_ERR,b); // 注:这里就相当于往Result对象的属性中赋值,然后又因为方法类型是Result对象,
                                                                // 所以就是说把封装好数据的Result对象返回给前端(这个数据就是商量好的协议)

    }

    // 改
    @PutMapping
    public Result update(@RequestBody Book book) {

        // 调用业务层的修改方法
       boolean b = bookService.update(book);
       return new Result(b? Code.UPDATE_OK:Code.UPDATE_ERR,b);

    }

    // 通过id查询
    @GetMapping(value = "/{id}")
    public Result getById(@PathVariable Integer id) {

        // 调用业务层的通过id查询方法
        Book gs = bookService.getById(id);

        // 有可能通过id查询出来的没有数据,(比如说:数据库就id到5,而想查询id为6的数据,那么就会为null)
        Integer integer = gs != null ? Code.SELECT_OK : Code.SELECT_ERR;    // 如果不等于null SELECT_OK状态码
        String msg = gs != null ? "查询成功~" : "查询失败了~";

        return new Result(gs,integer,msg); // (数据,状态码,消息)

    }

    // 查询所有
    @GetMapping
    public Result getAll() {

        // 调用业务层的查询所有方法
        List all = bookService.getAll();
        // 判断查询出来的数据是否为null,有可能数据库是空的,所以要进行判断
        Integer code = all != null ? Code.SELECT_OK : Code.SELECT_ERR;// 查询出来的数据不为null时,把SELECT_OK状态码赋给code变量名(成功的状态码标识)
        String s = all != null ? "查询成功~" : "数据查询失败,请重试~";
        // (Object data, Integer code, String msg) 构造方法
        return new Result(all,code,s);

    }
}

注意1:

我们知道,客户端通过访问表现层BookController的增删改查的方法,
*          最终调用完增删改查方法拿到结果是我们返回的true或者false、要么就是查询出来的数据
*
*          前端人就开始找事了:说你返回给我的true到底是修改功能返回的true还是增加功能返回的true啊
*          所以为了解决事B,我们用一个类专门封装查询出来的数据,并且标记好状态码(比如1:表示成功,2:表示失败)
*
*          注意:该类的写法在实际开发中,是前后端商量出来的协议,就是说前后端程序员商量好后端的数据以什么样的格式返回给前端

Result类:

package com.itheima.controller;


public class Result {

    private Object data;    // 封装结果数据 (用Object万能,返回给前端数据的时候,可以把Code类中的标识符封装到该属性中)
    private Integer code;   // 标记状态码(比如1:表示成功,2:表示失败)
    private String msg;     // 消息(比如说:调用增删改查功能失败了,返回给前端一句话让前端知道失败了)

    

    public Result() {
    }

    public Result(Integer code,Object data) {
        this.data = data;
        this.code = code;
    }

    public Result(String msg) {
        this.msg = msg;
    }

    public Result(Object data, Integer code, String msg) {
        this.data = data;
        this.code = code;
        this.msg = msg;
    }

    // getter and setter方法
    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

Code类:(专门存放字符标识的类)

package com.itheima.controller;



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 SELECT_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 SELECT_ERR = 20040;


    
    public static final Integer SYSTEM_ERR =50001; // 出现系统异常状态码
    public static final Integer BUSINESS_ERR =60001;   // 出现业务异常状态码


}

客户端访问增加功能时,看返回给前端的信息(可以看出确实比true、false清晰多了):

二、异常处理器代码

* 异常处理器的作用就是:当客户端访问资源路径下的数据的时候,如果该资源路径下的程序出现了异常,那么客户端就会500然后就是一堆异常信息代码,那么客户端就会蒙蔽,我他妈查的是增删改查的功能,这返回的是什么玩意。

因此我们后端就需要异常处理器进行处理异常(忘记的话可以翻前面的笔记)

        而异常又分为:

                系统异常

                业务异常

                其他异常

假设模拟业务层通过id查询功能中出现了系统异常(也就是说:客户端正访问该资源路径下数据的时候,我们服务器宕机了,因此我们为了不直接返回给客户端一堆异常代码500,我们就需要处理系统异常):

package com.itheima.service.impl;

import com.itheima.controller.Code;
import com.itheima.dao.BookDao;
import com.itheima.domain.Book;
import com.itheima.exception.BusinessException;
import com.itheima.exception.SystemException;
import com.itheima.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;


@Service
public class BookServiceImpl implements BookService {

    

    @Autowired // 自动装配(处理依赖关系)注解
    private BookDao bookDao;

    // 增
    public boolean save(Book book) {

        // 调用数据层的增加功能
        bookDao.save(book);
        return true;
    }

    // 删
    public boolean delete(Integer id) {

        // 调用数据层的删除功能
        bookDao.delete(id);
        return true;
    }

    // 改
    public boolean update(Book book) {

        // 调用数据层的修改功能
        bookDao.update(book);
        return true;
    }

    // 通过id查询
    public Book getById(Integer id) {

        

        try {
            int i =1/0; // 模拟系统异常
        } catch (Exception e){
            throw new SystemException("服务器访问超时~",e, Code.SYSTEM_ERR);
            // 把想返回给前端的信息封装到SystemException对象的属性当中
            // Code.SYSTEM_ERR :系统异常状态码标识 50001
        }

        // 调用数据层的通过id查询功能
        Book books = bookDao.getById(id);
        return books;
    }

    // 查询所有
    public List getAll() {

        // 调用数据层的查询所有功能
        List list = bookDao.getAll();
        return list;
    }
}

 这里捕获到系统异常后,就要把想要返回给前端用户的提示信息封装到系统异常类当中,然后通过异常处理器进行系统异常的处理并且把封装在系统异常类属性中提示的信息响应给前端用户:

系统数据封装类:(该类的作用其实就是起到一个封装数据的作用)

SystemException:

package com.itheima.exception;


public class SystemException extends RuntimeException{

    private Integer code;    // 加个code编号属性,来标注以后出现的是哪一种异常

    

    public SystemException(Integer code) {
        this.code = code;
    }

    public SystemException(String message, Integer code) {
        super(message);
        this.code = code;
    }

    public SystemException(String message, Throwable cause, Integer code) {
        super(message, cause);
        this.code = code;
    }

    public SystemException(Throwable cause, Integer code) {
        super(cause);
        this.code = code;
    }

    public SystemException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Integer code) {
        super(message, cause, enableSuppression, writableStackTrace);
        this.code = code;
    }

    
    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }
}

然后上面封装好数据后,就进入到异常处理器:

异常处理器:

        专门处理系统异常、业务异常、其他异常并且把封装的数据响应给前端用户

注: 通常使用异常处理器时:都会把系统异常处理方法、业务异常处理方法、其他异常处理方法全先写出来,然后项目中出现哪种形式的异常,异常处理器就直接可以进行处理了

ProjectExceptionAdvice: 

package com.itheima.controller;

import com.itheima.exception.BusinessException;
import com.itheima.exception.SystemException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;



// @ControllerAdvice // 这是普通风格处理异常的注解 (只要访问路径用的不是REST风格就用这个注解)
@RestControllerAdvice   // 这是REST风格的处理异常的注解 (告诉spring这是一个处理异常的类的注解)
// 注1:这个@RestControllerAdvice注解需要被SpringMvcConfig类的@ComponentScan({"com.itheima.controller"})注解
// 扫描到,(SpringMvcConfig类的扫描注解刚好扫到controller包下,所以能扫到,因此如果换成其他的包,记得扫一下)

public class ProjectExceptionAdvice {

    

    @ExceptionHandler(SystemException.class)    // 该注解作用: 拦截是否是系统异常,是的话就调用下面的方法进行处理异常
    public Result doSystemException(SystemException sy){
            // (SystemException sy):把SystemException对象传递过来(因为刚才业务层模拟系统异常的时候,把返回给前端的信息封装到sy对象属性中了)
        

        return new Result(null,sy.getCode(), sy.getMessage());
        // 把封装到sy系统异常类属性中的系统异常状态码信息返回给用户
    }

    

    @ExceptionHandler(BusinessException.class)   //  拦截是否是业务异常,是的话就调用下面的方法进行处理异常
    public Result doBusinessException(BusinessException bs){


        return new Result(null,bs.getCode(),bs.getMessage());
    }

    

    @ExceptionHandler(Exception.class)    //  拦截是否是其他异常,是的话就调用下面的方法进行处理异常
    public Result doException(){

        return new Result(null,0,"出现异常了铁子~");
    }
}

 测试:

假设通过id查询的功能存在系统异常,与因为我们异常处理器处理该异常并且响应给前端相对应的数据了(比如:直接响应个服务器访问超时~),演示如下所示:(直接返回给客户端一些服务器访问超时信息什么的,而不是直接返回报错500然后一堆异常代码)

三、拦截器(看笔记)

SpringMvcSupport:

package com.itheima.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;



@Configuration

public class SpringMvcSupport extends WebMvcConfigurationSupport {

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry){
        // 意思就是说:当客户端访问/pages

@Configuration

public class SpringMvcSupport extends WebMvcConfigurationSupport {

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry){
        // 意思就是说:当客户端访问/pages
    @Autowired  // 自动装配处理依赖关系注解
    private BookService bookService;

    // 增
    @PostMapping    // REST风格访问路径Post动作注解
    public Result save(@RequestBody Book book) {   // @RequestBody注解:json5数据格式封装到book实体类中  // 把返回值类型设定为Result对象

        // 调用业务层的增加方法
        Boolean flag =bookService.save(book);  // 因为BookServiceImpl的save方法中已经把返回的true/false等返回过来了,所以这里保存成功的话,接收业务层返回的true
        return new Result(flag ?Code.SAVE_OK:Code.SAVE_ERR,flag);  // true的话相当于返回的是:(20011,true) 【注:走的是Result两个参数的构造方法】
        // 三元运算符:if flag为true,调用Code的SAVE_OK状态码进行传参
        //return new Result(flag ?Code.SAVE_OK:Code.SAVE_ERR,flag); 就相当于返回Result对象,后面的参数就是为属性赋的值,就相当于响应POJO类型数据
    }

    // 删
    @DeleteMapping(value = "/{id}")
    public Result delete(@PathVariable Integer id) {  // @PathVariable 注解的作用是为id赋上{id}的值   返回类型是Result对象

        // 调用业务层的删除方法
        boolean b = bookService.delete(id);
        return new Result(b? Code.DELETE_OK:Code.DELETE_ERR,b); // 注:这里就相当于往Result对象的属性中赋值,然后又因为方法类型是Result对象,
                                                                // 所以就是说把封装好数据的Result对象返回给前端(这个数据就是商量好的协议)

    }

    // 改
    @PutMapping
    public Result update(@RequestBody Book book) {

        // 调用业务层的修改方法
       boolean b = bookService.update(book);
       return new Result(b? Code.UPDATE_OK:Code.UPDATE_ERR,b);

    }

    // 通过id查询
    @GetMapping(value = "/{id}")
    public Result getById(@PathVariable Integer id) {

        // 调用业务层的通过id查询方法
        Book gs = bookService.getById(id);

        // 有可能通过id查询出来的没有数据,(比如说:数据库就id到5,而想查询id为6的数据,那么就会为null)
        Integer integer = gs != null ? Code.SELECT_OK : Code.SELECT_ERR;    // 如果不等于null SELECT_OK状态码
        String msg = gs != null ? "查询成功~" : "查询失败了~";

        return new Result(gs,integer,msg); // (数据,状态码,消息)

    }

    // 查询所有
    @GetMapping
    public Result getAll() {

        // 调用业务层的查询所有方法
        List all = bookService.getAll();
        // 判断查询出来的数据是否为null,有可能数据库是空的,所以要进行判断
        Integer code = all != null ? Code.SELECT_OK : Code.SELECT_ERR;// 查询出来的数据不为null时,把SELECT_OK状态码赋给code变量名(成功的状态码标识)
        String s = all != null ? "查询成功~" : "数据查询失败,请重试~";
        // (Object data, Integer code, String msg) 构造方法
        return new Result(all,code,s);

    }
}

ProjectExceptionAdvice异常处理器:

package com.itheima.controller;

import com.itheima.exception.BusinessException;
import com.itheima.exception.SystemException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;



// @ControllerAdvice // 这是普通风格处理异常的注解 (只要访问路径用的不是REST风格就用这个注解)
@RestControllerAdvice   // 这是REST风格的处理异常的注解 (告诉spring这是一个处理异常的类的注解)
// 注1:这个@RestControllerAdvice注解需要被SpringMvcConfig类的@ComponentScan({"com.itheima.controller"})注解
// 扫描到,(SpringMvcConfig类的扫描注解刚好扫到controller包下,所以能扫到,因此如果换成其他的包,记得扫一下)

public class ProjectExceptionAdvice {

    

    @ExceptionHandler(SystemException.class)    // 该注解作用: 拦截是否是系统异常,是的话就调用下面的方法进行处理异常
    public Result doSystemException(SystemException sy){
            // (SystemException sy):把SystemException对象传递过来(因为刚才业务层模拟系统异常的时候,把返回给前端的信息封装到sy对象属性中了)
        

        return new Result(null,sy.getCode(), sy.getMessage());
        // 把封装到sy系统异常类属性中的系统异常状态码信息返回给用户
    }

    

    @ExceptionHandler(BusinessException.class)   //  拦截是否是业务异常,是的话就调用下面的方法进行处理异常
    public Result doBusinessException(BusinessException bs){


        return new Result(null,bs.getCode(),bs.getMessage());
    }

    

    @ExceptionHandler(Exception.class)    //  拦截是否是其他异常,是的话就调用下面的方法进行处理异常
    public Result doException(){

        return new Result(null,0,"出现异常了铁子~");
    }
}
4.2、业务层代码

BookService:

package com.itheima.service;
import com.itheima.domain.Book;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;



@Transactional  // 为下面的增删改查功能添加开启spring事务的注解
public interface BookService {

    
    public boolean save(Book book);

    
    public boolean delete(Integer id);

    
    public boolean update(Book book);

    
    public Book getById(Integer id);

    
    public List getAll();
}

BookServiceImpl: 

package com.itheima.service.impl;

import com.itheima.controller.Code;
import com.itheima.dao.BookDao;
import com.itheima.domain.Book;
import com.itheima.exception.BusinessException;
import com.itheima.exception.SystemException;
import com.itheima.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;


@Service
public class BookServiceImpl implements BookService {

    

    @Autowired // 自动装配(处理依赖关系)注解
    private BookDao bookDao;

    // 增
    public boolean save(Book book) {

        // 调用数据层的增加功能
        bookDao.save(book);
        return true;
    }

    // 删
    public boolean delete(Integer id) {

        // 调用数据层的删除功能
        bookDao.delete(id);
        return true;
    }

    // 改
    public boolean update(Book book) {

        // 调用数据层的修改功能
        bookDao.update(book);
        return true;
    }

    // 通过id查询
    public Book getById(Integer id) {

        

        try {
            int i =1/0; // 模拟系统异常
        } catch (Exception e){
            throw new SystemException("服务器访问超时~",e, Code.SYSTEM_ERR);
            // 把想返回给前端的信息封装到SystemException对象的属性当中
            // Code.SYSTEM_ERR :系统异常状态码标识 50001
        }

        // 调用数据层的通过id查询功能
        Book books = bookDao.getById(id);
        return books;
    }

    // 查询所有
    public List getAll() {

        // 调用数据层的查询所有功能
        List list = bookDao.getAll();
        return list;
    }
}

4.3、数据层代码

BookDao:

package com.itheima.dao;

import com.itheima.domain.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})")
    public void save(Book book);

    // 删
    @Delete("delete from tbl_book where id =#{id}")
    public void delete(Integer id);

    // 改
    @Update("update tbl_book set type =#{type},name =#{name},description =#{description}")
    public void update(Book book);

    // 查 (通过id查单条数据)
    @Select("select * from tbl_book where id =#{id}")
    public Book getById(Integer id);

    // 查(查全部数据)
    @Select("select * from tbl_book")
    public List getAll();
}

BookDaoImpl:

package com.itheima.dao.impl;

import com.itheima.dao.BookDao;
import com.itheima.domain.Book;
import java.util.List;

public class BookDaoImpl implements BookDao {

    public void save(Book book) {

    }

    public void delete(Integer id) {

    }

    public void update(Book book) {

    }

    public Book getById(Integer id) {
        return null;
    }

    public List getAll() {
        return null;
    }
}
4.4、系统/业务异常类:(代码都是一样的)
package com.itheima.exception;


public class SystemException extends RuntimeException{

    private Integer code;    // 加个code编号属性,来标注以后出现的是哪一种异常

    

    public SystemException(Integer code) {
        this.code = code;
    }

    public SystemException(String message, Integer code) {
        super(message);
        this.code = code;
    }

    public SystemException(String message, Throwable cause, Integer code) {
        super(message, cause);
        this.code = code;
    }

    public SystemException(Throwable cause, Integer code) {
        super(cause);
        this.code = code;
    }

    public SystemException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Integer code) {
        super(message, cause, enableSuppression, writableStackTrace);
        this.code = code;
    }

    
    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }
}

Book类:

package com.itheima.domain;

public class Book {

    private Integer id;
    private String type;
    private String name;
    private String description;

    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", type='" + type + ''' +
                ", name='" + name + ''' +
                ", description='" + description + ''' +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1031557.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号