1.SpringMVC中重要组件
(1)DispatcherServlet:前端控制器,接收所有请求(如果配置/不包含jsp)
(2)HandlerMapping:解析请求格式,判断希望执行哪个方法
(3)HandlerAdapter:负责调用具体的方法
(4)ViewResovler:视图解析器,解析结果,准备跳转到具体的物理视图
2.SpringMVC运行原理
(1)文字解释
如果在web.xml中设置DisptcherServlet的<url-partten>为 / 时,当用户发起请求,请求一个控制器,首先会执行DisptcherServlet。由DisptcherServlet调用HandleMapping的DefaultAnnotationHandleMapping来解析URL,解析后调用HandleAdapter组件的AnnotationMethodHandleAdapter调用Co'ntroller中的HandlerMethod。当HandlerMethod执行完成后会返回一个view,这个view会被ViewResovler进行视图解析,解析后调用jsp对应的.class文件并运行,最终把结果响应给客户端
3.SpringMVC环境搭建
(1)导入jar
(2)在web.xml中配置前端控制器DispatcherServlet
如果不配置<init-param>会在/WEB-INF/<servlet-name>-servlet.xml
<!-- 配置前端控制器 --> <servlet> <servlet-name>dispatcherservlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!-- 自启动 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherservlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
(3)在src下新建springmvc.xml
引入xmln:mvc命名空间
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--扫描注解--> <context:component-scan base-package="com.mxj.controller"></context:component-scan> <!-- 注解驱动 --> <mvc:annotation-driven></mvc:annotation-driven> <!-- 静态资源 mapping:请求路径js/** location: 到WEB-INF/js/下找**资源 <mvc:resources location="/WEB-INF/js/" mapping="/js/*"></mvc:resources> --> <mvc:resources location="/js/" mapping="/js/**"></mvc:resources> <mvc:resources location="/css/" mapping="/css/**"></mvc:resources> <mvc:resources location="/images/" mapping="/images/**"></mvc:resources> </beans>
(4)编写控制器类
@Controller public class DemoController { @RequestMapping("demo") public String demo(){ System.out.println("执行demo"); return "main.jsp"; } }
4.字符编码过滤器
<!-- 字符编码过滤器 --> <filter> <filter-name>encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
5.传参
(1)把内容写到方法(HandlerMethod)参数中,SpringMVC只要有这个内容,就会注入内容
(2)基本数据类型参数
默认保证参数名称和请求中 传递的参数名相同
@Controller public class DemoController { @RequestMapping("demo") public String demo(String name,int age){ System.out.println("执行demo:"+name+" "+age); return "main.jsp"; } }
如果请求参数名和方法参数名不对应,使用@RequestParam()赋值
@RequestMapping("demo") public String demo(@RequestParam("name") String name,@RequestParam("name") int age){ System.out.println("执行demo:"+name+" "+age); return "main.jsp"; }
如果方法参数是基本数据类型(不是封装类),可以通过@RequestParam()设置默认值
@RequestMapping("page") public String page(@RequestParam(defaultValue="2") int pageSize,@RequestParam(defaultValue="1")int pageNumber){ return "main.jsp"; }
如果强制要求必须有某个参数
@RequestMapping("demo2") public String demo2(@RequestParam(required=true)String name){ System.out.println("name是SQL的查询条件,必须传递name参数"+name); return "main.jsp"; }
(3)HandlerMethod中参数是对象类型
请求参数名和对象中属性名对应(get/set方法)
@RequestMapping("demo3") public String demo4(People peo){ return "main.jsp"; }
(4)请求参数中包含多个同名参数的获取方式
复选框传递的参数就是多个同名参数
@RequestMapping("demo4") public String demo5(String name,int age,@RequestParam("hover") ArrayList<String> hover){ System.out.println(name+" "+age+" "+hover); return "main.jsp"; }
<input type="text" value="peo.name"> <input type="text" value="peo.age">
新建一个类:对象名和参数中电前面名称对应
public class Demo { private People peo;
控制器
@RequestMapping("demo4") public String demo5(String name,int age,@RequestParam("hover") ArrayList<String> hover){ System.out.println(name+" "+age+" "+hover); return "main.jsp"; }
(6)请求参数中传递集合对象类型参数
jsp代码
<input type="text" value="peo[0].name"> <input type="text" value="peo[1].name"> <input type="text" value="peo[0].age"> <input type="text" value="peo[1].age">
新建类
public class Demo { private List<People> peo;
(7)restful传值方式
简化jsp中参数编写格式
在jsp中设定特定的格式
<a href="demo6/123/abc>跳转</a>
在控制器中代码
在@RequestMapping中一定要和请求格式对应
{名称}中名称是自定义名称
@PathVariable:获取@RequestMapping中内容,默认按照方法参数名称去寻找
@RequestMapping("demo6/{id}/{name}") public String demo6(@PathVariable String name,@PathVariable("id") int age){ System.out.println(name+" "+age); return "/main.jsp"; }
6.跳转方式
默认跳转方式请求转发
设置返回值字符串内容
添加 redirect:资源路径 重定向
添加 forward:资源路径 或省略forward 转发
7.视图解析器
(1)SpringMVC会提供默认视图解析器
(2)程序员自定义视图解析器
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver>"> <property name="prefix" value="/"></property> <property name="suffix" value=".jsp"></property> </bean>
(3)如果希望不执行自定义视图解析器,在方法返回值前面添加 forward: 或 redirect:
8.@ResponseBody
在方法上只有@RequestMapping时,无论返回值是什么都认为是需要跳转
在方法上添加@ResponseBody(恒不跳转)
如果返回值满足key-value形式(对象或map)
把响应头设置为application/json:charset=utf-8
把转换后的内容以输出流的形式相应给客户端
如果返回值不满足key-value,例如返回值为String
把响应头设置为text/html
把方法返回值以流的形式直接输出
如果返回值包含中文,出现中文乱码: @RequestMapping("demo12",produces="text/html;charset=utf-8")
produces表示响应头中Content-Type取值
@RequestMapping("demo12") @ResponseBody public People demo12()throws IOException{ People p = new People(); p.setAge(12); p.setName("张三"); return p; }
9.自定义拦截器
(1)发送请求时被拦截器拦截,在控制器的前后添加额外功能
拦截器,请求的拦截,针对点是控制器方法(Controller)
(2)SpringMVC拦截器和Filter的区别
拦截器只能拦截Controller
Filter可以拦截任何请求
(3)实现自定义拦截器的步骤
新建类实现 HandlerInterceptor
public class DemoInterceptor implements HandlerInterceptor{ //在进入控制器之前执行 //如果返回值为false,阻止进入控制器 public boolean preHandle(HttpServletRequest arg0,HttpServletResponse arg1,Object arg2)throws Exception{ System.out.println("arg2:"+arg2); System.out.println("preHandle"); return true; } //控制器执行完成,进入到jsp之前执行 //日志记录 //敏感词语过滤 public void postHandle(HttpServletRequest arg0,HttpServletResponse arg1,Object arg2,ModelAndView arg3)throws Exception{ System.out.println("注"+arg3.getViewName()+"跳转"); System.out.println("model的值"+arg3.getModel().get("model")); System.out.println("postHandle"); } //jsp执行完成后执行 //记录执行过程中出现的异常 //把异常记录到日志中 public void afterCompletion(HttpServletRequest arg0,HttpServletResponse arg1,Object arg2,Exception arg3)throws Exception{ System.out.println("afterCompletion"); } }
(4)在springmvc.xml配置拦截器需要拦截哪些控制器
拦截所有控制器
<mvc:interceptors> <bean class="com.mxj.interceptor.DemoInterceptor"></bean> </mvc:interceptors>
拦截特定的url
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/demo1"/> <mvc:mapping path="/demo2"/> <bean class="com.mxj.interceptor.DemoInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
10.拦截器栈
(1)多个拦截器同时生效时,组成拦截器栈
(2)顺序:先进后出
(3)执行顺序和在springmvc.xml中配置顺序有关
(4)设置先配置拦截器A再配置拦截器B执行顺序为:
preHandle(A)-->preHandle(B)-->控制方法-->postHandle(B)-->postHandle(A)-->JSP-->afterCompletion(B)-->afterCompletion(A)