目录
【REST风格】—— Representational State Transfer
【SpringMVC】
【REST风格】—— Representational State Transfer
【概述】
表现形式状态转换
【描述】
传统风格资源描述形式
- http://localhost/user/getById?id=1
- http://localhost/user/saveUser
REST风格描述形式
- http://localhost/user/1
- http://localhost/user
【优点】
- 隐藏资源的访问行为,无法通过地址得知对资源是何种操作
- 书写简化
【行为区分】
按照REST风格访问资源时使用行为动作区分对资源进行了何种操作
- http://localhost/users 查询全部用户信息 GET(查询)
- http://localhost/users/1 查询指定用户信息 GET(查询)
- http://localhost/users 添加用户信息 POST(新增/保存)
- http://localhost/users 修改用户信息 PUT(修改/更新)
- http://localhost/users/1 删除用户信息 DELETE(删除)
根据REST风格对资源进行访问称为RESTful
【注意】
- 上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范
- 描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如:users、books、accounts……
【使用】
1、设置http请求动作
@RequestMapping(value = "/users", method = RequestMethod.POST)
@ResponseBody
public String save(@RequestBody User user){
System.out.println("user save..." + user);
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、设置请求参数(路径变量)
@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】
- 名称:@RequestMapping
- 类型:方法注解
- 作用:设置当前控制器方法请求访问路径
- 属性:
- value(默认):请求访问路径
- method:http请求动作,标准动作(GET/POST/PUT/DELETE)
例:
@RequestMapping(value = "/users", method = RequestMethod.POST)
@ResponseBody
public String save(@RequestBody User user){
System.out.println("user save..." + user);
return "{'module':'user save'}";
}
【@PathVariable】
- 名称:@PathVariable
- 类型:形参注解
- 作用:绑定路径参数与处理器方法形参间的关系,要求路径参数名与形参名一一对应
例:
@RequestMapping(value = "/users/{id}" ,method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id){
System.out.println("user delete..." + id);
return "{'module':'user delete'}";
}
【注意】
@RequestBody、@RequestParam、@PathVariable的区别
- @RequestParam用于接收url地址传参或表单传参
- @RequestBody用于接收json数据
- @PathVariable用于接收路径参数,使用{参数名称}描述路径参数
应用
- 开发中,发送请求参数超过1个时,以json格式为主,@RequestBody应用较广
- 如果发送非json格式数据,选用@RequestParam接收请求参数
- 采用RESTful进行开发,当参数数量较少时,例如1个,可以采用@PathVariable接收请求路径变量,通常用于传递id值
【标准开发】
【@RestController】
- 名称:@RestController
- 类型:类注解
- 作用:设置当前控制器类为RESTful风格,等同于@Controller与@ResponseBody两个注解组合功能
例:
@RestController
public class BookController {
}
【@GetMapping、@PostMapping、@PutMapping、@DeleteMapping】
- 名称:@GetMapping @PostMapping @PutMapping @DeleteMapping
- 类型:方法注解
- 作用:设置当前控制器方法请求访问路径与请求动作,每种对应一个请求动作,例如@GetMapping对应GET请求
- 属性:value(默认):请求访问路径
@GetMapping("/{id}")
public String getById(@PathVariable Integer id){
System.out.println("book getById..."+id);
return "{'module':'book getById'}";
}
【SSM整合】
【整合流程】
1.创建工程
2.SSM整合
- Spring
- SpringConfig
- MyBatis
- MybatisConfig
- JdbcConfig
- jdbc.properties
- SpringMVC
- ServletConfig
- SpringMvcConfig
3.功能模块
- 表与实体类
- dao(接口+自动代理)
- service(接口+实现类)
- 业务层接口测试(整合JUnit)
- controller
- 表现层接口测试(PostMan)
【Spring整合MyBatis】
- 配置
- SpringConfig
- JDBCConfig、jdbc.properties
- MyBatisConfig
- 模型
- Book
- 数据层标准开发
- BookDao
- 业务层标准开发
- BookService
- BookServiceImpl
- 测试接口
- BookServiceTest
- 事务处理
【Spring整合SpringMVC】
- SpringMVC配置类
- 基于Restful的Controller开发
【表现层数据封装】
1、设置统一数据返回结果类
public class Result {
private Object data;
private Integer code;
private String msg;
}
【注意】
- Result类中的字段并不是固定的,可以根据需要自行增减
- 提供若干个构造方法,方便操作
2、设置统一数据返回结果编码
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类的常量设计也不是固定的,可以根据需要自行增减,例如将查询再进行细分为GET_OK,GET_ALL_OK,GET_PAGE_OK
3、根据情况设定合理的Result
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
@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);
}
}
【异常处理器】
出现异常现象的常见位置与常见原因:
- 框架内部抛出的异常:因使用不合规导致
- 数据层抛出的异常:因外部服务器故障导致(例如:服务器访问超时)
- 业务层抛出的异常:因业务逻辑书写错误导致(例如:遍历业务书写操作,导致索引异常等)
- 表现层抛出的异常:因数据收集、校验等规则导致(例如:不匹配的数据类型间导致异常)
- 工具类抛出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)
【注意】
- 所有的异常均抛出到表现层进行处理
- 表现层处理异常,使用AOP思想
【使用】
集中的、统一的处理项目中出现的异常
@RestControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(Exception.class)
public Result doException(Exception ex){
return new Result(666,null,"异常");
}
}
【@RestControllerAdvice】
- 名称:@RestControllerAdvice
- 类型:类注解
- 作用:为Rest风格开发的控制器类做增强
【注意】
此注解自带@ResponseBody注解与@Component注解,具备对应的功能
【@ExceptionHandler】
- 名称:@ExceptionHandler
- 类型:方法注解
- 作用:设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原始控制器执行,并转入当前方法执行
【注意】
此类方法可以根据处理的异常不同,制作多个方法分别处理对应的异常
【项目异常分类】
- 业务异常(BusinessException)
- 规范的用户行为产生的异常
- 不规范的用户行为操作产生的异常
- 系统异常(SystemException)
- 项目运行过程中可预计且无法避免的异常
- 其他异常(Exception)
- 编程人员未预期到的异常
【项目异常处理方案】
业务异常(BusinessException)
- 发送对应消息传递给用户,提醒规范操作
系统异常(SystemException)
- 发送固定消息传递给用户,安抚用户
- 发送特定消息给运维人员,提醒维护
- 记录日志
其他异常(Exception)
- 发送固定消息传递给用户,安抚用户
- 发送特定消息给编程人员,提醒维护(纳入预期范围内)
- 记录日志
【异常处理】
1、自定义项目系统级异常
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) {
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 SystemException(Integer code, Throwable cause) {
super(cause);
this.code = code;
}
public SystemException(Integer code, String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
this.code = code;
}
}
2、自定义项目业务级异常
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) {
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 BusinessException(Integer code, Throwable cause) {
super(cause);
this.code = code;
}
public BusinessException(Integer code, String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
this.code = code;
}
}
3、自定义异常编码
public class Code {
public static final Integer SYSTEM_ERR = 50001;
public static final Integer SYSTEM_TIMEOUT_ERR = 50001;
public static final Integer SYSTEM_UNKNOW_ERR=59999;
public static final Integer BUSINESS_ERR = 60002;
}
4、触发自定义异常
public Book getById(Integer id) {
if(id==1){
throw new BusinessException(Code.BUSINESS_ERR,"请勿进行非法操作");
}
try {
int i=1/0;
}catch (Exception ex){
throw new SystemException(Code.SYSTEM_TIMEOUT_ERR,"服务器访问超时,请稍后再试");
}
return bookDao.getById(id);
}
5、拦截并处理异常
@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) {
return new Result(Code.SYSTEM_UNKNOW_ERR, null, "系统异常,请稍后再试");
}
}
【拦截器】
【概述】
是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行
【作用】
- 在指定的方法调用前后执行预先设定的代码
- 阻止原始方法的执行
【拦截器与过滤器的区别】
- 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
- 拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强
【使用】
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 addInterceptors(InterceptorRegistry registry) {
}
}
3、添加拦截器并设定拦截的访问路径,路径可以通过可变参数设置多个
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Autowired
private ProjectInterceptor projectInterceptor;
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");
}
}
【可使用标准接口WebMvcConfigurer简化开发】(注意:侵入式较强)
@Configuration
@ComponentScan("com.itheima.controller")
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer{
@Autowired
private ProjectInterceptor projectInterceptor;
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(projectInterceptor).addPathPatterns("/books", "/books/*");
}
}
【执行流程】
【拦截器参数】
【前置处理】
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
【参数】
- request:请求对象
- response:响应对象
- handler:被调用的处理器对象,本质上是一个方法对象,对反射技术中的Method对象进行了再包装
【返回值】
返回值为false,被拦截的处理器将不执行
【后置处理】
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
【参数】
modelAndView:如果处理器执行完成具有返回结果,可以读取到对应数据与页面信息,并进行调整
【完成后处理】
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
【参数】
ex:如果处理器执行过程中出现异常对象,可以针对异常情况进行单独处理
【多拦截器执行顺序】
- 当配置多个拦截器时,形成拦截器链
- 拦截器链的运行顺序参照拦截器添加顺序为准
- 当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行
- 当拦截器运行中断,仅运行配置在前面的拦截器的afterCompletion操作
【注意】
与过滤器链执行类似