请求流程
具体流程:
- 用户发请求–>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制。
2.DispatcherServlet–>HandlerMapping,HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器,多个HandlerInterceptor拦截器)。
3.DispatcherServlet–>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器。
4.HandlerAdapter–>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理,并返回一个ModelAndView对象(包含模型数据,逻辑视图名)
5.ModelAndView的逻辑视图名–>ViewResolver,ViewResoler将把逻辑视图名解析为具体的View。
6.View–>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构
7.返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户。
传参:
- 表单模式
- 基本数据类型和字符串类型
- 实体类型(JavaBean)
- 集合数据类型(List、map集合等)
- json
- 需要引入json依赖
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.10.2</version> </dependency>
这两种前端传参都可以用如下示例:
@PostMapping(value = "test" )
@ResponseBody
public UserModel test( UserModel userModel){
return userModel;
}
自定义类型转化
- 实现Converter类
package com.zzg.control.converter;
import org.springframework.core.convert.converter.Converter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class StringToDateConverter implements Converter<String, Date> {
public Date convert(String s) {
try {
DateFormat df = new SimpleDateFormat("yyyy/MM-dd");
// 解析字符串
Date date = df.parse(s);
return date;
} catch (Exception e)
{
throw new RuntimeException("类型转换错误");
}
}
}
- 配置 config xml文件
<!-- 增加自定义配置-->
<bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters" >
<set>
<bean class="com.zzg.control.converter.StringToDateConverter"/>
</set>
</property>
</bean>
<!-- 开启springmvc框架注解支持-->
<!-- 添加conversion-service 属性 -->
<mvc:annotation-driven conversion-service="conversionServiceFactoryBean">
常用注解
-
RequestParam注解
-
作用:把请求中的指定名称的参数传递给控制器中的形参赋值
-
属性
1. value:请求参数中的名称 2. required:请求参数中是否必须提供此参数,默认值是true,必须提供
-
代码如下
/** * 接收请求 * @return */ @RequestMapping(path="/hello") public String sayHello(@RequestParam(value="username",required=false)String name) { System.out.println("aaaa"); System.out.println(name); return "success"; }
-
-
RequestBody
1. 作用:用于获取请求体的内容(注意:get方法不可以)
2. 属性1. required:是否必须有请求体,默认值是true
/** * 接收请求 * @return */ @RequestMapping(path="/hello") public String sayHello(@RequestBody String body) { System.out.println("aaaa"); System.out.println(body); return "success"; }
-
PathVariable注解
- 作用:拥有绑定url中的占位符的。例如:url中有/delete/{id},{id}就是占位符
- 属性 1. value:指定url中的占位符名称
//<a href="user/hello/1">入门案例</a>
/** * 接收请求 * @return */
@RequestMapping(path="/hello/{id}")
public String sayHello(@PathVariable(value="id") String id) {
System.out.println(id);
return "success";
}
文件上传
- 引入依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
- 添加bean配置
<!--文件上传,接收multipart/form-data 传输的数据; id值必须是multipartResolver-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
/**
* SpringMVC方式的文件上传
*
* @param request
* @return
* @throws Exception
*/
@RequestMapping(value="/fileupload2")
public String fileupload2(HttpServletRequest request,MultipartFile upload) throws Exception {
System.out.println("SpringMVC方式的文件上传...");
// 先获取到要上传的文件目录
String path = request.getSession().getServletContext().getRealPath("/uploads");
// 创建File对象,一会向该路径下上传文件
File file = new File(path);
// 判断路径是否存在,如果不存在,创建该路径
if(!file.exists()) {
file.mkdirs();
}
// 获取到上传文件的名称
String filename = upload.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
// 把文件的名称唯一化
filename = uuid+"_"+filename;
// 上传文件
upload.transferTo(new File(file,filename));
return "success";
}
- 异常处理器
- 处理类
package com.zzg.control.ext;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
public class ExectionR implements HandlerExceptionResolver {
public ModelAndView resolveException(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) {
ModelAndView mv = new ModelAndView();
// 存入错误的提示信息
mv.addObject(" message ", ex.getMessage());
// 跳转的Jsp页面
mv.setViewName("error");
return mv;
//返回json
// setResponseParam(response, 500, JSON.toJSONString(mv));
//return null;
}
private void setResponseParam(HttpServletResponse response, int code, String msg) {
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
try {
response.getWriter().print(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 配置bean
<bean id="exectionR" class="com.zzg.control.ext.ExectionR"/>
拦截器
-
SpringMVC框架中的拦截器用于对处理器进行预处理和后处理的技术。
-
可以定义拦截器链,连接器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链 中的拦截器会按着定义的顺序执行。
-
拦截器和过滤器的功能比较类似,有区别
1. 过滤器是Servlet规范的一部分,任何框架都可以使用过滤器技术。 2. 拦截器是SpringMVC框架独有的。 3. 过滤器配置了/*,可以拦截任何资源。 4. 拦截器只会对控制器中的方法进行拦截。 5. 拦截器也是AOP思想的一种实现方式 6. 想要自定义拦截器,需要实现HandlerInterceptor接口。
- 继承 HandlerInterceptor
拦截器包含三个方法preHandle、postHandle、afterCompletion
-
preHandle
在handler方法执行之前执行,返回一个boolean值。只有当返回true时才会继续执行handler的方法或者下一个拦截器的preHandle方法,如果返回false或者抛出异常则中止。
-
postHandle
在handler方法成功执行之后、dispatcher渲染视图之前执行。 如果任何一个拦截器的preHandle方法返回false或者抛出异常, 或者handler方法中抛出异常都不会执行postHandle方法。
-
afterCompletion
在视图渲染结束后执行,并且无论handler方法中是否抛出异常都一定会执行。
假如有拦截器1、2、3,preHandle方法中打印pre1、pre2、pre3,postHandle方法中打印post1、post2、post3,afterCompletion方法中打印after1、after2、after3,如果全部拦截器都执行执行结束,打印结果应该为: pre1, pre2, pre3, post3, post2, post1, after3, after2, after1
如果拦截器2的preHandle返回false或者抛出异常,则打印结果为: pre1, pre2, after1
如果handler方法抛出异常,则打印结果为: pre1, pre2, pre3, after3, after2, after1