消息转换器【HttpMessageConverter】
1 消息转换器简介
- HttpMessageConverter 是 Spring3.0 新添加的一个接口,负责将请求信息转换为一个对象(类型为 T),将对象(类型为 T)输出为响应信息。
- 作用:将Java对象与信息可以相互转换
- 注意:SpringMVC的配置文件中一定要配置mvc:annotation-driven标签。如果不配置将只装配4个转换器,如果配置mvc:annotation-driven标签,装配7个转换器
2 使用消息转换器
-
处理请求数据
-
使用@RequestBody定义在处理请求方法入参中
@RequestMapping("/testRequestBody") public String testRequestBody(@RequestBody String rbody/*String username,String password*/){ System.out.println("rbody = " + rbody); return SUCCESS; }
-
使用Entity定义在处理请求方法入参中
@RequestMapping("/testHttpEntity") public String testtestHttpEntity(HttpEntity<String> httpEntity){ HttpHeaders headers = httpEntity.getHeaders(); System.out.println("headers = " + headers); String body = httpEntity.getBody(); System.out.println("body = " + body); return SUCCESS; }
-
-
处理响应数据
-
使用@ResponseBody注解定义在方法上【或类上面】,使用响应流响应数据【response.getWriter().write()】
@ResponseBody @RequestMapping("/testResponseBody") public String testResponseBody(){ System.out.println("测试testResponseBody!!!"); return "sfdsfds"; }
-
-
使用ResponseEntity,定义在方法返回值位置,解决文件下载问题
<h3>测试【ResponseEntity】文件下载-0728资源库</h3> <a th:href="@{/testDownload(fileName='lss1.jpg')}">lss1.jpg</a><br> <a th:href="@{/testDownload(fileName='zqbb2.jpg')}">zqbb2.jpg</a><br> <a th:href="@{/testDownload(fileName='秘籍.txt')}">秘籍.txt</a><br>
/** * 处理文件下载 */ @RequestMapping(value = "/testDownload") public ResponseEntity<byte[]> fileDownload(String fileName, HttpServletRequest request)throws Exception{ System.out.println("fileName = " + fileName); //获取下载目标文件,真实路径 String realPath = request.getServletContext().getRealPath("/WEB-INF/dir/" + fileName); //创建输入流 InputStream is = new FileInputStream(realPath); //定义存储文件字节数组 byte[] bytes = new byte[is.available()]; //通过流,将文件字节读取bytes数组中 is.read(bytes); //响应头 //MultiValueMap<String,String> headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders(); //设置当前文件为附件【通知浏览器别打开,下载】 headers.add("Content-Disposition", "attachment;filename="+fileName); //处理文件中文名问题 headers.setContentDispositionFormData("attachment", new String(fileName.getBytes("utf-8"), "ISO-8859-1")); //响应码 HttpStatus ok = HttpStatus.OK; //创建ResponseEntity<byte[]> ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes,headers,ok); return responseEntity; }
SpringMVC中使用HttpMessageConverter处理Json数据
-
加载json相关jar包
<!-- jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.10.5.1</version> </dependency>
-
在springmvc.xml配置文件中,添加<mvc:annotation-driven>
<!-- 解决静态资源加载、view-controller后续问题等、解决Jackson消息转换器问题--> <mvc:annotation-driven></mvc:annotation-driven>
-
返回需要转换为json格式数据
@ResponseBody @RequestMapping("/testJsonData") public Employee testJsonData(){ Employee employee = new Employee(); employee.setId(1001); employee.setLastName("zq"); employee.setEmail("zq@163.com"); employee.setGender(1); return employee; }
mvc:annotation-driven主要作用
1 添加mvc:view-controller标签
-
添加上面标签,会导致未装配RequsetMappingHandlerAdapter适配器,从而导致RequestMapping失效。
所以,添加mvc:annotation-driven标签,会将RequsetMappingHandlerAdapter适配器装配,从而解决上述问题
2 添加<mvc:default-servlet-handler></mvc:default-servlet-handler>
- 添加上述标签,解决静态资源加载问题。但添加后出现其他请处理器失效,添加mvc:annotation-driven解决问题
3 使用Jackson2处理json数据,必须添加mvc:annotation-driven标签
- 使用Jackson2步骤
- 添加jar包支持
- 添加@ResponseBody
- 添加配置:mvc:annotation-driven
- 注意:只有添加mvc:annotation-driven标签后,SpringMVC才会添加一个消息转换器【MappingJackson2HttpMessageConverter:处理Json数据消息转换器】
SpringMVC实现文件上传
1 使用 Jakarta Commons FileUpload
- 使用Jakarta Commons FileUpload技术实现了一个 MultipartResolver接口, 实现类是:CommonsMultipartResolver
2 使用步骤
-
导入相关jar包【pom.xml】 导入完jar包以后,注意查看project Settings中的Artifacts项目中WEB-INF/classes下有没有lib目录看看有没有刚导入的jar包
<!-- 实现文件上传:commons-fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
-
装配CommonsMultipartResolver
<!-- 装配CommonsMultipartResolver 注意:id必须是multipartResolver --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8"></property> <property name="maxUploadSize" value="102400"></property> </bean>
-
实现文件上传
<h2>上传文件</h2> <form th:action="@{/fileUpload}" method="post" enctype="multipart/form-data"> 用户名:<input type="text" name="username"><br> 上传文件:<input type="file" name="ufile"><br> <input type="submit"> </form>
@Controller
public class Test2FileUploadController {
private static final String SUCCESS = "success";
@RequestMapping(value = "/fileUpload", method = RequestMethod.POST)
public String doFileUpload(String username,
@RequestParam("ufile") MultipartFile multipartFile,
HttpSession session) {
try {
System.out.println("username = " + username);
System.out.println("multipartFile = " + multipartFile);
//1. 获取upload【文件上传-根目录】真实路径
String realPath = session.getServletContext().getRealPath("/upload");
File pFile = new File(realPath);
if (pFile.exists() == false) {
pFile.mkdirs();
}
//2. 获取文件名
String fileName = multipartFile.getOriginalFilename();
System.out.println("fileName = " + fileName);
String uuId = UUID.randomUUID().toString().replace("-", "").toUpperCase();
System.out.println("uuId = " + uuId);
//3. 实现文件上传 File.separator:路劲分隔符
multipartFile.transferTo(new File(realPath + File.separator + uuId + fileName));
} catch (Exception e) {
e.printStackTrace();
}
return SUCCESS;
}
}
3 优化文件上传
- 允许同名文件上传
- 为文件名拼接一个不可重复随机数
- 时间戳
- UUID【是一个32位,十六进制全球唯一随机数】
- 为文件名拼接一个不可重复随机数
SpringMVC拦截器
1 自定义拦截器两种方式
- 实现HandlerInterceptor接口
- 继承HandlerInterceptorAdapter适配器类
2 定义拦截器步骤
- 定义拦截器实现接口或继承类
- 重写三个方法【preHandle()、postHandle()、afterCompletion()】
- 将拦截器装配到IOC容器中
- 注解:@Component
- xml:bean标签
- 配置拦截器【将拦截器配置到指定请求处理器中(Controller)】
3 单个拦截器工作原理【执行流程】
- 客户端【浏览器】端向服务器端发送请求
- 前端控制器【略】
- 执行拦截器中preHandle()方法
- 执行Controller中处理请求方法
- 执行拦截器postHandle()方法
- 前端控制器【略】
- 执行拦截器afterCompletion()方法
- HandlerInterceptor接口方法说明:
a)preHandle():这个方法在业务处理器处理请求之前被调用,可以在此方法中做一些权限的校验。如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回true;如果程序员决定不需要再调用其他的组件去处理请求,则返回false。
b)postHandle():这个方法在业务处理器处理请求之后,渲染视图之前调用。在此方法中可以对ModelAndView中的模型和视图进行处理。
c)afterCompletion():这个方法在 DispatcherServlet 完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。