一、SpringMVC请求流程
用户发送请求,到前端控制器(servlet,DispatcherServlet)配置在web.xml中;前端控制器去找处理器映射器(HandlerMapping) 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理拦截器一并返回给 DispatcherServlet;根据处理器映射器返回的处理器,DispatcherServlet 会找“合适”的处理器适配器(HandlerAdapter);处理器适配器HandlerAdapter 会去执行处理器(Handler开发的时候会被叫成Controller也叫后端控制器)执行前会有转换器、数据绑定、校验器等等完成上面这些才会去正式执行Handler后端控制器Handler执行完成之后返回一个ViewResolver对象处理器适配器HandlerAdapter会将这个ModelAndView返回前端控制器DispatcherServlet 前端控制器会将ModelAndView对象交给视图解析器ViewResolver视图解析器ViewResolver解析ViewResolver对象之后返回逻辑视图前端控制器DispatcherServlet对逻辑视图进行渲染 (数据填充) 之后返回真正的物理View并响应给浏览器
二、配置文件
1. web.xml
<!-- 1. 配置DispatcherServlet
-->
<servlet>
<servlet
-name
>springmvc
</servlet
-name
>
<servlet
-class>org
.springframework
.web
.servlet
.DispatcherServlet
</servlet
-class>
<!-- 2. 配置初始化参数
-->
<init
-param
>
<param
-name
>contextConfigLocation
</param
-name
>
<param
-value
>classpath
:springmvc2
.xml
</param
-value
>
</init
-param
>
<load
-on
-startup
>1</load
-on
-startup
>
</servlet
>
<servlet
-mapping
>
<servlet
-name
>springmvc
</servlet
-name
>
<url
-pattern
>/</url
-pattern
>
</servlet
-mapping
>
2. springmvc.xml
<!-- 1. 注解的扫描
-->
<context
:component
-scan base
-package="com.lyzzz"/>
<!-- 自动配置RequestMappingHandlerMapping
和RequestMappingHandlerAdapter注解的驱动
-->
<mvc
:annotation
-driven
/>
<!-- 2. 配置视图解析器
-->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name
="viewClass" value
="org.springframework.web.servlet.view.JstlView"/>
<property name
="prefix" value
="/WEB-INF/view/"/>
<property name
="suffix" value
=".jsp"/>
</bean
>
<!-- 3. 配置拦截器
-->
<mvc
:interceptors
>
<mvc
:interceptor
>
<mvc
:mapping path
="/**"/>
<!-- 不拦截登录请求
-->
<!--<mvc
:exclude
-mapping path
="/login"/>-->
<bean
class="com.lyzzz.interceptor.MyInterceptor"/>
</mvc
:interceptor
>
<!-- 当设置多个拦截器时,先按顺序调用preHandler方法
然后逆序调用每个拦截器的postHandler和afterCompletion方法
-->
</mvc
:interceptors
>
<!-- 4. 异常处理器
-->
<bean id
="customExceptionResolver" class="com.lyzzz.exception.CustomExceptionResolver"></bean
>
<!-- 5. 前端控制器拦截的是
/ 释放静态资源的handler
-->
<mvc
:default-servlet
-handler
/>
三、@RequestMapping注解
@RequestMapping
value: 可配置多个地址
@RequestMapping(value
= {"/method1","/method2","/method3"})
public String
method()
method:配置请求方式
@RequestMapping(method
= {RequestMethod
.POST
,RequestMethod
.GET
})
public void method()
如有多个重复地址,可在类上添加@RequestMapping
@Controller
@RequestMapping("/param")
public class ParamController
响应数据格式consumes:指定处理请求的提交内容的类型(content-Type)
@RequestMapping(consumes
= "application/json;charset=utf-8")
public void method()
读取数据格式produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回
@RequestMapping(produces
= "application/json;charset=utf-8")
public void method()
params:指定request中必须包含某些参数值,才让该方法处理
@RequestMapping(params
= {"/num"})
public void method()
headers:指定request中必须包含某些指定的header值,才让该方法处理请求
@RequestMapping(headers
= {"\"Referer=http://www.hello.com/\""})
public void method()
四、@ResponseBody和 @RequestBody
@ResponseBody 发送 json
@RequestMapping(value
= "/method1",produces
= "application/json;charset=utf-8")
@ResponseBody
public String
method1(){
String json
= "{\"name\":\"zs\",\"age\":\"18\"}";
return json
;
}
@RequestBody 接收 json 封装参数
@RequestMapping(value
= "/method2" ,method
= {RequestMethod
.POST
})
@ResponseBody
public Teacher
method2(@RequestBody Teacher teacher
){
System
.out
.println(teacher
);
return teacher
;
}
要添加jackson jar包 * tomcat报错conf>catalina.properties * 添加 ,\ jackson-databind-2.10.0.jar,jackson-annotations-2.10.0.jar,jackson-core-2.10.0.jar
<!-- jackson
-databind
-->
<dependency>
<groupId>com
.fasterxml
.jackson
.core
</groupId
>
<artifactId>jackson
-databind
</artifactId
>
<version>2.10.0</version
>
</dependency
>
@RestController
@RestController
五、reseful @PathVariable
@RequestMapping("/method6/{name}/{age}")
public String
method6(@PathVariable("name") String name
, @PathVariable("age") int age
){
System
.out
.println(name
);
System
.out
.println(age
);
return "param";
}
六、封装数据
方法参数不同 @RequestParam
@RequestMapping("/method2")
public String
method2(@RequestParam(value
= "names",required
= true) String name
, @RequestParam(defaultValue
= "20") Integer age
){
System
.out
.println(name
);
System
.out
.println(age
);
return "param";
}
日期类型
@RequestMapping(value
= "/method3")
public String
method3(Date birthday
){
System
.out
.println(birthday
);
return "param";
}
@InitBinder
public void bindValue(WebDataBinder binder
){
binder
.registerCustomEditor(Date
.class,
new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));
}
@DateTimeFormat(pattern
= "yyyy-MM-dd")
private Date birthday
;
七、返回值
@RequestMapping("method1")
public ModelAndView
method1(){
ModelAndView modelAndView
= new ModelAndView();
modelAndView
.addObject("result","返回值是modelandview");
modelAndView
.setViewName("method1");
return modelAndView
;
}
@RequestMapping("method2")
public void method2(HttpServletRequest request
, HttpServletResponse response
) throws ServletException
, IOException
{
request
.setAttribute("request","request");
request
.getRequestDispatcher("/WEB-INF/view/method1.jsp").forward(request
,response
);
HttpSession session
= request
.getSession();
session
.setAttribute("response","response1");
response
.sendRedirect("/index.jsp");
response
.setContentType("application/json;charset=utf-8");
response
.getWriter().println("{\"name\":\"中国\"}");
String method3
= (String
) request
.getAttribute("method3");
System
.out
.println(method3
);
String name
= request
.getParameter("name");
System
.out
.println(name
);
}
@RequestMapping("method3")
public String
method3(HttpServletRequest request
){
request
.setAttribute("method3","转发到另一个");
return "method1";
return "forward:/return/method2";
return "redirect:/return/method2?name=zsss";
}
八、拦截器
* 8. 拦截器 interceptor
* 在controller之后view视图解析之前执行
* 过滤器和拦截器的区别
* 1. 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
* 2. 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
* 3. 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
* 4. 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
* 5. 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
*
* |-- 拦截器配置
* |-- 编写拦截器类,实现HandlerInterceptor接口,重写方法
* |-- springmvc
.xml中配置拦截器
* <!-- 配置拦截器
-->
* <mvc
:interceptors
>
* <mvc
:interceptor
>
* <!-- 匹配url路径,如果不配置或者 设置为
"/**" 将拦截所有controller
-->
* <mvc
:mapping path
="/**"/>
* <!-- 不拦截登录请求
-->
* <!--<mvc
:exclude
-mapping path
="/login"/>-->
* <bean
class="com.lyzzz.interceptor.MyInterceptor"/>
* </mvc
:interceptor
>
* <!-- 当设置多个拦截器时,先按顺序调用preHandler方法
* 然后逆序调用每个拦截器的postHandler和afterCompletion方法
-->
* </mvc
:interceptors
>
* |-- preHandle()
* 在控制器方法调用前执行,返回值为是否中断
* true表示继续执行
* false则会中断后续的所有操作,所以我们使用response来继续响应后续请求
*
* |-- postHandle()
* 在控制器方法调用后,解析视图前调用
* 可以对模型和视图进一步进行修改或渲染
* 可在ModelAndView中加入数据,比如当前时间
*
* |-- afterCompletion()
* 整个请求完成,即视图渲染结束后调用,
* 可做资源清理工作,或日志记录
九、异常机制