restfurl:描述性状态转移。用来做接口。
通过url来定义资源,通过method(get、post、put、delete)来描述动作。
涉及到的两个注解
@RestController(不常用),定义接口,表示本类中所有的方法都是异步,不用写ResponseBody,不用写ResponseEntity
@PathValiable:注解处理器方法的形参,用来获取url中变量值。
注意点:在put与delete请求中,请求参数如果是key=value&key=value,后端收不到数据?
tomcat默认只对get和post请求的key=value&key=value解析,保存内部的map,我们可以通过getParameter来获取数据。
解决方法:在web.xml配置过滤器FormContentFilter,对put和delete请求支持。
@Controller @RequestMapping("rest") public class RestUrlHandler { @GetMapping("{sid}") // 查询 http://localhost:8080/0803/rest/12 @ResponseBody public ResponseBean getStuById(@PathVariable("sid") String sid){ SysStudent stu = new SysStudent(); stu.setSid(sid); stu.setSname("千珏"); stu.setSpass("1234"); return new ResponseBean(StatusEnum.SUCCESS,stu); } @PostMapping // 新增 http://localhost:8080/0803/rest public ResponseEntity addStu(@RequestBody SysStudent sysStudent){ System.out.println(sysStudent); return ResponseEntity.ok(new StatusBean(StatusEnum.SUCCESS)); } @PutMapping // 修改 http://localhost:8080/0803/rest public ResponseEntity editStu(@RequestBody SysStudent sysStudent){ System.out.println(sysStudent); return ResponseEntity.ok(new StatusBean(StatusEnum.SUCCESS)); } @DeleteMapping("{sid}") // 删除 http://localhost:8080/0803/rest/12 public ResponseEntity deleteStuById(@PathVariable("sid") String sid){ System.out.println(sid); return ResponseEntity.ok(new StatusBean(StatusEnum.SUCCESS)); } }局部异常处理:对某个处理器类中的异常处理。通过@ExceptionHandler注解
@ExceptionHandler可以转页面,可以返回json数据。缺点:只能对一个类中的异常生效。 @Controller @RequestMapping("exception") public class ExceptionTestHandler { @ExceptionHandler(Exception.class) @ResponseBody public Map<String,Object> doException(Exception e){ Map<String,Object> map = new HashMap<>(); map.put("time",System.currentTimeMillis()); map.put("info",e.getMessage()); return map; } @DeleteMapping("{sid}") // 删除 public ResponseEntity deleteStuById(@PathVariable("sid") Integer sid){ // int i = 1/0; // 算术异常 if (sid == 12){ throw new RuntimeException(StatusEnum.ERROR.getMsg()); } System.out.println(sid); return ResponseEntity.ok(new StatusBean(StatusEnum.SUCCESS)); } }全局异常处理:对所有的处理器类中的异常处理。实现HandlerExceptionResolver接口。
针对的同步请求,返回错误页面,可以自定义错误信息。
缺点:对于前后端分离项目,不能返回数据。
@Component public class GlobExceptionHandler implements HandlerExceptionResolver { //返回ModelAndView对象.处理同步请求。 @Override public ModelAndView resolveException(HttpServletRequest req, HttpServletResponse resp, Object o, Exception e) { ModelAndView mv = new ModelAndView(); mv.setViewName("error"); mv.addObject("time",System.currentTimeMillis()); mv.addObject("info",e.getMessage()); HandlerMethod hm = (HandlerMethod) o; Method method = hm.getMethod(); String name = method.getDeclaringClass().getName(); mv.addObject("clzName",name); return mv; } }全局统一异常处理:通过@ControllerAdvice与@ExceptionHandler两者结合。
一个状态枚举类,两个响应实体类(StatusBean,ResponseBean)
正常返回,返回ResponseBean
异常情况,返回StatusBean,全部进入一个统一的全局异常处理类。
@Component // 注入容器 @ControllerAdvice // controller增强注解。做异常的统一处理。 public class GlobExceptionHandler2 { @ExceptionHandler(Exception.class) public ResponseEntity doException(Exception e){ return ResponseEntity.ok(new StatusBean(StatusEnum.OPS_ERROR)); } @ExceptionHandler(MyException.class) public ResponseEntity doException(MyException e){ return ResponseEntity.ok(new StatusBean(e.getStatusEnum())); } }SpringMVC对apache的commons-fileupload组件进行封装,避免了繁琐的request解析操作。
操作流程:
导入jar包:fileUpload、io配置bean <!-- id:必须是multipartResolver --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="50000000"></property><!-- 最大文件大小 --> <property name="maxInMemorySize" value="10000000"></property><!-- 临时文件域 --> <property name="defaultEncoding" value="UTF-8"></property><!-- 中文文件名 --> <property name="uploadTempDir" value="/upload/tmp"></property><!-- 临时文件存储路径 --> </bean> 在handler类中添加upload()方法,参数列表添加MultipartFile类型形参接收上传的文件。多文件上传,upload方法MultipartFile形参改为数组,或多个MultipartFile类型的形参。
@Controller @RequestMapping("file") public class FileHandler { // 文件上传 @PostMapping("upload") public ResponseEntity doUpload(MultipartFile file, HttpServletRequest req) throws IOException { if (file == null) { System.out.println("无文件"); return ResponseEntity.ok("无文件"); } InputStream inputStream = file.getInputStream(); // 大文件上传 byte[] bytes = file.getBytes();// 适合小文件,10M以下 String filename = file.getOriginalFilename(); // 文件真实名 long size = file.getSize();// 文件大小 // 上传文件至服务器 String realPath = req.getServletContext().getRealPath("/"); String savePath = "/upload/" + filename; System.out.println(realPath + savePath); File target = new File(realPath + savePath); FileUtils.writeByteArrayToFile(target, bytes); // 保存文件 // 把文件的保存路径返回给客户端 return ResponseEntity.ok(new ResponseBean(StatusEnum.SUCCESS, savePath)); // /upload/dui.png } //前端如何调用下载接口:<a href="/download?filepath=/upload/aaa.png"> <button click="location.href=/download?filepath=xxxxx"></button> @GetMapping("/download") public ResponseEntity doDownLoad(String filepath, HttpServletRequest req) throws IOException { System.out.println("文件下载!"); // /upload/dui.png String realPath = req.getServletContext().getRealPath(filepath); File file = new File(realPath); String name = file.getName(); byte[] bytes = FileUtils.readFileToByteArray(file); if (bytes != null) { //指定响应头,传字节数组 HttpHeaders headers = new HttpHeaders(); headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name, "UTF-8")); return new ResponseEntity(bytes, headers, HttpStatus.OK); } else { throw new NullPointerException(StatusEnum.ERROR.getMsg()); } } }interceptor拦截器,是控制层框架中的一个概念,与Filter概念一样。
url请求,处理器映射器找到一个处理器方法对象以及一系列的拦截器对象(preHandle,postHandle,afterCompletion)。在执行处理器方法的前,后,异常处执行拦截器对应的方法。
6.1 从HandlerInterceptor派生拦截器类。
6.2 配置拦截器(拦截范围,忽略范围)
<mvc:interceptors> <mvc:interceptor> <!--配置拦截路径--> <mvc:mapping path="/**"/> <!--忽略路径--> <mvc:exclude-mapping path="/user5/login"></mvc:exclude-mapping> <mvc:exclude-mapping path="/static/**"></mvc:exclude-mapping> <!--拦截器bean对象--> <bean class="com.javasm.sys.interceptor.LoginInterceptor"></bean> </mvc:interceptor> </mvc:interceptors> public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(); Object login_user = session.getAttribute("LOGIN_USER"); if(login_user!=null){ return true; }else{ //未登陆,要做什么. // 如果是同步请求,可以转登陆页面 // 如果是异步请求,则返回数据。 throw new MyException(StatusEnum.NO_LOGIN); } } // @Override // public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // //处理器方法执行完毕,并正常返回,执行这里 // System.out.println("后拦截"); // } // // @Override // public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // //处理器方法执行完毕,不论有没有异常,都执行最终拦截 // System.out.println("最终拦截"); // } }