学习目标:
1.掌握基于SpringMVC获取请求参数与响应json数据操作
2.熟练应用基于REST风格的请求路径设置与参数传递
3.能够根据实际业务建立前后端开发通信协议并进行实现
4.基于SSM整合技术开发任意业务模块功能
目录
一、SpringMVC简介
1.1概述
1.2 SpringMVC入门案例
1.2.1 注解说明:
1.2.2 开发总结:
1.3 入门案例工作流程分析
1.4 Controller加载控制与业务bean加载控制
1.5 PostMan
二、请求与响应
2.1 请求映射路径
2.2 请求参数
2.2.1 普通参数
2.2.2 POJO参数
2.2.3 嵌套参数
2.2.4 数组参数
2.2.5 集合参数
2.2.6 json参数
2.3 日期类型参数传递
2.4 响应
三、REST风格
3.1 简介
3.2 入门案例
3.3 RESTful快速开发
3.4 案例:基于RESTful页面数据交互
四、SSM整合
4.1 整合流程
4.1.1创建工程
4.1.2 SSM整合
4.1.3 功能模块
4.1.4 接口测试
4.2 表现层数据封装
4.2.1前端接受数据格式
4.2.2 设置统一数据返回结果类
4.2.3设置统一数据返回结果编码
4.2.4根据情况设定合理的Result
4.3 异常处理
4.3.1 简介
4.3.2 项目异常分类
4.3.3 项目异常处理方案
4.3.4 项目异常处理步骤
4.4 页面
4.4.1 列表
4.4.2 增加
4.4.3 修改
4.4.4 删除
4.4.5 总结
五、拦截器
5.1 拦截器概念
5.2 入门案例
5.3执行流程
5.4 拦截器参数
5.5 拦截器工作流程分析
SpringMVC是一种基于java实现MVC模型的轻量级web框架
使用简单,开发快捷
1.导入SpringMVC坐标与Servlet坐标,tomcat7插件
javax.servlet javax.servlet-api 3.1.0 provided org.springframework spring-webmvc 5.2.10.RELEASE org.apache.tomcat.maven tomcat7-maven-plugin 2.1 80 /
2.创建SpringMVC控制类(等同于Servlet功能)
//定义表现层控制器bean
@Controller
public class UserController {
//设置映射路径为/save,即外部访问路径
@RequestMapping("/save")
//设置当前操作返回结果为指定json数据(本质上是一个字符串信息)
@ResponseBody
public String save(){
System.out.println("user save ...");
return "{'info':'springmvc'}";
}
}
3.初始化SpringMVC环境(同Spring环境),设定SpringMVC加载对应的bean
//springmvc配置类,本质上还是一个spring配置类
@Configuration
@ComponentScan("com.itheima.controller")
public class SpringMvcConfig {
}
4.初始化Servlet容器,加载SpringMVC环境,并设置SpirngMVC技术处理的请求5
//web容器配置类
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
//加载springmvc配置类,产生springmvc容器(本质还是spring容器)
protected WebApplicationContext createServletApplicationContext() {
//初始化WebApplicationContext对象
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
//加载指定配置类
ctx.register(SpringMvcConfig.class);
return ctx;
}
//设置由springmvc控制器处理的请求映射路径
protected String[] getServletMappings() {
return new String[]{"/"};
}
//加载spring配置类
protected WebApplicationContext createRootApplicationContext() {
return null;
}
}
一次性工作: | 多次工作: |
1.创建工程,设置服务器,加载工程 | 1.定义处理请求的控制器类 |
2.导入坐标 | |
3.创建web容器启动类,今安在SpringMVC配置,并设置SpringVC请求拦截路径 | 2.定义处理请求的控制器方法,并配置映射路径(@RequestMapping)与返回json数据(@ResponseBody) |
4.SpringMVC核心配置类(设置配置类,扫描controller包,加载Controller控制器bean) |
·AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类
·AbstractDispatcherServletInitializer提供三个接口方法供用户实现
1.createServletApplicationContext(),创建Servlet容器时,加载SpringMVC对应的bean并放入 WebApplicationContext对象范围中,而WebApplicationContext的作用范围为ServletContext范围,即整个web容器范围。
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
2.getServletMappings(),设定SpringMVC对应的请求映射路径,设置为/表示拦截所用请求,任意请求都将转入到SpringMVC进行处理。
protected String[] getServletMappings() {
return new String[]{"/"};
}
3.createRootApplicationContext(),如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,方式同createServletApplicationContext()。
protected WebApplicationContext createRootApplicationContext() {
return null;
}
//一下两种方式取其一
//@ComponentScan({"com.itheima.service","com.itheima.dao"})
@ComponentScan(value = "com.itheima",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
)
public class SpringConfig {
}
//第三种办法
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringConfig.class);
return ctx;
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
简化开发
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
protected Class>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
Get请求传参
Post请求传参
Post请求中文乱码处理
为web容器添加过滤器并指定字符集,Spring-web包中提供了专用的字符过滤器
@Override
protected Filter[] getServletFilters() {
//配字符编码过滤器
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("utf-8");
return new Filter[]{filter};
}
1. 导入坐标
com.fasterxml.jackson.core jackson-databind 2.9.0
2. 设置发送json数据(请求body中添加json数据)
3. 开启自动转换json数据支持
注:EnableWebMvc注解功能强大,该注解整合了多个功能,此处仅使用其中一部分功能,即json数据进行自动类型转换。
4.设置json接受数据
@RequestBody与@RequestParam区别
REST:Representational State Transfer,表现形式状态转换
优点:隐藏资源的访问行为,无法通过地址得知对资源是何种操作,书写简化
注意:上述行为是约定方式,约定不是规范,可以打破,所一称REST风格,而不是REST规范,描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源而非单个资源
1.设定http请求动作
@RequestMapping(value = "/users",method = RequestMethod.POST)
@ResponseBody
public String save(@RequsetBody User user){
System.out.println("user save...");
return "{'module':'user save'}";
}
@RequestMapping(value = "/users",method = RequestMethod.PUT)
@ResponseBody
public String update(@RequestBody User user){
System.out.println("user update..."+user);
return "{'module':'user update'}";
}
2.设定请求参数(路径变量)
//@Controller
//@ResponseBody配置在类上可以简化配置,表示设置当前每个方法的返回值都作为响应体
//@ResponseBody
@RestController //使用@RestController注解替换@Controller与@ResponseBody注解,简化书写
@RequestMapping("/books")
public class BookController {
// @RequestMapping( method = RequestMethod.POST)
@PostMapping //使用@PostMapping简化Post请求方法对应的映射配置
public String save(@RequestBody Book book){
System.out.println("book save..." + book);
return "{'module':'book save'}";
}
// @RequestMapping(value = "/{id}" ,method = RequestMethod.DELETE)
@DeleteMapping("/{id}") //使用@DeleteMapping简化DELETE请求方法对应的映射配置
public String delete(@PathVariable Integer id){
System.out.println("book delete..." + id);
return "{'module':'book delete'}";
}
// @RequestMapping(method = RequestMethod.PUT)
@PutMapping //使用@PutMapping简化Put请求方法对应的映射配置
public String update(@RequestBody Book book){
System.out.println("book update..."+book);
return "{'module':'book update'}";
}
// @RequestMapping(value = "/{id}" ,method = RequestMethod.GET)
@GetMapping("/{id}") //使用@GetMapping简化GET请求方法对应的映射配置
public String getById(@PathVariable Integer id){
System.out.println("book getById..."+id);
return "{'module':'book getById'}";
}
// @RequestMapping(method = RequestMethod.GET)
@GetMapping //使用@GetMapping简化GET请求方法对应的映射配置
public String getAll(){
System.out.println("book getAll...");
return "{'module':'book getAll'}";
}
}
1. 制作SpringMVC控制器,并通过PostMan测试接口功能
@RestController
@RequestMapping("/books")
public class BookController {
@PostMapping
public String save( @RequestBody Book book){
System.out.println("book save ==>"+book );
return "{’module':'book save success'}";
}
@GetMapping
public List getAll(){
ArrayList books = new ArrayList();
Book book1 = new Book();
book1.setType("计算机");
book1.setName("SpringMVC入门教程");
book1.setDescription("小试牛刀");
Book book2 = new Book();
book2.setType("计算机");
book2.setName("SpringMVC实战教程");
book2.setDescription("一代宗师");
books.add(book2);
books.add(book1);
return books;
}
}
2. 设置对静态资源的访问放行(在config目录下创建java)
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
//当访问pages/????时 走/pages目录下的内容
registry.addResourceHandler("pages/**").addResourceLocations("/pages/");
registry.addResourceHandler("js/**").addResourceLocations("/js/");
registry.addResourceHandler("css/**").addResourceLocations("/css/");
registry.addResourceHandler("plugins/**").addResourceLocations("/plugins/");
}
}
3.前端页面通过异步提交访问后台控制器(都建立在vue中)
saveBook () {
axios.post("/books",this.formData).then((res)=>{
});
},
//主页列表查询
getAll() {
axios.get("/books").then((res)=>{
this.dataList = res.data;
});
},
saveBook方法中 不光要写访问路径 还要写提交的内容 即this.formData,这个数据模型已经建立。
依赖导入
插件导入
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
80
/
包结构
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) {
DataSourceTransactionManager ds = new DataSourceTransactionManager();
ds.setDataSource(datasource);
return ds;
}
}
//
public class MyBatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setTypeAliasesPackage("com.itheima.domian");
return factoryBean;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setBasePackage("com.itheima.dao");
return msc;
}
}
//
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
@Override
protected Class>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
//乱码处理 如果有表单提交的需求就一定要加
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
return new Filter[] {filter};
}
}
//
@Configuration
@ComponentScan({"com.itheima.service"})
@PropertySource("jdbc.properties")
@Import({JdbcConfig.class,MyBatisConfig.class})
@EnableTransactionManagement
public class SpringConfig {
}
/
@Configuration
@ComponentScan("com.itheima.control")//这里记录一个错误,括号中应该输入的是包名而不是类名,一
//开始写的时候写成了类名,没注意导致spring No mapping
//这个错误
@EnableWebMvc
public class SpringMvcConfig {
}
在Dao、Service、Control 三层分别建立如下代码,实现功能(具体内容待写入!!!)
Dao
public interface BookDao {
//@Insert("insert into tbl_book values(null,#{type},#{name},#{description})")
@Insert("insert into tbl_book (type,name,description)values(#{type},#{name},#{description})")
public void save(Book book);
@Update("update tbl_book set type=#{type},name=#{name},description=#{description}where id=#{id}")
public void update(Book book);
@Delete("delete tbl_book where id = #{id}")
public void delete(Integer id);
@Select("select * from tbl_book where id = #{id}")
public Book getById(Integer id);
@Select("select * from tbl_book")
public List getAll();
}
Service
@Transactional
public interface BookService {
/**
*增加
* @param book
* @return
*/
public boolean save(Book book);
/**
*修改
* @param book
* @return
*/
public boolean update(Book book);
/**
* 删除
* @param id
* @return
*/
public boolean delete(Integer id);
/**
* 按id查找
* @param id
* @return
*/
public Book getById(Integer id);
/**
* 查询全部
* @return
*/
public List getAll();
}
///
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
public boolean save(Book book) {
bookDao.save(book);
return true;
}
public boolean update(Book book) {
bookDao.update(book);
return true;
}
public boolean delete(Integer id) {
bookDao.delete(id);
return true;
}
public Book getById(Integer id) {
Book book = bookDao.getById(id);
return book;
}
public List getAll() {
List all = bookDao.getAll();
return all;
}
}
Control
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
@PostMapping
public boolean save(@RequestBody Book book) {
return bookService.save(book);
}
@PutMapping
public boolean update(@RequestBody Book book) {
return bookService.update(book);
}
@DeleteMapping("/{id}")
public boolean delete(@PathVariable Integer id) {
return bookService.delete(id);
}
@GetMapping("/{id}")
public Book getById(@PathVariable Integer id) {
Book book = bookService.getById(id);
return book;
}
@GetMapping
public List getAll() {
List all = bookService.getAll();
return all;
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class BookServiceTest {
@Autowired
private BookService bookService;
@Test
public void testGetById(){
Book book = bookService.getById(1);
System.out.println(book);
}
@Test
public void testGetAll(){
List all = bookService.getAll();
System.out.println(all);
}
}
创建结果模型类,封装数据到data属性中
封装操作结果到code属性中
封装特殊消息到message(msg)属性中
建议将该类定义在control包下
注意:Result类中的字段并不是固定的,可以根据需要自行增键,提供若干个构造方法,方便操作
public class Result {
private Object data;
private Integer code;
private String msg;
public Result(Integer code, Object data, String msg) {
this.data = data;
this.code = code;
this.msg = msg;
}
public Result(Integer code, Object data) {
this.data = data;
this.code = code;
}
public Result() {
}
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;
}
}
public class Code {
public static final Integer SAVE_OK =20011;
public static final Integer DELETE_OK =20021;
public static final Integer UPDATE_OK =20031;
public static final Integer GET_OK =20041;
public static final Integer SAVE_ERR =20010;
public static final Integer DELETE_ERR =20020;
public static final Integer UPDATE_ERR=20030;
public static final Integer GET_ERR =20040;
}
注意Code类的常量设计不是固定的 ,可以根据需要自行增减
@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 bookList = bookService.getAll();
Integer code = bookList!=null? Code.GET_OK: Code.GET_ERR;
String msg = bookList!=null?"":"数据查询失败,请重试!";
return new Result(code,bookList,msg);
}
}
·程序开发过程中不可避免会遇到异常
·出现异常现象的常见位置与常见诱因如下:
所有的异常均抛到表现层进行处理 利用AOP思想简化代码
在Control包下创建该类,保证Spring配置文件可以扫描到该类
@RestControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(Exception.class)
public Result doException(Exception ex){
System.out.println("异常来了");
return new Result(666,null);
}
}
1.自定义项目系统异常、项目业务异常
这两个定义的类放在新建的exception包下
public class BusinessException extends RuntimeException{
private Integer code;
public Integer getCode() {
return 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 SystemException(Integer code, String message ) {
super(message);
this.code = code;
}
public SystemException(Integer code,String message, Throwable cause) {
super(message, cause);
this.code = code;
}
}
2.自定义异常编码
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;
}
3.出发自定义异常
在service层中,模拟(位于BookServiceImpl.class)
public Book getById(Integer id) {
if(id==1){
throw new BusinessException(Code.BUSINESS_ERR,"请不要用你的技术挑战我!");
}
//将可能出现的异常进行包装,转换成自定义异常
try {
int i = 1/0;
} catch (ArithmeticException e) {
throw new SystemException(Code.SYSTEM_TIMEOUT_ERR,"服务器访问超时,请重试!!!",e);
}
Book book = bookDao.getById(id);
return book;
}
4.拦截并处理异常
@RestControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(SystemException.class)
public Result doSystemException(SystemException 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());
}
@ExceptionHandler(Exception.class)
public Result doException(Exception ex){
//记录日志
//发送消息给运维
//发送邮件给开发人员
System.out.println("异常来了");
return new Result(Code.SYSTEM_UNKNOW_ERR,null,"系统繁忙请稍后重试");
}
}
5.异常处理器效果
首先导入显示页面的资源
之后设置拦截路径,保证加载页面不会被MVC所调用
@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/");
}
}
设置这个配置文件别忘记加@Configuration
在SpringMvcConfig 中添加查找路径
@Configuration
@ComponentScan({"com.itheima.control","com.itheima.config"})
@EnableWebMvc
public class SpringMvcConfig {
}
数据流已经产生,只需要在Vue中创建显示数据的方法即可
//钩子函数,VUE对象初始化完成后自动执行
created() {
this.getAll();
},
methods: {
//列表
getAll() {
//发送ajax请求
axios.get("/books").then((res)=>{
this.dataList = res.data.data;
});
},
注意这个钩子函数
为了让增删改得到消息是否成功会在DAO层修改其返回值为Int,从而得到数据库被修改的行数,在service层判断出是否成功
public interface BookDao {
//@Insert("insert into tbl_book values(null,#{type},#{name},#{description})")
@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 tbl_book where id = #{id}")
public int delete(Integer id);
}
********************************************************
public class BookServiceImpl implements BookService {
public boolean save(Book book) {
return bookDao.save(book) >0;
}
public boolean update(Book book) {
return bookDao.update(book)>0;
}
public boolean delete(Integer id) {
return bookDao.delete(id)>0;
}
.......}
点击新增会触发以下方法
新建
***************************************************
//弹出添加窗口
handleCreate() {
this.dialogFormVisible=true;
this.resetForm();
},
//重置表单
resetForm() {
this.formData = {};
},
重置表单是为了保证每次点击都会返回一个空白的表单
提交表单后会触发以下方法
确定
********************************************************************
//添加
handleAdd () {
axios.post("/books",this.formData).then((res)=>{
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();
});
},
如果产生异常 那么会返回一个Result,其中msg是异常信息。
最后不管成功与否都要调用getAll()
点击编辑会触发以下方法
编辑
***************************************************************************************
//弹出编辑窗口
handleUpdate(row) {
//查看日志,判断row是否传入
console.log(row);
//展示弹层
this.dialogFormVisible4Edit = true;
//根据id查询数据
axios.get("/books/"+row.id).then((res)=>{
if(res.data.code ==20041){
this.formData = res.data.data;
}else{
this.$message.error(res.data.msg);
}
});
},
提交表单会触发以下方法
确定
****************************************************************
//编辑
handleEdit() {
//上传数据
axios.put("/books",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);
}
});
},
点击删除触发方法
删除
******************************************************************
// 删除
handleDelete(row) {
//1.弹出提示框
this.$confirm("此操作永久删除提示数据","提示",{
type:'info'
}).then(()=>{
//2.做删除业务
axios.delete("/books/"+row.id).then((res)=>{
if(res.data.code == 20021 ){
this.$message.success("删除成功");
}else{
this.$message.error("删除失败");
}
});
}).finally(()=>{
this.getAll();
}).catch(()=>{
//3.取消删除
this.$message.info("取消删除");
});
}
1.声明拦截器的bean,并实现HandlerInterceptor接口(注意:扫描加载bean)
@Component
public class ProjectInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle....");
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......");
}
}
2.定义配置类,继承WebMvcConfigurationSupport,实现addInterceptor方法(注意:扫描加载配置)
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
.....
}
}
3.添加拦截器并设定拦截的访问路径,路径可以通过可变参数设置多个
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Autowired
private ProjectInterceptor projectInterceptor;
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
}
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");
}
}
4.使用标准接口WebMvcConfigurer简化开发(注意:侵入式较强)
@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
//实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
public class SpringMvcConfig implements WebMvcConfigurer {
@Autowired
private ProjectInterceptor projectInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");
}
}