《SpringMVC应用》
目录
一、异常处理
后台处理数据时,可能会发生各种异常,如空指针异常、算数异常、下标越界异常等等,而后端的异常并不是前端所关心的,因此当后端发生异常后,可全局监控统一给前端响应一个结果。
案例一
- com.hpr.common.GlobalControllerException
package com.hpr.common;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
//全局异常处理
@ControllerAdvice
public class GlobalControllerException {
@ExceptionHandler(Exception.class)
@ResponseBody
public Response<Object> exceptionHandler() {
return new Response<>(500, "服务器故障,请联系管理员或稍后刷新重试!");
}
}
- com.hpr.controller.TestController
...
public class TestController {
...
@GetMapping("/testException")
@ApiOperation("测试统一异常处理")
public Response<Object> testException() {
//模拟异常
int x = 3 / 0;
return new Response<>(200, "success");
}
}
- 启动测试
执行结果
二、文件上传下载
文件上传
- 桌面——>新建文本文档——>输入内容123456——>保存。
- com.hpr.controller.TestController
...
public class TestController {
...
@PostMapping("/fileUpload")
@ApiOperation("测试文件上传")
public Response<Object> fileUpload(@ApiParam("上传的文件") @RequestParam MultipartFile mf) {
if (mf == null) {
return new Response<>(400, "上传的文件不可为空!");
}
if (mf.getOriginalFilename() == null) {
return new Response<>(400, "文件名不可为空!");
}
//本地文件系统根目录创建
File rootDir = new File("./rootDir");
if (!rootDir.exists()) {
rootDir.mkdir();
}
//保存至服务器(注意!此处要用绝对路径)
File target = new File(rootDir.getAbsolutePath() + File.separator + mf.getOriginalFilename());
try {
mf.transferTo(target);
} catch (IOException e) {
e.printStackTrace();
}
return new Response<>(200, "success");
}
}
- 启动测试
执行结果
项目根目录下将出现上传后的文件。
文件下载
- com.hpr.controller.TestController
...
public class TestController {
...
@GetMapping("/fileDownload")
@ApiOperation("测试文件下载")
public void fileDownload(HttpServletResponse response) throws IOException {
File file = new File("./rootDir/新建文本文档.txt");
//设置编码格式(重要!)
response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(file.getName(), "utf-8"));
FileInputStream fis = new FileInputStream(file);
OutputStream os = response.getOutputStream();
byte[] b = new byte[1024];
int len = fis.read(b);
while (len > 0) {
os.write(b, 0, len);
len = fis.read(b);
}
fis.close();
os.flush();
os.close();
}
}
- 启动项目,浏览器访问http://localhost:8080/test/fileDownload进行下载。
执行结果
三、拦截器
拦截器是SpringMVC中强大的控件,在SpringMVC中有着相当重要的作用,一般如拦截用户的请求并进行相应的处理。比如权限验证,或者是来判断用户是否登陆,或者是像12306 那样子判断当前时间是否是购票时间。
拦截器与过滤器
拦截器和过滤器有着相似之处,二者都是AOP思想的体现,都能实现权限检查,日志记录等功能。
不同的是:
- 使用的范围不同,过滤器是Servlet规范当中定义的特殊的类,拦截器是Spring框架提供的一种特殊的类,前者只能用在web程序里,拦截器既可以用在web也可以用在Application中。
- 使用的资源不同,同其他的代码块一样,拦截器也是Spring的组件,因此他能使用Spring里的任何资源,通过IOC注入bean对象,service对象,事物管理等,但是Filter则不能。
- 拦截的深度不同,过滤器Filter只在Servlet前后起作用,而拦截器可以深入到方法的前后,异常抛出前后等,因此拦截器有更大的弹性,故而在Spring架构程序里优先使用拦截器。
权限校验
- com.hpr.controller.GlobalController
package com.hpr.controller;
import com.hpr.common.Response;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/global")
@Api(hidden = true)
public class GlobalController {
@RequestMapping("/validationFailed")
public Response<Object> validationFailed() {
return new Response<>(400, "请登录后操作!");
}
}
- com.hpr.common.AuthorizationInterceptor
package com.hpr.common;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 权限校验拦截器
*/
public class AuthorizationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//处理器处理前
//判断是否有校验令牌(一般为登录后响应给前端的校验字符串)
String token = request.getHeader("Authorization");
if (token == null || token.trim().equals("")) {
request.getRequestDispatcher("/global/validationFailed").forward(request, response);
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//处理器处理后
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//请求结束后
}
}
- com.hpr.config.GlobalConfig
package com.hpr.config;
import com.hpr.common.AuthorizationInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class GlobalConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
/*
* addInterceptor:添加拦截器
* addPathPatterns:需要拦截的路径
* excludePathPatterns:允许直接访问的路径(跳过拦截)
* */
registry.addInterceptor(new AuthorizationInterceptor())
.addPathPatterns("/**")
.excludePathPatterns(
//swagger-ui相关请求
"/doc.html",
"/swagger-resources/configuration/ui",
"/swagger-resources",
"/v2/api-docs",
//js、css资源请求
"/**/*.js", "/**/*.css",
//自定义路径
"/login",
"/global/validationFailed"
);
}
}
- 启动测试
执行结果
总结
重点
- 全局异常处理方式;
- 文件上传下载操作;
- 拦截器的使用。
难点
- 拦截器原理及逻辑代码书写。