HttpMessageConverter
报文信息转换器,将请求报文转换为Java对象 ,或将Java对象转换为响应报文,它提供了两个注解给两个类型:@RequestBody @RequestEntity @ResponseBody @ResponseEntity
@RequestBody
可以获取请求体,需要在控制器方法设置一个形参,使用@RequestBody进行标识,当前请求的请求体就会为当前注解所标识的形参赋值 。(请求报文转换为Java对象)



@RequestEntity
封装请求报文的一种类型,需要在控制器方法的形参中设置该类型的形参,当前请求的请求报文就会赋值给该形参 ,可以通过getHeaders()获取请求头信息 ,通过getBody()获取请求体信息。 (请求报文转换为Java对象)

html
<form th:action="@{testRequestEntity}" method="post">
<input type="text" name="username"><br>
<input type="text" name="password"><br>
<input type="submit" value="测试RequestEntity"><br>
</form><br>


@ResponseBody
用于标识一个控制器方法,可以将该方法的返回值直接作为响应报文的响应体响应到浏览器(Java对象转换为响应报文)。
在原来使用的是HttpServletResponse。
java
@RequestMapping("/testResponse")
public void testResponse(HttpServletResponse response) throws IOException {
response.getWriter().print("Hello,response");
}


使用ReponseBody实现java对象转为响应报文
java
@RequestMapping("/testResponseBody")
@ResponseBody
//这个方法的返回返回的是当前的响应体
public String testResponseBody(){
return "success";
}

无ResponseBody返回响应效果

处理json的步骤
无法直接返回对象,想要对象直接返回,需要将对象转换为json,需要导入jackson依赖。(还有一个是jackson-core,该API过于基本,此处导入jackson-databind依赖)
XML
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
在springMVC的核心配置文件中开启mvc的注解驱动,此时在HandlerAdaptor中会自动装配。可以将响应到浏览器的Java对象转换为json格式的字符串。
XML
<!--开启mvc的注解驱动-->
<mvc:annotation-driven/>



Ajax
请求超链接
html
<div id="app">
<a @click="testAxios" th:href="@{/testAxios}">SpringMVC处理ajax</a>
</div>
通过vue和axios处理点击事件
html
<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>
java
@RequestMapping("/testAxios")
@ResponseBody
public String testAxios(String username,String password){
System.out.println(username+","+password);
return "hello,axios";
}

@RestController注解
@RestController注解是springMVC提供的一个复合注解,标识在控制器的类 上,就相对于为类添 加了**@Controller注解** ,并且为其中的每个办法添加了@ResponseBody注解。
@ReponseEntity
用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文。
文件上传和下载
文件下载
使用ResponseEntity实现下载文件的功能
java
//文件下载
@RequestMapping("/testDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException, IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("/static/img/1.jpg");
System.out.println(realPath);
//创建输入流
InputStream is = new FileInputStream(realPath);
//创建字节数组
byte[] bytes = new byte[is.available()];
//将流读到字节数组中
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式attachment(以附件的形式下载)以及下载文件的名字
headers.add("Content-Disposition", "attachment;filename=1.jpg");
//设置响应状态码
HttpStatus statusCode = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
//关闭输入流
is.close();
return responseEntity;
}

文件上传
文件上传:要求form表单的请求方式必须为post,并且添加属性enctype="multipart/form-data",SpringMVC中将上传的文件封装到MultIpartFile对象中,通过此对象可以获取文件相关信息。


文件上传需要添加commons-fileupload依赖。
XML
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
配置文件上传解析器
XML
<!--配置文件上传解析器,将上传的文件封装为MultipartFile-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
java
@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().replaceAll("-","");
//将uuid和后缀名拼接后的结果作为最终的文件名
fileName = uuid + suffixName;
//通过ServletContext获取服务器中photo目录的路径
ServletContext servletContext = session.getServletContext();
String photoPath = servletContext.getRealPath("photo");
File file = new File(photoPath);
//判断photoPath所对应路径是否存在
if(!file.exists()){
//若不存在,则创建目录
file.mkdir();
}
String finalPath = photoPath + File.separator + fileName;
//上传文件,transferTo转移
photo.transferTo(new File(finalPath));
return "success";
}
我的文件上传完成后是存放在tomcat服务下的路径中。


