SpringMVC-day02
01_基于SSM的三层架构
目标
- 了解基于SSM框架的三层架构技术体系
路径
- SSM框架的三层架构技术体系
SSM框架的三层架构技术体系
在三层架构开发时会使用到SSM框架:
- 表现层:SpringMVC
- 业务层:Spring
- 数据访问层:Mybatis
在使用SSM框架搭建三层架构时:
- Spring ,管理全项目
- IoC(父容器):管理除web层以外的bean
- AOP :一般用在业务层(声明式事务放在业务层)
- SpringMVC ,管理web层
- 基于Spring
- IoC(子容器):管理web层的bean
- 父子容器:子容器可以访问父容器中的bean (反之不行)
- AOP:统一异常处理器、拦截器
- IoC(子容器):管理web层的bean
- 封装web
- 三大组件:Servlet(DispatcherServlet 前端控制器)、Filter(CharacterEncodeingFilter 乱码过滤器)、Listener
- 请求、响应:请求参数映射、响应数据自动转换json格式
- 基于Spring
- Mybatis ,管理dao层
- 和数据库交互
小结
在三层架构体系中:
- SpringMVC,属于表现层 (使用自己独立的IOC容器)
- 接收前端请求
- 处理请求(交给业务层完成)
- 给前端响应
- Spring,属于业务层(使用Spring的IOC容器)
- 处理业务逻辑
- Mybatis,属于持久层(由Spring的IOC容器管理)
- 和数据库交互
02_SSM框架整合流程
目标
- 了解SSM框架整合的流程
路径
- SSM框架整合的流程
SSM框架整合的流程
SSM框架整合流程步骤:
- 创建项目工程
- 创建包(分包):config、dao、service、controller、domain
- 搭建Spring框架环境
- 导入Spring相关依赖
- 编写SpingConfig配置类
- Spring整合Mybatis框架(业务层和持久层整合)
- 导入坐标:MySQL、Mybatis、druid、Spring-jdbc、mybatis-spring
- 编写配置类:
- JdbcConfig // 连接池、事务管理器
- MybatisConfig
- 修改SpringConfig
- 编写dao层代码
- 编写service层代码
- Spring整合SpringMVC框架(业务层和表现层整合)
- 导入坐标:Servlet、Jackson、Springmvc
- 编写配置类
- ServletConfig //Web容器配置类
- SpringmvcConfig //SpringMVC配置类
- 编写web层代码(Controller)
项目工程结构目录:
03_SSM整合-搭建Spring环境
目标
- 能够搭建Spring框架环境
路径
- 导入坐标
- 编写Spring配置类
导入坐标
pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>springmvc_day02-ssm</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<!-- 依赖管理 -->
<dependencies>
<!-- SpringMVC(底层依赖Spring)-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
</project>
编写Spring配置类
SpringConfig:
/* Spring IoC容器(父容器)
1. 管理除Controller包之外的所有bean
2. spring的组件扫描 : 扫描controller包之外的其他包
1). 方案一: 一个个配置,就是不配置controller包
2). 方案二: 全扫描,排除controller包
ComponentScan
I. value : 要扫描的包
II. excludeFilters : 排除不扫描 Controller和 RestController注解
a. type : 要排除的类型 (注解)
b. classes : 要排除的类
*/
/*@ComponentScan(value = "com.itheima",
excludeFilters = {
@ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = {Controller.class, RestController.class}
)
}
)*/
//Spring配置类 (添加到IoC容器中)
@Configuration
@ComponentScan({"com.itheima.service"}) //扫描service层包
public class SpringConfig {
}
04_SSM整合-Spring整合Mybatis
目标
- 能够使用Spring整合Mybatis,实现对数据的CRUD操作
路径
- 导入坐标
- 编写配置类
- 编写dao层
- 编写service层
- 测试service层功能
数据库:
create database ssm_db;
use ssm_db;
create table tbl_book(
id int primary key auto_increment,
type varchar(20),
name varchar(50),
description varchar(255)
);
INSERT INTO `tbl_book` VALUES ('1', '编程', 'Spring实战', 'spring入门经典教程');
INSERT INTO `tbl_book` VALUES ('2', '编程', 'springmvc实战', 'springmvc经典教程');
INSERT INTO `tbl_book` VALUES ('3', '编程', 'mybatis入门', '手把手教你操作数据库');
INSERT INTO `tbl_book` VALUES ('4', '市场营销', '直播就该这么做', '李佳琦,薇娅推荐');
INSERT INTO `tbl_book` VALUES ('5', '市场营销', '直播带货', '一本教你如何玩转直播的书');
导入坐标
<!-- Spring整合Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- Spring JDBC : 声明式事务 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- Spring整合Junit -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- druid连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.1</version>
</dependency>
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
编写配置类
db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/ssm_db
jdbc.username=root
jdbc.password=itheima
JdbcConfig:连接池配置、事务管理器
//配置:连接池、事务管理器
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
//设置连接池
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
//设置事务管理器 (声明式事务)
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
//PlatformTransactionManager是DataSourceTransactionManager的父接口
DataSourceTransactionManager dstm = new DataSourceTransactionManager();
dstm.setDataSource(dataSource);
return dstm;
}
}
MybatisConfig
//Mybatis配置类
public class MybatisConfig {
@Bean
public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource ds){
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
//设置pojo的包扫描
factoryBean.setTypeAliasesPackage("com.itheima.domain");
//设置连接池
factoryBean.setDataSource(ds);
return factoryBean;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer msc = new MapperScannerConfigurer();
//设置dao层的接口扫描
msc.setBasePackage("com.itheima.dao");
return msc;
}
}
SpringConfig修改
@Configuration //Spring配置类 (添加到IoC容器中)
@ComponentScan({"com.itheima.service"}) //扫描指定包下的类,并添加到IoC容器
@PropertySource("classpath:db.properties") //加载外部配置文件
@Import({JdbcConfig.class, MybatisConfig.class}) //引入配置类
@EnableTransactionManagement //开启事务管理支持
public class SpringConfig {
}
编写dao层
dao层:
public interface BookDao {
@Insert("insert into tbl_book (type,name,description) values(#{type},#{name},#{description})")
public int save(Book book);
@Update("update tbl_book set type = #{type}, name = #{name}, description = #{description} where id = #{id}")
public int update(Book book);
@Delete("delete from tbl_book where id = #{id}")
public int delete(Integer id);
@Select("select id, type, name, description from tbl_book where id = #{id}")
public Book getById(Integer id);
@Select("select id, type, name, description from tbl_book")
public List<Book> getAll();
}
编写service层
service层:
//接口
@Transactional //给接口的每个方法添加事务
public interface IBookService {
/**
* 保存
* @param book
* @return
*/
public boolean saveBook(Book book);
/**
* 修改
* @param book
* @return
*/
public boolean updateBook(Book book);
/**
* 按id删除
* @param id
* @return
*/
public boolean deleteBookById(Integer id);
/**
* 按id查询
* @param id
* @return
*/
public Book getBookById(Integer id);
/**
* 查询全部
* @return
*/
public List<Book> getAllBook();
}
//实现类
@Service
public class BookServiceImpl implements IBookService {
@Autowired
private BookDao bookDao;
@Override
public boolean saveBook(Book book) {
int result = bookDao.save(book);
if(result>0){
return true;
}
return false;
}
@Override
public boolean updateBook(Book book) {
bookDao.update(book);
return true;
}
@Override
public boolean deleteBookById(Integer id) {
bookDao.delete(id);
return true;
}
@Override
public Book getBookById(Integer id) {
Book book = bookDao.getById(id);
return book;
}
@Override
public List<Book> getAllBook() {
List<Book> bookList = bookDao.getAll();
return bookList;
}
}
测试service层功能
测试类:
@RunWith(SpringJUnit4ClassRunner.class)//spring整合junit
@ContextConfiguration(classes = SpringConfig.class)//加载注解配置类
public class BookServiceTest {
@Autowired
IBookService bookService;
@Test
public void testGetBook() {
Book book = bookService.getBookById(1);
System.out.println(book);
}
@Test
public void testGetAllBook() {
List<Book> bookList = bookService.getAllBook();
for (Book book : bookList) {
System.out.println(book);
}
}
@Test
public void testSaveBook(){
Book book = new Book();
book.setType("编程");
book.setName("MySQL高级");
book.setDescription("MySQL数据库的高级应用开发");
boolean result = bookService.saveBook(book);
System.out.println(result);
}
}
05_SSM整合-Spring整合SpringMVC
目标
- 能够使用Spring整合SpringMVC,实现前端数据交互
路径
- 导入坐标
- 编写配置类
- 编写Controller类
- 使用postman测试
导入坐标
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Jackson : 实现json格式和javabean之间的数据转换 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
编写配置类
SpringMVC配置类
@Configuration
@ComponentScan("com.itheima.controller") //springmvc的ioc容器只管理web层相关的bean
@EnableWebMvc //开启javabean自动转换json
public class SpringmvcConfig {
}
Web容器配置类
public class ServletInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
//指定spring配置类加载(根配置)
return new Class[]{SpringConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
//指定springmvc配置类加载
return new Class[]{SpringmvcConfig.class};
}
@Override
protected String[] getServletMappings() {
//配置springmvc拦截路径为 / (全路径)
return new String[]{"/"};
}
//中文乱码过滤器
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("utf-8");
return new Filter[]{encodingFilter};
}
}
-
配置启动顺序:
-
Tomcat启动,利用SPI机制加载ServletInitConfig
-
在ServletInitConfig中,先加载SpringConfig,然后加载SpringmvcConfig,最后设置SpringMVC中的DispatcherServlet的匹配路径为:
/
-
SpringConfig
-
1、加载com.itheima.service下的bean(IoC父容器)
-
2、加载jdbc.properties文件
-
3、加载mybatis配置类:JdbcConfig、MybatisConfig
- 将com.itheima.dao下的bean放到父容器
-
-
SpringmvcConfig
- 加载com.itheima.controller下的bean(子容器)
-
父子容器:子容器可以访问父容器中的bean (反之不行)
编写Controller类
BookController
//RESTful风格
@RestController
@RequestMapping("/book")
public class BookController {
@Autowired
private IBookService bookService;
@PostMapping
public boolean save(@RequestBody Book book) {
return bookService.saveBook(book);
}
@PutMapping
public boolean update(@RequestBody Book book) {
return bookService.updateBook(book);
}
@DeleteMapping("/{id}")
public boolean delete(@PathVariable Integer id) {
return bookService.deleteBookById(id);
}
@GetMapping("/{id}")
public Book getById(@PathVariable Integer id) {
return bookService.getBookById(id);
}
@GetMapping
public List<Book> getAll() {
return bookService.getAllBook();
}
}
使用postman测试
-
修改
-
查询
06_SSM整合-封装表现层数据
目标
- 能够使用封装的方式优化表现层响应的数据
路径
- 表现层存在的问题
- 改造表现层:对响应的数据进行统一封装
表现层存在的问题
现在后端程序响应的数据格式是五花八门,这种情况不利于前端解析,同时也加大了前后端交互的难度
解决方案:对响应的数据进行统一的封装 (自定义交互协议)
改造表现层:对响应的数据进行统一封装
添加:响应结果类(Result)、状态码类(Code)
响应结果类:设置统一数据返回结果
- 说明:Result类中的字段并不是固定的,可以根据需要自行增减
public class Result{
//描述统一格式中的数据
private Object data;
//描述统一格式中的编码,用于区分操作,可以简化配置0或1表示成功失败
private Integer code;
//描述统一格式中的消息,可选属性
private String msg;
public Result() {
}
//可用于增删改操作的响应结果(查询失败也可以用)
public Result(Integer code,String msg) {
this.msg = msg;
this.code = code;
}
//可用于查询成功
public Result(Integer code, Object data, String msg) {
this.data = data;
this.code = code;
this.msg = msg;
}
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;
}
}
Result responseResult = new Result(响应状态码, 响应的数据, 响应状态消息);
问题:在Result类中有指定响应状态码,那么响应状态码应该怎么定义呢?
- 可以参照之前学习http协议时有接触过的状态码。如:200、404、500
自定义状态码:设置统一数据返回结果编码
//状态码
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 = 50010;//保存失败
public static final Integer DELETE_ERR = 50020;//删除失败
public static final Integer UPDATE_ERR = 50030;//修改失败
public static final Integer GET_ERR = 50040;//查询失败
}
- 说明:Code类的常量设计也不是固定的,可以根据需要自行增减
- 例如:将查询再进行细分为GET_OK,GET_ALL_OK,GET_PAGE_OK
修改BookController类:
@RestController
@RequestMapping("/book")
public class BookController {
@Autowired
private IBookService bookService;
@PostMapping
public Result save(@RequestBody Book book) {
boolean result = bookService.saveBook(book);
Integer code = result ? Code.SAVE_OK : Code.SAVE_ERR;
String message = result ? "保存成功" : "保存失败";
return new Result(code, result, message);
}
@PutMapping
public Result update(@RequestBody Book book) {
boolean result = bookService.updateBook(book);
Integer code = result ? Code.UPDATE_OK : Code.UPDATE_ERR;
String message = result ? "修改成功" : "修改失败";
return new Result(code, result, message);
}
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
boolean result = bookService.deleteBookById(id);
Integer code = result ? Code.DELETE_OK : Code.DELETE_ERR;
String message = result ? "删除成功" : "删除失败";
return new Result(code, result, message);
}
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id) {
Book book = bookService.getBookById(id);
Integer code = book != null ? Code.GET_OK : Code.GET_ERR;
String message = book != null ? "查询用户成功" : "查询用户失败";
return new Result(code, book, message);
}
@GetMapping
public Result getAll() {
List<Book> bookList = bookService.getAllBook();
Integer code = bookList != null && bookList.size() != 0 ? Code.GET_OK : Code.GET_ERR;
String message = bookList != null && bookList.size() != 0 ? "查询全部成功" : "查询全部失败";
return new Result(code, bookList, message);
}
}
使用postman测试:
-
修改
-
查询
-
查询失败
07_SpringMVC异常处理器
目标
- 了解SpringMVC异常处理器
路径
- 三层架构下的异常现象
- SpringMVC的异常处理器
三层架构下的异常现象
在三层架构下异常现象出现的位置与诱因:
- 框架内部抛出的异常:因使用不合规导致
- 数据层抛出的异常:因外部服务器故障导致(如:服务器访问超时)
- 业务层抛出的异常:因业务逻辑书写错误导致(如:遍历过程中出现索引异常)
- 表现层抛出的异常:因数据收集、校验等规则导致(如:不匹配的数据类型导致异常)
- 工具类抛出的异常:因工具类书写不严谨不够健壮导致(如:要释放的连接长期未释放)
思考:各层都可能出现异常,那么异常处理代码应该写在哪一层?
之前:学习Java时,可以把异常都抛出到main方法中,在main方法中进行统一处理。
现在:三层架构体系下,把异常都抛出到表现层(controller)进行处理
思考:在表现层处理异常时,每个方法都可能会存在异常,如果在每个方法中都添加异常处理代码,代码书写量巨大且意义不强,如何解决?
AOP思想
SpringMVC参照AOP思想,设计了可以统一处理项目中发生异常的处理器
-- 切面 = 切入点 + 通知
-- 切入点: controller层所有方法
-- 通知: 异常通知
SpringMVC的异常处理器
AOP思想:
- 切面 = 切入点 + 通知
- 切入点 : controller的方法
- 通知 : 异常通知
SpringMVC的异常处理器可以集中的、统一的处理项目中出现的异常
- 为SpringMVC控制器类做增强
//@RestControllerAdvice = @ResponseBody + @ControllerAdvice
//此注解自带@ResponseBody注解与@ControllerAdvice注解,具备对应的功能
@RestControllerAdvice
public class ProjectExceptionAdvice {
/*
专门处理Exception类型异常的通知
1. 此方法在controller层代码抛出异常之后
2. 并且此异常类型为Exception,那么此方法就会运行
3. 而且参数ex就是所发生的异常
*/
@ExceptionHandler(Exception.class)
public Result doException(Exception ex){
ex.printStackTrace();
return new Result(666,null);
}
}
08_项目异常处理方案
目标
- 能够在SSM项目中添加自定义异常处理
路径
- 项目中异常的分类
- 改造SSM项目:添加异常处理
项目中异常的分类
异常出现的可能情况:
- 代码写错了:程序员自身原因
- 用户出错了:程序有一部分数据是由用户输入的
- 系统的影响:项目所依赖的整个环境(tomcat,mysql)
项目中异常分类:
- 业务异常(BusinessException) 用户行为产生的异常
- 系统异常(SystemException) 项目运行过程中可预计且无法避免的异常(数据库崩溃)
- 其他异常(Exception) 编程人员未预期到的异常
项目中异常处理方案
- 业务异常(BusinessException)
- 发送对应消息传递给用户,提醒规范操作
- 记录日志
- 系统异常(SystemException)
- 发送固定消息传递给用户,安抚用户
- 发送特定消息给运维人员,提醒维护
- 记录日志
- 其他异常(Exception)
- 发送固定消息传递给用户,安抚用户
- 发送特定消息给编程人员,提醒维护(纳入预期范围内)
- 记录日志
SpringMVC中异常处理示例
添加:自定义异常类、异常通知类
自定义异常处理器: 用于封装异常信息,对异常进行分类
//业务异常处理器
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;
}
}
//系统异常处理器
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;
}
}
自定义异常状态码:
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 = 50010;//保存失败
public static final Integer DELETE_ERR = 50020;//删除失败
public static final Integer UPDATE_ERR = 50030;//修改失败
public static final Integer GET_ERR = 50040;//查询失败
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 = 60001; //业务异常
}
异常通知:
@RestControllerAdvice
public class ProjectExceptionAdvice {
//专门处理业务功能导致的异常
@ExceptionHandler(BusinessException.class)
public Result doBusinessException(BusinessException ex){
//发送对应消息传递给用户,提醒规范操作
return new Result(ex.getCode(),ex.getMessage());
}
//专门处理系统异常
@ExceptionHandler(SystemException.class)
public Result doSystemException(SystemException ex){
//发送固定消息传递给用户,安抚用户
//发送特定消息给运维人员,提醒维护
//记录日志
return new Result(ex.getCode(),ex.getMessage());
}
//处理其他未知异常
@ExceptionHandler(Exception.class)
public Result doException(Exception ex){
//发送固定消息传递给用户,安抚用户
//发送特定消息给编程人员,提醒维护
//记录日志
return new Result(Code.SYSTEM_UNKNOW_ERR,"服务器正在维护,请稍后访问");
}
}
修改业务类(模拟异常发生)
@Service
public class BookServiceImpl implements IBookService {
@Autowired
private BookDao bookDao;//由于idea不能很好的识别spring整合myabtis的配置,所以可能报错,但实际运行没有问题
@Override
public boolean saveBook(Book book) {
int result = bookDao.save(book);
if(result>0){
return true;
}
return false;
}
@Override
public boolean updateBook(Book book) {
bookDao.update(book);
return true;
}
@Override
public boolean deleteBookById(Integer id) {
bookDao.delete(id);
return true;
}
@Override
public Book getBookById(Integer id) {
//业务逻辑判断:传递参数的合法性(用户录入)
if (id < 0) {
//业务异常: 用户造成的
throw new BusinessException(Code.BUSINESS_ERR, "用户id不能为负数");
}
Book book = null;
try {
//数据库可能有问题抛出异常
book = bookDao.getById(id);
} catch (Exception e) {
throw new SystemException(Code.SYSTEM_ERR, "当前访问人数较多,请稍后访问");
}
//模拟未知异常
int i = 1 / 0;
return book;
}
@Override
public List<Book> getAllBook() {
List<Book> bookList = bookDao.getAll();
return bookList;
}
}
使用postman测试:
09_SpringMVC拦截器
目标
- 了解SpringMVC中拦截器的概念
路径
- 拦截器介绍
- 拦截器和过滤器的区别
- 拦截器的应用场景
拦截器介绍
在前面学习Servlet技术时,有使用过:Filter(过滤器)
而在SpringMVC中有存在类似于Filter的功能:拦截器(Interceptor)。用于对controller进行预处理和后处理。
拦截器:
- 拦截器是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行
- 作用:
- 在指定的controller方法前后执行预先设定的代码
- 阻止controlle方法的执行
- 原理:AOP思想
拦截器和过滤器的区别
官方:
黑马:
- 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
- 拦截内容不同:Filter对所有访问进行拦截,Interceptor仅针对SpringMVC的访问进行拦截
- 执行顺序:先执行过滤器,然后再能执行拦截器
拦截器的应用场景
应用场景:
- 权限检查
- 如登录检测,进入处理器前检测用户是否登录,如果没有登陆直接返回到登录页面。
- 性能监控
- 有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,统计处理器执行使用了多少时间。
10_SpringMVC拦截器的使用
目标
- 能够使用SpringMVC拦截器增强contorller功能
路径
- 拦截器的使用步骤
- 拦截器的使用示例
拦截器的使用步骤
要使用SpringMVC拦截器,必须实现HandlerInterceptor接口,重写接口中的方法:
-
preHandle() ,在contorller方法执行前拦截
-
postHandle() ,在contorller方法执行后拦截
-
afterCompletion ,在视图解析器解析完毕后拦截
拦截器使用步骤:
- 自定义拦截器(通知)
- 创建类并实现HandlerInterceptor接口,重写接口中的方法
- 配置拦截器的拦截规则(切入点)
拦截器的使用示例
代码示例:
- 自定义拦截器(通知)
//定义拦截器类,实现HandlerInterceptor接口
@Component //当前类必须受Spring容器控制
public class TimeConsumeInterceptor implements HandlerInterceptor {
long beginTime;//开始时间
long endTime;//结束时间
//原始方法调用前增强的功能
/**
* @param request 请求对象
* @param response 响应对象
* @param handler 处理器方法的封装(方法对象)
* @return true:表示资源放行 、 false:资源禁止访问
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle... 开始计时");
beginTime = System.currentTimeMillis();
return true;//返回值类型可以拦截控制的执行。 true放行,false终止
}
//原始方法调用后执行增强的功能
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle... 结束计时");
endTime = System.currentTimeMillis();
//强制转换为:HandlerMethod (反射中的Method对象再次包装)
HandlerMethod handlerMethod = (HandlerMethod) handler;
//获取controller方法的名字
String methodName = handlerMethod.getMethod().getName();
System.out.println(methodName+"方法执行,耗时:" + (endTime - beginTime) + "毫秒");
}
}
- 配置拦截器的拦截规则(切入点)
//拦截器配置类
@Configuration
public class SpringmvcSupport extends WebMvcConfigurationSupport {
@Autowired
private TimeConsumeInterceptor timeConsumeInterceptor;
@Override
protected void addInterceptors(InterceptorRegistry registry) {
//配置拦截器 设定拦截的访问路径,路径可以通过可变参数设置多个
registry.addInterceptor(timeConsumeInterceptor)
.addPathPatterns("/book","/book/*");
}
}
//修改SpringmvcConfig配置类: 添加扫描包
@Configuration
@ComponentScan({"com.itheima.controller","com.itheima.config"}) //新增扫描包
@EnableWebMvc
public class SpringmvcConfig {
}
//输出结果:
preHandle... 开始计时
postHandle... 结束计时
getAll方法执行,耗时:7毫秒
使用标准接口WebMvcConfigurer简化开发 (侵入式编码)
@Configuration
//@ComponentScan({"com.itheima.controller","com.itheima.config"})
@ComponentScan("com.itheima.controller")
@EnableWebMvc
public class SpringmvcConfig implements WebMvcConfigurer {
@Autowired
private TimeConsumeInterceptor timeConsumeInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//配置拦截器 设定拦截的访问路径,路径可以通过可变参数设置多个
registry.addInterceptor(timeConsumeInterceptor)
.addPathPatterns("/book","/book/*");
}
}
11_SpringMVC拦截器链
目标
- 了解SpringMVC中的拦截器链
路径
- 拦截器链介绍
- 拦截器链示例
拦截器链介绍
拦截器链:
-
当配置多个拦截器时,就形成拦截器链
-
拦截器链的运行顺序参照拦截器添加顺序为准
-
当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
实际开发中,尽量避免多拦截器的使用,因为请求拦截器的增多会造成请求链路的增长,那么执行请求的效率也会降低
以上图中3个拦截器为例说明:
规律:当3个拦截器的pre方法都返回true时,则对应的所有post和after方法都会被执行;
规律:当有一个pre方法返回false时,所有的post方法都不会被执行;
规律:after方法只有在对应的pre方法被执行且返回true时才执行;
拦截器链示例
代码示例:
- 自定义拦截器(通知)
@Component
public class ProjectInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("ProjectInterceptor => preHandle");
return true;//放行:执行controller方法
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
System.out.println("ProjectInterceptor => postHandle");
}
}
- 配置多个拦截器(切入点)
@Configuration
public class SpringmvcSupport extends WebMvcConfigurationSupport {
@Autowired
private TimeConsumeInterceptor timeConsumeInterceptor;
@Autowired
private ProjectInterceptor projectInterceptorl;
protected void addInterceptors(InterceptorRegistry registry) {
//配置多个拦截器
registry.addInterceptor(timeConsumeInterceptor)
.addPathPatterns("/book","/book/*");
registry.addInterceptor(projectInterceptorl)
.addPathPatterns("/book","/book/*");
}
}
//输出结果:
preHandle... 开始计时
ProjectInterceptor => preHandle
ProjectInterceptor => postHandle
postHandle... 结束计时
getAll方法执行,耗时:6毫秒
12_在SpringMVC中访问静态资源
目标
- 能够解决在SpringMVC中访问静态资源时存在的问题
路径
- 问题演示
- 解决问题
问题演示
向项目工程下,添加web静态资源:
启动Tomcat,访问页面时,会出现404错误(找不到资源):
原理分析:
解决问题
在config包下,新建配置类:SpringmvcSupport
@Configuration
public class SpringmvcSupport extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
}
}
修改SpringMVC配置类:
@Configuration
@ComponentScan({"com.itheima.controller","com.itheima.config"}) //新增扫描包
@EnableWebMvc //开启javabean自动转换json
public class SpringmvcConfig {
}
再次访问books.html页面:
13_前端vue代码实现
目标
- 能够编写vue代码,实现和后端程序的交互
路径
- 查询功能
查询功能
books.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>SpringMVC案例</title>
<meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport">
<!-- 引入样式 -->
<link rel="stylesheet" href="../plugins/elementui/index.css">
<link rel="stylesheet" href="../plugins/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="../css/style.css">
</head>
<body class="hold-transition">
<div id="app">
<div class="content-header">
<h1>图书管理</h1>
</div>
<div class="app-container">
<div class="box">
<div class="filter-container">
<el-input placeholder="图书名称" v-model="pagination.queryString" style="width: 200px;"
class="filter-item"></el-input>
<el-button @click="getAll()" class="dalfBut">查询</el-button>
<el-button type="primary" class="butT" @click="handleCreate()">新建</el-button>
</div>
<el-table size="small" current-row-key="id" :data="dataList" stripe highlight-current-row>
<el-table-column type="index" align="center" label="序号"></el-table-column>
<el-table-column prop="type" label="图书类别" align="center"></el-table-column>
<el-table-column prop="name" label="图书名称" align="center"></el-table-column>
<el-table-column prop="description" label="描述" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button>
<el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 新增标签弹层 -->
<div class="add-form">
<el-dialog title="新增图书" :visible.sync="dialogFormVisible">
<el-form ref="dataAddForm" :model="formData" :rules="rules" label-position="right"
label-width="100px">
<el-row>
<el-col :span="12">
<el-form-item label="图书类别" prop="type">
<el-input v-model="formData.type"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="图书名称" prop="name">
<el-input v-model="formData.name"/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="描述">
<el-input v-model="formData.description" type="textarea"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="handleAdd()">确定</el-button>
</div>
</el-dialog>
</div>
<!-- 编辑标签弹层 -->
<div class="add-form">
<el-dialog title="编辑检查项" :visible.sync="dialogFormVisible4Edit">
<el-form ref="dataEditForm" :model="formData" :rules="rules" label-position="right"
label-width="100px">
<el-row>
<el-col :span="12">
<el-form-item label="图书类别" prop="type">
<el-input v-model="formData.type"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="图书名称" prop="name">
<el-input v-model="formData.name"/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="描述">
<el-input v-model="formData.description" type="textarea"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible4Edit = false">取消</el-button>
<el-button type="primary" @click="handleEdit()">确定</el-button>
</div>
</el-dialog>
</div>
</div>
</div>
</div>
</body>
<!-- 引入组件库 -->
<script src="../js/vue.js"></script>
<script src="../plugins/elementui/index.js"></script>
<script type="text/javascript" src="../js/jquery.min.js"></script>
<script src="../js/axios-0.18.0.js"></script>
<script>
/*
* TODO: Vue就两部分内容
* 1. 视图 : html(界面)
* 1). 不用脚手架 <body>
2). 脚手架 <template>
* 2. 脚本 : js(data数据,methods交互)
* <script>
* TODO: Vue的理念
* 1). 数据绑定 (通用)
* 视图绑定脚本中的data数据 -> data数据改变,视图会随之改变
* 2). 双向数据绑定 (表单 : v-model)
* data数据改变,视图会随之改变
* 视图改变,data数据也会随之改变
* TODO: 交互部分,是不需要关注视图,关注data数据
* 发送请求,获取数据,设置到data中
*
* 视图 <- data <- 交互
* */
var vue = new Vue({
el: '#app',
data: {
pagination: {},
dataList: [],//当前页要展示的列表数据
formData: {},//表单数据
dialogFormVisible: false,//控制表单是否可见
dialogFormVisible4Edit: false,//编辑表单是否可见
rules: {//校验规则
type: [{required: true, message: '图书类别为必填项', trigger: 'blur'}],
name: [{required: true, message: '图书名称为必填项', trigger: 'blur'}]
},
url: "/book"
},
//钩子函数,VUE对象初始化完成后自动执行
created() {
this.getAll();
},
methods: {
//列表 TODO:
getAll() {
//查询 : 发起一个查询请求,接收数据,设置给dataList
axios.get(this.url).then(response => {
console.log(response.data);
if (response.data.code == 20041) {
this.dataList = response.data.data
} else {
this.$message.error(response.data.msg);
}
})
},
//重置表单
resetForm() {
this.formData = {};
},
//弹出添加窗口
handleCreate() {
this.dialogFormVisible = true;
this.resetForm();
},
//弹出编辑窗口
handleUpdate(row) {
this.formData = row
this.dialogFormVisible4Edit = true;
},
//TODO:省略....
}
});
</script>
</html>
扩展:文件上传
目标
- 能够使用SpringMVC接收上传的文件
路径
- 客户端文件上传要求
- SpringMVC的文件上传
客户端文件上传要求
浏览器客户端实现文件上传的要求:
- form表单的method属性设置为
post
方式- get的请求参数拼接url中,体现在地址栏,长度是受限
- post请求参数放在请求体中,长度不受限
- form表单的enctype属性设置为
multipart/form-data
,默认是:x-www-form-urlencoded - form表单中需要一个的文本选择域
<form method="post" enctype="multipart/form-data">
头像: <input type="file" name="file" /> <!-- 上传文件项 -->
<input type="submit" value="提交表单" />
</form>
SpringMVC的文件上传
代码示例:
-
前端
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>文件上传</h1> <form action="uploadfile" method="post" enctype="multipart/form-data"> <!-- 普通表单项 --> 用户名: <input type="text" name="username"/> <br> 密码: <input type="text" name="password" /> <br> <!-- 上传文件项 --> 头像: <input type="file" name="myFile" /> <br> <input type="submit" value="提交表单" /> </form> </body> </html>
-
后端
- 导入坐标
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.2</version> </dependency>
- 配置类:SpringMvcSupport
@Configuration public class SpringMvcSupport extends WebMvcConfigurationSupport { /** * 释放静态资源 * @param registry */ @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/pages/**").addResourceLocations("/pages/"); registry.addResourceHandler("/js/**").addResourceLocations("/js/"); } //配置多媒体解析器,方法名须为:multipartResolver @Bean public CommonsMultipartResolver multipartResolver(){ CommonsMultipartResolver resolver = new CommonsMultipartResolver(); //设置上传文件的总大小,单位是字节 100MB resolver.setMaxUploadSize(1024*1024*100); //设置每个文件上传的大小,单位是字节 10MB resolver.setMaxUploadSizePerFile(1024*1024*10); return resolver; } }
- Controller
@RestController public class UploadController { /** * 注意参数名跟前端name属性一致 * @param username * @param password * @param myFile 本质是个InputStream * springmvc用这个对象封装了前端发送的文件数据 * @return */ @PostMapping("/uploadfile") public String upload(String username, String password, MultipartFile myFile) throws IOException { System.out.println(username + "," + password); System.out.println(myFile); String name = myFile.getName(); System.out.println("属性名:" + name); String originalFilename = myFile.getOriginalFilename(); System.out.println("文件名:" + originalFilename); //随机文件名 String randomName = UUID.randomUUID().toString().replaceAll("-", ""); //切割文件名: 6.jpg =切割=> 6 jpg String[] split = originalFilename.split("\\."); String fileName = "f:/upload/" + randomName + "." + split[1]; //创建文件对象 File destFile = new File(fileName); //将myFile数据写到destFile去 myFile.transferTo(destFile); return "success"; } }
扩展:使用postman进行图片上传测试
附录:SSM整合案例完整依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itheima</groupId>
<artifactId>springmvc_day02-ssm</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<!-- 依赖管理 -->
<dependencies>
<!-- SpringMVC(底层依赖Spring)-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- Spring整合Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- Spring JDBC : 声明式事务 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- Spring整合Junit -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- druid连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.1</version>
</dependency>
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Jackson : 实现json格式和javabean之间的数据转换 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
</project>
附录:books.html完整代码
books.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>SpringMVC案例</title>
<meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport">
<!-- 引入样式 -->
<link rel="stylesheet" href="../plugins/elementui/index.css">
<link rel="stylesheet" href="../plugins/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="../css/style.css">
</head>
<body class="hold-transition">
<div id="app">
<div class="content-header">
<h1>图书管理</h1>
</div>
<div class="app-container">
<div class="box">
<div class="filter-container">
<el-input placeholder="图书名称" v-model="pagination.queryString" style="width: 200px;"
class="filter-item"></el-input>
<el-button @click="getAll()" class="dalfBut">查询</el-button>
<el-button type="primary" class="butT" @click="handleCreate()">新建</el-button>
</div>
<el-table size="small" current-row-key="id" :data="dataList" stripe highlight-current-row>
<el-table-column type="index" align="center" label="序号"></el-table-column>
<el-table-column prop="type" label="图书类别" align="center"></el-table-column>
<el-table-column prop="name" label="图书名称" align="center"></el-table-column>
<el-table-column prop="description" label="描述" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button>
<el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 新增标签弹层 -->
<div class="add-form">
<el-dialog title="新增图书" :visible.sync="dialogFormVisible">
<el-form ref="dataAddForm" :model="formData" :rules="rules" label-position="right"
label-width="100px">
<el-row>
<el-col :span="12">
<el-form-item label="图书类别" prop="type">
<el-input v-model="formData.type"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="图书名称" prop="name">
<el-input v-model="formData.name"/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="描述">
<el-input v-model="formData.description" type="textarea"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="handleAdd()">确定</el-button>
</div>
</el-dialog>
</div>
<!-- 编辑标签弹层 -->
<div class="add-form">
<el-dialog title="编辑检查项" :visible.sync="dialogFormVisible4Edit">
<el-form ref="dataEditForm" :model="formData" :rules="rules" label-position="right"
label-width="100px">
<el-row>
<el-col :span="12">
<el-form-item label="图书类别" prop="type">
<el-input v-model="formData.type"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="图书名称" prop="name">
<el-input v-model="formData.name"/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="描述">
<el-input v-model="formData.description" type="textarea"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible4Edit = false">取消</el-button>
<el-button type="primary" @click="handleEdit()">确定</el-button>
</div>
</el-dialog>
</div>
</div>
</div>
</div>
</body>
<!-- 引入组件库 -->
<script src="../js/vue.js"></script>
<script src="../plugins/elementui/index.js"></script>
<script type="text/javascript" src="../js/jquery.min.js"></script>
<script src="../js/axios-0.18.0.js"></script>
<script>
/*
* TODO: Vue就两部分内容
* 1. 视图 : html(界面)
* 1). 不用脚手架 <body>
2). 脚手架 <template>
* 2. 脚本 : js(data数据,methods交互)
* <script>
* TODO: Vue的理念
* 1). 数据绑定 (通用)
* 视图绑定脚本中的data数据 -> data数据改变,视图会随之改变
* 2). 双向数据绑定 (表单 : v-model)
* data数据改变,视图会随之改变
* 视图改变,data数据也会随之改变
* TODO: 交互部分,是不需要关注视图,关注data数据
* 发送请求,获取数据,设置到data中
*
* 视图 <- data <- 交互
* */
var vue = new Vue({
el: '#app',
data: {
pagination: {},
dataList: [],//当前页要展示的列表数据
formData: {},//表单数据
dialogFormVisible: false,//控制表单是否可见
dialogFormVisible4Edit: false,//编辑表单是否可见
rules: {//校验规则
type: [{required: true, message: '图书类别为必填项', trigger: 'blur'}],
name: [{required: true, message: '图书名称为必填项', trigger: 'blur'}]
},
url: "/book"
},
//钩子函数,VUE对象初始化完成后自动执行
created() {
this.getAll();
},
methods: {
//列表 TODO:
getAll() {
//查询 : 发起一个查询请求,接收数据,设置给dataList
axios.get(this.url).then(response => {
console.log(response.data);
if (response.data.code == 20041) {
this.dataList = response.data.data
} else {
this.$message.error(response.data.msg);
}
})
},
//弹出添加窗口
handleCreate() {
this.dialogFormVisible = true;
this.resetForm();
},
//重置表单
resetForm() {
this.formData = {};
},
//添加 TODO:
handleAdd() {
//发送ajax请求
axios.post(this.url, this.formData).then((res) => {
console.log(res.data);
//如果操作成功,关闭弹层,显示数据
if (res.data.code == 20011) {
this.dialogFormVisible = false;
this.$message.success("添加成功");
} else if (res.data.code == 20010) {
this.$message.error("添加失败");
} else {
this.$message.error(res.data.msg);
}
}).finally(() => {
this.getAll();
});
},
//弹出编辑窗口
handleUpdate(row) {
this.formData = row
this.dialogFormVisible4Edit = true;
},
//编辑 TODO:
handleEdit() {
//发送ajax请求
axios.put(this.url, this.formData).then((res) => {
//如果操作成功,关闭弹层,显示数据
if (res.data.code == 20031) {
this.dialogFormVisible4Edit = false;
this.$message.success("修改成功");
} else if (res.data.code == 20030) {
this.$message.error("修改失败");
} else {
this.$message.error(res.data.msg);
}
}).finally(() => {
this.getAll();
});
},
// 删除
handleDelete(row) {
//1.弹出提示框
this.$confirm("此操作永久删除当前数据,是否继续?", "提示", {
type: 'info'
}).then(() => {
//2.做删除业务TODO:
//2.做删除业务
axios.delete(this.url + "/" + row.id).then((res) => {
if (res.data.code == 20021) {
this.$message.success("删除成功");
} else {
this.$message.error("删除失败");
}
}).finally(() => {
this.getAll();
});
}).catch(() => {
//3.取消删除
this.$message.info("取消删除操作");
});
}
}
})
</script>
</html>
标签:code,拦截器,return,SpringMVC,day02,book,Integer,public
From: https://www.cnblogs.com/-turing/p/17206367.html