1.HttpMessageConverter
HttpMessageConverter,报文信息转换器,将请求报文转换为Java对象,或将ava对象转换为响应报文
HttpMessageConverter提供了两个注解和两个类型:
@RequestBody,@ResponseBody,RequestEntity,ResponseEntity
1.1、@RequestBody
@RequestBodyi可以获取请求体,需要在控制器方法设置一个形参,使用@RequestBodyi进行标识,当前请求的
请求体就会为当前注解所标识的形参赋值
<form th:action="@{/testRequestBody}" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit">
</form>
@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String requestBody){
System.out.println("requestBody:"+requestBody);
return "success";
}
输出结果:
requestBody:username=admin&password=123456
1.2、RequestEntity
RequestEntity封装请求报文的一种类型,需要在控制器方法的形参中设置该类型的形参,当前请求的请求报文就会赋值给该形参,可以通过getHeaders()获取请求头信息,通过getBody()获取请求体信息
@RequestMapping("/testRequestEntity")
public String testRequestEntity(RequestEntity<String> requestEntity){
System.out.println("requestHeader:"+requestEntity.getHeaders());
System.out.println("requestBody:"+requestEntity.getBody());
return "success";
}
requestHeader:[host:"localhost:8080", connection:"keep-alive", content-length:"30", cache-control:"max-age=0", sec-ch-ua:""Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"", sec-ch-ua-mobile:"?0", sec-ch-ua-platform:""Windows"", upgrade-insecure-requests:"1", origin:"http://localhost:8080", content-type:"application/x-www-form-urlencoded", user-agent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36", accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", sec-fetch-site:"same-origin", sec-fetch-mode:"navigate", sec-fetch-user:"?1", sec-fetch-dest:"document", referer:"http://localhost:8080/springMVC/", accept-encoding:"gzip, deflate, br", accept-language:"zh-CN,zh;q=0.9", cookie:"Idea-c2e4bb65=623e8a9c-5cb8-4dd4-9e6b-41cd2a86cff3; Pycharm-71831198=30c7fc79-3e64-4012-ba2f-e49f7c2a68a6; _CITA_hid=26EUCnMD8WKF-kYHR1V7OgA; _ga=GA1.1.528973499.1659967166; __utmz=111872281.1660009822.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); Y190cmFja2lk=ed75e8351ca6400b95cfb507ead15153; userNewsPort0=1; Hm_lvt_d78fc86b6a707e2ec20bacb216c0eb62=1660269636; Hm_lvt_ba187bdcb4cc97d2cdba3789bd52488d=1660269636; Idea-c2e4bb66=9ca4f8d1-64a6-4389-86b3-3694a8a9af0e; Hm_lvt_bc2faede6630417a4d534de035bbebe0=1672800089; Hm_lvt_d2eddf9b155bdbd9ea015490aef570fa=1672799616,1672799888,1672821447,1672821778; Hm_lvt_649f268280b553df1f778477ee743752=1673001368; _pk_id.24.1fff=a834b9e0f9d8fb1e.1660138423.3.1673066803.1660185596.; Hm_lvt_2601a0f4477572ee12d6c06945adc380=1673066803; _pk_id.100001.1fff=fdf306702529342d.1660009822.6.1673448701.1672802947.; __utma=111872281.528973499.1659967166.1672802946.1673448701.6"]
requestBody:username=admin&password=123456
1.3、@ResponseBody
@ResponseBody用于标识一个控制器方法,可以将该方法的返回值直接作为响应报文的响应体响应到浏览器
@RequestMapping("/testResponseBody")
@ResponseBody
public String testResponseBody(){
return "success";
}
结果:
浏览器页面显示success
1.4、@ResponseBody处理json
@ResponseBody:处理json的步骤:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.2.1</version>
</dependency>
- 在SpringMVC的核心配置文件中开启mvc的注解驱动,此时在HandlerAdaptor中会自动装配一个消息转换器:MappingJackson2 HttpMessageConverter,.可以将响应到浏览器的java对象转换为json格式的字符串
- 在处理器方法上使用@ResponseBody注解进行标识
- 将Java对象直接作为控制器方法的返回值返回,就会自动转换为Json格式的字符串
@RequestMapping("/testResponseuser")
@ResponseBody
public User testResponseUser(){
return new User (1001,"admin","123456",23,"");
}
浏览器的页面中展示的结果:
("id":1001,"username":"admin","password":"123456","age":23,"sex":"男")
1.5、处理ajax
- 请求超链接
testAjax
- 通过vue和axios处理点击事件:
<script type="text/javascript"th:src="@{/static/js/vue.js}"></script>
<script type="text/javascript"th:src="@{/static/js/axios.min.js}"></script>
<script type="text/javascript">
new Vue({
el:"#app",
methods:{
testAxios:function (event){
axios({
method:"post",
url:event.target.href,
params:{
username:"admin",
password:"123456"
}
}).then(function (response){
alert(response.data)
});
event.preventDefault()
}
}
})
</script>
@RequestMapping("/testAxios")
@ResponseBody
public String testAxios(String usernme, String passworf) {
System.out.println("username"+usernme+",password"+passworf);
return "hello,axios";
}
1.6、@RestController注解
@RestController注解是springMVC提供的一个复合注解,标识在控制器的类上,就相当于为类添加了
@Controlleri注解,并且为其中的每个方法添加了@ResponseBody注解
1.7、ResponseEntity
ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文
2.文件上传和下载
2.1、文件下载
使用ResponseEntity实现下载文件功能
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf">
<head>
<meta charset="UTF-8">
<title>测试文件上传和下载</title>
</head>
<body>
<a th:href="@{/testDown}">下载思诺的照片</a>
</body>
</html>
@Controller
public class FileUpAndDownController {
@RequestMapping("/testDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
//获取Serv]etContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("/static/img/思诺.jpg");
//创建输入流
InputStream is = new FileInputStream(realPath);
//创建字节数组
byte[] bytes = new byte[is.available()];
//将流读到字节数组中
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式以及下载文件的名字
headers.add("Content-Disposition", "attachment;filename=思诺.jpg");
//设置响应状态码
HttpStatus statusCode = HttpStatus.OK;
//创建ResponseEntity.对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers,statusCode);
//关闭输入流
is.close();
return responseEntity;
}
}
2.2 、文件上传
@RequestMapping("/testUp")
public String testUp(MultipartFile photo, HttpSession session) throws IOException {
//获取上传的文件的文件名
String filename = photo.getOriginalFilename();
//获取上传的文件的后缀名
String suffixName = filename.substring(filename.lastIndexOf("."));
//将UUID作为文件名
String uuid = UUID.randomUUID().toString();
//将uuid和后缀名拼接后的结果作为最终的文件名
filename = uuid+suffixName;
ServletContext servletContext = session.getServletContext();
String photoPath = servletContext.getRealPath("photo");
File file = new File(photoPath);
if (!file.exists()) {
//若不存在则创建目录
file.mkdirs();
}
String finalPath = photoPath + File.separator + filename;
photo.transferTo(new File(finalPath));
return "success";
}
3.拦截器
3.1、拦截器的配置
SpringMVCE中的拦截器用于拦截控制器方法的执行
SpringMVC中的拦截器需要实现Handlerlnterceptor
SpringMVC的拦截器必须在SpringMVC的配置文件中进行配置:
<mvc:interceptors>
<bean class="com.gbx.mvc.interceptors.FirstInterceptor"></bean>
<ref bean="firstInterceptor"></ref>
<mvc:interceptor>
<mvc:mapping path="/*"/>
<mvc:exclude-mapping path="/"/>
<ref bean="firstInterceptor"></ref>
</mvc:interceptor>
</mvc:interceptors>
3.2、拦截器的三个抽象方法
SpringMVC中的拦截器有三个抽象方法:
preHandle:控制器方法执行之前执行preHandle0,其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用控制器方法;返回flse表示拦截,即不调用控制器方法
postHandle:控制器方法执行之后执行oostHandle()
afterComplation:处理完视图和模型数据,渲染视图完毕之后执行afterComplation0
3.3、多个拦截器的执行顺序
- 若每个拦截器的preHandle()都返回true
此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关:
preHandle(0会按照配置的顺序执行,而postHandle(0和afterComplation(O会按照配置的反序执行 - 若某个拦截器的preHandlel()返回了false
preHandle()返回false和它之前的拦截器的preHandle()都会执行,postHandle()都不执行,返回false的拦截器之前的拦截器的afterComplation()会执行
四.异常处理器
4.1、基于配置的异常处理
SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口:HandlerExceptionResolver
HandlerExceptionResolver接口的实现类有:DefaultHandlerExceptionResolveri和SimpleMappingExceptionResolver
SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResolver,使用方式:
<!--配置异常处理-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!--
properties的键表示处理器方法执行过程中出现的异常
properties的值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面
-->
<prop key="java.lang.ArithmeticException">error</prop>
</props>
</property>
<!--设置将异常信息共享在请求域中的-->
<property name="exceptionAttribute"value="ex"></property>
</bean>
4.2、基于注解的异常处理
//@ControllerAd小vice将当前类标识为异常处理的组件
@ControllerAdvice
public class ExceptionController {
//@ExceptionHandler用于设置所标识方法处理的异常
@ExceptionHandler(ArithmeticException.class)
//ex表示当前请求处理中出现的异常对象
public String handleArithmeticException(Exception ex, Model model) {
model.addAttribute("ex", ex);
return "error";
}
}