拦截器
拦截器的配置
SpringMVC的拦截器用于拦截控制器方法的执行
并且拦截器需要实现HandlerInterceptor或者继承HandlerInterceptorAdapter类。并且重写三个抽象方法,拦截器必须在SpringMVC的配置文件中进行配置。
过滤器filter作用在DispatcherServlet之前,DispatcherServlet在接收到浏览器的请求之后,对请求进行处理,将请求信息与RequestMapping(请求映射进行匹配),匹配上后,调用Controller,拦截器Handler作用在调用Controller之前。
拦截器的三个抽象方法
- preHandle() :控制器方法执行之前 执行preHandle(),其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用控制器方法;返回false表示拦截,即不调用控制器方法。
- postHandle(): 控制器方法执行之后执行postHandle()。
- afterCompletion(): 处理完视图和模型数据,渲染视图完毕之后 执行afterCompletion()。当**
preHandle()
里** 的返回值为false时,postHandle()
和afterCompletion()
都不会执行,因为控制器方法被拦截了,而它们都是在控制器方法之后。
添加拦截器
在配置文件中,拦截器使用<mvc:interceptors>进行配置,其中**<bean>和<ref>都是默认** 对所有请求进行拦截,<mvc:interceptor>可以设置拦截规则。
<bean>直接指定编写的拦截类**,<ref>需要在拦截类上添加@Component将该类交给IoC管理**,所有IoC管理的类都需要被扫描,注意扫描范围。
java
@Controller
public class TestController {
//模糊映射,有效拦截恶意请求
@RequestMapping("/**/testInterceptor")
public String testInterceptor(){
return "success";
}
}

使用bean:
XML
<!--配置拦截器-->
<mvc:interceptors>
<bean class="com.serenity.mvc.Interceptors.FirstInterceptor"></bean>
</mvc:interceptors>
java
//拦截器配置,需要实现HandlerInterceptor接口,Ctrl+O快速重写方法
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor->preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("FirstInterceptor->postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("FirstInterceptor->afterHandle");
}
}

使用ref:
XML
<!--配置拦截器-->
<mvc:interceptors>
<!--<bean class="com.serenity.mvc.Interceptors.FirstInterceptor"></bean>-->
<ref bean="firstInterceptor"/>
</mvc:interceptors>
java
//拦截器配置,需要实现HandlerInterceptor接口
//通过组件Component将拦截器交给IoC容器管理(注意需要扫描),可以在配置时用ref进行拦截器的配置,未用,可用bean配置
@Component
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor->preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("FirstInterceptor->postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("FirstInterceptor->afterHandle");
}
}

使用interceptor:
mapping :设置拦截路径。
exclude-mapping:设置排除路径
指定拦截器:也是bean和ref两种
XML
<!--配置拦截器-->
<mvc:interceptors>
<!--<bean class="com.serenity.mvc.Interceptors.FirstInterceptor"></bean>-->
<!--<ref bean="firstInterceptor"/>-->
<mvc:interceptor>
<!--拦截规则-->
<!--拦截所有-->
<mvc:mapping path="/*"/>
<!--除了这个路径-->
<mvc:exclude-mapping path="/"/>
<!--指定拦截器-->
<ref bean="firstInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
主页不会被拦截:


页面跳转后显示拦截:


若需要拦截所有请求,需要在mapping :设置拦截路径中写/**
多个拦截器的执行顺序
- 若存在多个拦截器,且每个拦截器的preHandle()都返回true,则拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关。
- preHandle()会按照配置的顺序执行,
- postHandle()和afterComplation()会按照配置的反序执行。
- 若某个拦截器的preHandle()返回了false,
- preHandle()返回false的拦截器和它之前的拦截器的preHandle()都会执行,
- 所有拦截器的postHandle()都不执行,
- 返回false的拦截器之前的拦截器的afterComplation()都会执行。