springMVC
- 一款基于web开发的应用框架
- MVC:
- Model : 模型 - 数据 domain
- View : 视图 - 数据的展现方式 jsp, jstl, el
- Controller : 控制器 - 结合模型和视图,控制请求流程 例如:servlet, controller
- Servlet和Controller比较:
- servlet缺点:
- 请求参数处理麻烦 String 值 = request.getParameter(“参数名”)
- 当业务比较多时,servlet 类的数量膨胀不好管理
- controller优点:
- 利用spring 各种思想,ioc, di, aop, 可扩展性高
- servlet缺点:
开始学习:
知识点一:一个基于springMVC的http请求的响应过程
- 第一步:向服务器发送Http request请求,请求被前端控制器==(DispatcherServlet)==捕获。
- 第二步:前端控制器根据xml(spring.xml)文件中的配置(或者注解)对请求的URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用处理器映射器(HandlerMapping)获得处理该请求的Handler(controller)以及Handler对应的拦截器(Interceptor),最后以 HandlerExecutionChain 对象的形式返回。
- 第三步:前端控制器根据获得的Handler(controller),选择一个合适的处理器适配器(HandlerAdapter)去执行该Handler。
- 第四步:处理器适配器提取request中的模型数据,填充Handler入参,执行处理器(Handler)(也称之为Controller).
- 第五步:Handler(Controller)执行完成后,向处理器适配器返回一个ModelAndView对象,处理器适配器再向前端控制器返回该ModelAndView对象(ModelAndView只是一个逻辑视图)。
- 第六步:根据返回的ModelAndView,前端控制器请求一个适合的视图解析器(ViewResolver)(必须是已经注册到Spring容器中的ViewResolver)去进行视图解析,然后视图解析器向前端控制器返回一个真正的视图View(jsp)。
- 第七步:前端控制器通过Model解析出ModelAndView中的参数进行解析,最终展现出完整的View并通过Http response返回给客户端。
知识点二:组件分析
-
前端控制器DispatcherServlet:(不需要我们开发)
- 作用:接收请求,响应结果,相当于转发器,中央处理器。有了DispatcherServlet减少了其它组件之间的耦合度。
-
处理器映射器HandlerMapping:(不需要我们开发)
- 作用:根据请求url查找Handler。
-
处理器适配器HandlerAdapter:(不需要我们开发)
- 作用:按照特定的规则(HandlerAdapter要求的规则)去执行Handler
-
处理器Handler(需要我们开发)
- 注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
-
视图解析器ViewResolver(不需要我们开发)
- 作用:进行视图解析,根据逻辑视图名解析成真正的View
-
视图View(需要程序员开发JSP)
- View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)
-
【注】:不需要程序员开发的,需要程序员自己做一下配置即可。
-
依赖添加
依赖:
<!-- spring mvc 依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.21.RELEASE</version>
</dependency>
<!-- servlet, jsp, 标签库 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
- spring配置文件添加
这里和spring博客那里的xml配置是一样的:可以根据所需要的配置
下面我举了一些重要配置。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 启用了 与 springmvc 相关的注解
@RestController
@RequestMapping
@ResponseBody
@ExceptionHandler
...
-->
<mvc:annotation-driven />
<!-- 扫描控制器类 -->
<context:component-scan base-package="com.banban.controller"/>
<!-- 配置视图的完整路径(前缀 和 后缀) 配置视图解析器-->
<mvc:view-resolvers>
<!-- 前缀 + 视图名 + 后缀 == 完整路径, 再利用请求转发跳转至 jsp -->
<mvc:jsp prefix="/" suffix=".jsp" />
</mvc:view-resolvers>
<!-- 配置上传文件表单解析器, id 是固定的 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 限制上传文件的总大小,单位是字节-->
<property name="maxUploadSize" value="500000"></property>
</bean>
<!--静态资源(html,图片,js,css) 忽略静态资源路径的过滤-->
<mvc:default-servlet-handler/>
<!-- 扫描拦截器类 -->
<context:component-scan base-package="com.banban.interceptor"/>
<!--配置拦截器-->
<mvc:interceptors>
<!-- 某个拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/a"/>
<ref bean="myInterceptor1"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
- 控制器
- spring 提供的前控制器(实际是一个servlet),作为一个统一入口,由它来分发请求,进入真正的控制器
需要使用 WEB-INF/web.xml 文件配置它的路径
- spring 提供的前控制器(实际是一个servlet),作为一个统一入口,由它来分发请求,进入真正的控制器
<!-- 配置前控制器 (servlet) -->
<servlet>
<servlet-name>aa</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指明 spring 配置文件的位置, 根据它创建 spring容器 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- tomcat 启动时, 就创建和初始化 servlet, 同时创建 spring 容器 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>aa</servlet-name>
<!-- / 用来匹配所有的路径 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
说明:
- 在配置前端控制器的时候,需要我们配置的有contextConfigLocation,为他指定SpringMVC.xml的路径,否则默认加载WEB-INF/[DispatcherServlet的Servlet名字]-servlet.xml
- DispatcherServlet三种拦截方式:
- *.action:可以访问以.action结尾的地址,由DispatcherServlet进行解析。此方法最简单,不会导致静态资源(jpg,js,css)被拦截。
- / :所有访问的地址都由DispatcherServlet进行解析,此方法可以实现REST风格的url,很多互联网类型的应用使用这种方式。但是此方法会导致静态文件(jpg,js,css)被拦截后不能正常显示,所以对静态文件的解析需要配置不让DispatcherServlet进行解析。
- /*:这样配置是不对的,使用这种配置,最重要转发到一个jsp页面时,仍然会由DispatcherServlet解析jsp地址,不能根据jsp页面找到Handler,会报错。
操作:基于注解方式的MVC操作
SpringMVC.xml的配置说明:
<mvc:annotation-driven />
这个配置是开启关于MVC的所有相关注解
比如:《基本上这一个开启,就涵盖了所有的处理器映射器的配置》
<!-- 启用了 与 springmvc 相关的注解
@RestController 控制器注解
@RequestMapping 映射器注解
@ResponseBody JSON字符转换注解
@ExceptionHandler 异常处理注解
...
-->
<mvc:annotation-driven />
是一种简写形式,完全可以手动配置替代这种简写形式,简写形式可以让初学都快速应用默认配置方案。
<mvc:annotation-driven />
会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,是spring MVC为@Controllers分发请求所必须的。
并提供了:
数据绑定支持,
@NumberFormatannotation支持,
@DateTimeFormat支持,
@Valid支持,
读写XML的支持(JAXB),
读写JSON的支持(Jackson)。
后面,我们处理响应ajax请求时,就使用到了对json的支持。
后面,对action写JUnit单元测试时,要从spring IOC容器中取DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,来完成测试,取的时候要知道是<mvc:annotation-driven />这一句注册的这两个bean。
<context:component-scan base-package="com.banban.controller"/>
这个是扫描那些加了controller,service等等的注解的类,加入到容器中去。
<!-- 配置视图的完整路径(前缀 和 后缀) 配置视图解析器-->
<mvc:view-resolvers>
<!-- 前缀 + 视图名 + 后缀 == 完整路径, 再利用请求转发跳转至 jsp -->
<mvc:jsp prefix="/" suffix=".jsp" />
</mvc:view-resolvers>
配置视图解析,当controller完成逻辑后,spring会根据,我们返回或者定义的路径,拼接成完整的url返回。
<!--静态资源(html,图片,js,css) 忽略静态资源路径的过滤-->
<mvc:default-servlet-handler/>
因为拦截器原因,如果默认拦截所有路径,会一起将静态资源拦截,这个注解,就是忽略静态资源的拦截,使其能成功呈现在jsp中。而不会出现静态资源丢失的情况
<!--配置拦截器-->
<mvc:interceptors>
<!-- 某个拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/a"/>
<ref bean="myInterceptor1"/>
</mvc:interceptor>
</mvc:interceptors>
拦截器配置:我们可以自定义有哪些拦截器,以及拦截的路径有哪些
前控制器web.xml配置说明
<!-- 配置前控制器 (servlet) -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指明 spring 配置文件的位置, 根据它创建 spring容器 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- tomcat 启动时, 就创建和初始化 servlet, 同时创建 spring 容器 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<!-- / 用来匹配所有的路径 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
这是MVC的核心配置;
所有的请求与回应都会经过前端控制器。
<!-- 配置字符编码过滤器 -->
<filter>
<filter-name>Coding</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>Coding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这个配置是解决post请求乱码问题