赞
踩
REST(Representational State Transfer),表现形式状态转换
传统风格资源描述形式
http://localhost:8080/user/getById?id=1
http://localhost:8080/user/saveUser
REST风格描述形式
http://localhost:8080/user/1
http://localhost:8080/user
优点
隐藏资源访问行为,无法通过地址得知对资源是何种操作
书写简化
按照REST风格访问资源时使用行为动作区分对资源进行了何种操作
http://localhost/users 查询全部用户信息 GET(查询)
http://localhost/users/1 查询指定用户信息 GET(查询)
http://localhost/users 添加用户信息 POST(新增/保存)
http://localhost/users 修改用户信息 PUT(修改/更新)
http://localhost/users/1 删除用户信息 DELETE(删除)
步骤:
1.设定http请求动作(动词)
@RequestMapping(value = “/users”,method = RequestMethod.POST)
2.设定请求参数(路径变量)
@RequestMapping(value = “/users/{id}”,method = RequestMethod.DELETE)
public String delete(@PathVariable Integer id)
使用的注解:
@RequestMapping:设置当前控制器方法请求访问路径
属性:value(默认):请求访问路径
method:http请求动作,标准动作(GET/POST/PUT/DELETE)
@PathVariable:绑定路径参数与处理器方法形参间的关系,要求路径参数名与形参名一一对应
参数接受注解对比
@RequestBody、@RequestParam、@PathVariable
UserController类(目前的开发方式)
package com.example.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class UserController { @RequestMapping("/save") @ResponseBody public String save(){ System.out.println("user save..."); return "{'module':'user save'}"; } @RequestMapping("/delete") @ResponseBody public String delete(){ System.out.println("user delete..."); return "{'module':'user delete'}"; } @RequestMapping("/update") @ResponseBody public String update(){ System.out.println("user update..."); return "{'module':'user update'}"; } @RequestMapping("/getById") @ResponseBody public String getById(){ System.out.println("user getById..."); return "{'module':'user getById'}"; } @RequestMapping("/getAll") @ResponseBody public String getAll(){ System.out.println("user getAll..."); return "{'module':'user getAll'}"; } }
REST风格
package com.example.controller; import com.example.domain.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @Controller public class UserController { @RequestMapping(value = "/users",method = RequestMethod.POST) @ResponseBody public String save(){ System.out.println("user save..."); return "{'module':'user save'}"; } @RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE) @ResponseBody public String delete(@PathVariable Integer id){ System.out.println("user delete..."+id); return "{'module':'user delete'}"; } @RequestMapping(value = "/users",method = RequestMethod.PUT) @ResponseBody public String update(@RequestBody User user){ System.out.println("user update..." + user); return "{'module':'user update'}"; } @RequestMapping(value = "/users/{id}",method = RequestMethod.GET) @ResponseBody public String getById(@PathVariable Integer id){ System.out.println("user getById..." + id); return "{'module':'user getById'}"; } @RequestMapping(value = "/users",method = RequestMethod.GET) @ResponseBody public String getAll(){ System.out.println("user getAll..."); return "{'module':'user getAll'}"; } }
@RestController:设置当前控制器类为RESTful风格,等同于@Controller与@ResponseBody两个注解组合功能
@PostMapping、@DeleteMapping、@PutMapping、@GetMapping:设置当前控制器方法请求访问路径与请求动作,每种对应一个请求动作
快速开发
package com.example.controller; import com.example.domain.User; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/users") public class UserController { @PostMapping public String save(){ System.out.println("user save..."); return "{'module':'user save'}"; } @DeleteMapping("/{id}") public String delete(@PathVariable Integer id){ System.out.println("user delete..."+id); return "{'module':'user delete'}"; } @PutMapping public String update(@RequestBody User user){ System.out.println("user update..." + user); return "{'module':'user update'}"; } @GetMapping ("/{id}") public String getById(@PathVariable Integer id){ System.out.println("user getById..." + id); return "{'module':'user getById'}"; } @GetMapping public String getAll(){ System.out.println("user getAll..."); return "{'module':'user getAll'}"; } }
配置SpringMvcConfig和ServletContainersInitConfig
① 添加Book类
package com.example.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; } }
② BookController类
package com.example.controller; import com.example.domain.Book; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; import java.util.List; @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<Book> getAll(){ List<Book> bookList = new ArrayList<>(); Book book1 = new Book(); book1.setType("计算机"); book1.setName("SpringMVC入门教程"); book1.setDescription("小试牛刀"); Book book2 = new Book(); book2.setType("计算机"); book2.setName("SpringMVC实战教程"); book2.setDescription("一代宗师"); bookList.add(book1); bookList.add(book2); return bookList; } }
③ 测试:
发送Post请求用于测试保存图书接口
http://localhost:8080/books
发送的json数据
{
"type":"计算机",
"name":"SPringMVC终极开发",
"description":"这是一本好书"
}
发送Get请求用于测试查询所有图书接口
http://localhost:8080/books
将REST功能页面导入webapp中(链接:https://pan.baidu.com/s/1Eb0Dv1Z3Iaxa5zxAQkZUGg 提取码:nxve)
① 创建SpringMvcSupport(放行非SpringMvc的请求)
package com.example.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) { //当访问/page/???时候,走/pages目录下的内容 registry.addResourceHandler("/pages/**").addResourceLocations("/pages/"); registry.addResourceHandler("/js/**").addResourceLocations("/js/"); registry.addResourceHandler("/css/**").addResourceLocations("/css/"); registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/"); } }
② SpringMvcConfig中添加扫描路径
package com.example.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan({"com.example.controller","com.example.config"})
@EnableWebMvc
public class SpringMvcConfig {
}
访问:http://localhost:8080/pages/books.html
③ 前端页面通过异步提交访问后台控制器
books.html中
//添加
saveBook () {
axios.post("/books",this.formData).then((res)=>{
});
},
//主页列表查询
getAll() {
axios.get("/books").then((res)=>{
this.dataList = res.data;
});
},
③ 重启容器,访问:http://localhost:8080/pages/books.html
点击新建按钮,然后输入一些输入,在确认,查看idea是否接收到保存数据
SSM整合流程
1.新建工程
2.添加依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.10.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.10.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.2.10.RELEASE</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency>
3.创建目录,SSM整合配置
com.example下创建config、controller、dao、domain、service.impl目录
环境准备:
SpringConfig核心配置
package com.example.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
@Configuration
@ComponentScan({"com.example.service"})
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
public class SpringConfig {
}
resources下创建jdbc.properties(根据自己的mysql数据库更改)
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.1.224:3306/ssm_db?useSSL=false
jdbc.username=root
jdbc.password=123456
JdbcConfig配置类
package com.example.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import javax.sql.DataSource; 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; } }
MybatisConfig配置类
package com.example.config; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.context.annotation.Bean; import javax.sql.DataSource; public class MybatisConfig { @Bean public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){ SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); factoryBean.setTypeAliasesPackage("com.example.domain"); return factoryBean; } @Bean public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer msc = new MapperScannerConfigurer(); msc.setBasePackage("com.example.dao"); return msc; } }
SpringMvcConfig配置类
package com.example.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan({"com.example.controller"})
@EnableWebMvc
public class SpringMvcConfig {
}
ServletConfig
package com.example.config; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; import javax.servlet.Filter; 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}; } }
3.功能模块
mysql建表
CREATE DATABASE ssm_db; USE ssm_db; -- ---------------------------- -- Table structure for tbl_book -- ---------------------------- DROP TABLE IF EXISTS `tbl_book`; CREATE TABLE `tbl_book` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `type` VARCHAR(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `name` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `description` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = INNODB AUTO_INCREMENT = 13 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of tbl_book -- ---------------------------- INSERT INTO `tbl_book` VALUES (1, '计算机理论', 'Spring实战 第5版', 'Spring入门经典教程,深入理解Spring原理技术内幕'); INSERT INTO `tbl_book` VALUES (2, '计算机理论', 'Spring 5核心原理与30个类手写实战', '十年沉淀之作,手写Spring精华思想'); INSERT INTO `tbl_book` VALUES (3, '计算机理论', 'Spring 5 设计模式', '深入Spring源码剖析Spring源码中蕴含的10大设计模式'); INSERT INTO `tbl_book` VALUES (4, '计算机理论', 'Spring MVC+MyBatis开发从入门到项目实战', '全方位解析面向Web应用的轻量级框架,带你成为Spring MVC开发高手'); INSERT INTO `tbl_book` VALUES (5, '计算机理论', '轻量级Java Web企业应用实战', '源码级剖析Spring框架,适合已掌握Java基础的读者'); INSERT INTO `tbl_book` VALUES (6, '计算机理论', 'Java核心技术 卷I 基础知识(原书第11版)', 'Core Java 第11版,Jolt大奖获奖作品,针对Java SE9、10、11全面更新'); INSERT INTO `tbl_book` VALUES (7, '计算机理论', '深入理解Java虚拟机', '5个维度全面剖析JVM,大厂面试知识点全覆盖'); INSERT INTO `tbl_book` VALUES (8, '计算机理论', 'Java编程思想(第4版)', 'Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉'); INSERT INTO `tbl_book` VALUES (9, '计算机理论', '零基础学Java(全彩版)', '零基础自学编程的入门图书,由浅入深,详解Java语言的编程思想和核心技术'); INSERT INTO `tbl_book` VALUES (10, '市场营销', '直播就该这么做:主播高效沟通实战指南', '李子柒、李佳琦、薇娅成长为网红的秘密都在书中'); INSERT INTO `tbl_book` VALUES (11, '市场营销', '直播销讲实战一本通', '和秋叶一起学系列网络营销书籍'); INSERT INTO `tbl_book` VALUES (12, '市场营销', '直播带货:淘宝、天猫直播从新手到高手', '一本教你如何玩转直播的书,10堂课轻松实现带货月入3W+');
BookDao
package com.example.dao; import com.example.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); @Update("update tbl_book set type=#{type},name=#{name},description=#{description} where id = #{id}") public void update(Book book); @Delete("delete from 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<Book> getAll(); }
Book
package com.example.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; } }
BookService
package com.example.service; import com.example.domain.Book; import java.util.List; public interface BookService { /* * 保存 * */ public boolean save(Book book); /* * 修改 * */ public boolean update(Book book); /* * 根据id删除 * */ public boolean delete(Integer id); /* * 根据id查询 * */ public Book getById(Integer id); /* * 查询全部 * */ public List<Book> getAll(); }
BookServiceImpl
package com.example.service.impl; import com.example.dao.BookDao; import com.example.domain.Book; import com.example.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; @Override public boolean save(Book book) { bookDao.save(book); return true; } @Override public boolean update(Book book) { bookDao.update(book); return true; } @Override public boolean delete(Integer id) { bookDao.delete(id); return true; } @Override public Book getById(Integer id) { return bookDao.getById(id); } @Override public List<Book> getAll() { return bookDao.getAll(); } }
BookController
package com.example.controller; import com.example.domain.Book; import com.example.service.BookService; import org.apache.ibatis.annotations.Delete; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @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) { return bookService.getById(id); } @GetMapping public List<Book> getAll() { return bookService.getAll(); } }
4.接口测试
package com.example.service; import com.example.config.SpringConfig; import com.example.domain.Book; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.List; @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<Book> list = bookService.getAll(); System.out.println(list); } }
采用Postman发送请求:
① 保存图书,发送post请求
http://localhost:8080/books
{
"type":"计算机",
"name":"SPringMVC终极开发",
"description":"这是一本好书"
}
在mysql中查看
② 修改图书,发送put请求
http://localhost:8080/books
{
"id":13,
"type":"计算机",
"name":"SPringMVC终极开发666",
"description":"这是一本好书"
}
在mysql中查看
③ 删除图书,发送delete请求
http://localhost:8080/books/13
查看mysql
④ 查询单个图书,发送get请求
http://localhost:8080/books/1
查看页面(Postman中的Pretty)
⑤ 查看所有图书,发送get请求
http://localhost:8080/books
查看页面(Postman中的Pretty)
5.添加事务管理
① 在SpringConfig中添加注解@EnableTransactionManagement
② JdbcConfig中添加事务管理
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager ds = new DataSourceTransactionManager();
ds.setDataSource(dataSource);
return ds;
}
③ BookService接口中添加注解@Transactional
设置统一数据返回结果类
public class Result{
private Object data;
private Integer code;
private String msg;
}
注意事项:
Result类中的字段并不是固定的,可以根据需要自行增减
提供若干构造方法,方便操作
实现
设置统一数据返回类Result
package com.example.controller; 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; } }
设置统一数据返回结果码
package com.example.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 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;
}
根据情况设计合理的Result
修改BookController
package com.example.controller; import com.example.domain.Book; import com.example.service.BookService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @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); } }
用Postman工具测试各接口
程序开发过程中不可避免的会遇到异常现象
异常的种类及出现异常的原因:
1.框架内部抛出的异常:因使用不合规导致
2.数据层抛出的异常:因外部服务器故障导致(例如:服务器访问超时)
3.业务层抛出的异常:因业务逻辑书写错误导致(例如:遍历业务书写操作,导致索引异常等)
4.表现层抛出的异常:因数据收集、校验等规则导致(例如:不匹配的数据类型间导致异常)
5.工具类抛出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)
各个层级均出现异常,异常处理代码书写在哪一层——所有异常均抛出到表现层进行处理
表现层处理异常,每个方法中单独书写,代码书写量巨大且意义不强,如何解决——AOP思想
用到的注解:
@RestControllerAdvice:为Rest风格开发的控制器类做增强
@ExceptionHandler:设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原始控制器执行,并转入当前方法执行
异常处理器:集中的、统一的处理项目中出现的异常
创建异常处理器ProjectExceptionAdvice
package com.example.controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(Exception.class)
public Result doException(Exception ex){
return new Result(666,null,"出现异常");
}
}
项目异常分类
项目异常处理方案
实验
① 自定义项目系统级异常
package com.example.exception; public class SystemException extends RuntimeException{ private Integer 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 Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } }
② 自定义项目业务级异常
package com.example.exception; public class BusinessException extends RuntimeException{ private Integer 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 Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } }
③ 自动以哦异常编码(持续补充)
public static final Integer SYSTEM_ERR = 50001;
public static final Integer SYSTEM_TIMEOUT_ERR = 50002;
public static final Integer BUSSINESS_ERR = 60002;
public static final Integer SYSTEM_UNKNOW_ERR = 5999;
④ 模拟异常
修改BookServiceImpl
@Override
public Book getById(Integer id) {
if(id == 1){
throw new BusinessException(Code.BUSSINESS_ERR,"请不要使用你的技术,挑战我的耐性!");
}
//将可能出现的异常进行包装,转换成自定义异常
try{
int i = 1 / 0;
}catch(ArithmeticException e){
throw new SystemException(Code.SYSTEM_TIMEOUT_ERR,"服务器请求超时,请重试",e);
}
return bookDao.getById(id);
}
⑤ 拦截并处理异常
package com.example.controller; import com.example.exception.BusinessException; import com.example.exception.SystemException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice public class ProjectExceptionAdvice { @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()); } @ExceptionHandler(Exception.class) public Result doException(Exception ex){ //记录日志 //发送消息给运维 //发送邮件给开发人员,ex对象发送给开发人员 return new Result(Code.SYSTEM_UNKNOW_ERR,null,"系统繁忙,请稍后再试"); } }
⑥ 测试异常
发送get请求:http://localhost:8080/books/1
发送get请求:http://localhost:8080/books/2
在webapp包下导入SSM功能页面(链接:https://pan.baidu.com/s/15RVS1UO-l3BYcBPMOoGdaQ 提取码:4tn9)
添加配置(放行非SpringMvc的请求)
SpringMvcSupport
package com.example.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) { registry.addResourceHandler("/pages/**").addResourceLocations("/pages/"); registry.addResourceHandler("/css/**").addResourceLocations("/css/"); registry.addResourceHandler("/js/**").addResourceLocations("/js/"); registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/"); } }
SpringMvcConfig
package com.example.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan({"com.example.controller","com.example.config"})
@EnableWebMvc
public class SpringMvcConfig {
}
1.列表功能
在books.html中个修改
//列表
getAll() {
//发送ajax请求
axios.get("/books").then((res)=>{
this.dataList = res.data.data;
});
},
2.添加功能
BookDao返回影响行数
package com.example.dao; import com.example.domain.Book; import org.apache.ibatis.annotations.*; import java.util.List; public interface BookDao { @Insert("insert into tbl_book values(null,#{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 * from tbl_book where id = #{id}") public Book getById(Integer id); @Select("select * from tbl_book") public List<Book> getAll(); }
BookServiceImpl返回是否正确添加删除更新
package com.example.service.impl; import com.example.controller.Code; import com.example.dao.BookDao; import com.example.domain.Book; import com.example.exception.BusinessException; import com.example.exception.SystemException; import com.example.service.BookService; import org.omg.CORBA.CODESET_INCOMPATIBLE; 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; @Override public boolean save(Book book) { return bookDao.save(book) > 0; } @Override public boolean update(Book book) { return bookDao.update(book) > 0; } @Override public boolean delete(Integer id) { return bookDao.delete(id) > 0; } @Override public Book getById(Integer id) { return bookDao.getById(id); } @Override public List<Book> getAll() { return bookDao.getAll(); } }
在books.html中增添添加功能
//弹出添加窗口 handleCreate() { this.dialogFormVisible = true; this.resetForm(); }, //重置表单 resetForm() { this.formData = {} }, //添加 handleAdd () { //发送ajax请求 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(); }); },
3.修改功能
在books.html中增添修改功能
//弹出编辑窗口 handleUpdate(row) { // console.log(row); //row.id 查询条件 axios.get("/books/"+row.id).then((res)=>{ if(res.data.code == 20041){ //查询数据,根据id查询 this.formData = res.data.data; //展示弹层,加载数据 this.dialogFormVisible4Edit = true; }else{ this.$message.error(res.data.msg); } }); }, //编辑 handleEdit() { //发送ajax请求 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); } }).finally(()=>{ this.getAll(); }); },
4.删除功能
在books.html中增添删除功能
// 删除 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("取消删除操作"); }) }
拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行
作用:
在指定的方法调用前后执行预先设定的代码
阻止原始方法执行
拦截器与过滤器区别
归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强
1.制作拦截器功能类
2.配置拦截器的执行位置
① 声明拦截器的bean,并实现HandlerInterceptor接口(注意:扫描加载bean)
package com.example.controller.interceptor; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @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..."); } }
② 定义配置类,继承WebMvcConfigurationSupport,实现addInterceptors方法(注意:扫描加载配置)
package com.example.config; import com.example.controller.interceptor.ProjectInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; @Configuration public class SpringMvcSupport extends WebMvcConfigurationSupport { @Autowired private ProjectInterceptor projectInterceptor; @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/"); } @Override protected void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*"); } }
也可以使用简化配置
使用标准接口WebMvcConfigurer简化开发(注意:侵入式较强)
package com.example.config; import com.example.controller.interceptor.ProjectInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @ComponentScan({"com.example.controller","com.example.config"}) @EnableWebMvc public class SpringMvcConfig implements WebMvcConfigurer { @Autowired private ProjectInterceptor projectInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*"); } }标准接口
前置处理(preHandle)
参数
返回值
后置处理(postHandle)
参数
完成后处理(afterCompletion)
参数
多拦截器执行顺序
当配置多个拦截器时,形成拦截器链
拦截器链的运行顺序参照拦截器添加顺序为准
当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
当拦截器运行中断,进运行配置在前面的afterCompletion操作
拦截器链运行顺序
preHandle:与配置顺序想用,必定运行
postHandle:与配置顺序相反,可能不运行
afterCompletion:与配置顺序相反,可能不运行
实验
在创建一个拦截器
package com.example.controller.interceptor; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Component public class ProjectInterceptor2 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle222..."); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle222..."); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion222..."); } }
添加多个拦截器
package com.example.config; import com.example.controller.interceptor.ProjectInterceptor; import com.example.controller.interceptor.ProjectInterceptor2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; @Configuration public class SpringMvcSupport extends WebMvcConfigurationSupport { @Autowired private ProjectInterceptor projectInterceptor; @Autowired private ProjectInterceptor2 projectInterceptor2; @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/"); } @Override protected void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*"); registry.addInterceptor(projectInterceptor2).addPathPatterns("/books","/books/*"); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。