SpringMVC 知识点整理
来源:互联网 发布:测试网络丢包率软件 编辑:程序博客网 时间:2024/05/14 06:27
先放两张图,是网上找的。下面的文章很多都是其他地方直接copy过来的,尤其是这位仁兄(http://elf8848.iteye.com/blog/875830/),在此感谢,为了加深记忆。
1.DispatcherServlet
使用Spring MVC,配置DispatcherServlet是第一步。
DispatcherServlet是一个Servlet,所以可以配置多个DispatcherServlet。
DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自已定义,把拦截下来的请求,依据某某规则分发到目标Controller(我们写的Action)来处理。
<web-app> <servlet> <servlet-name>example</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>example</servlet-name> <url-pattern>*.form</url-pattern> </servlet-mapping> </web-app>
example这个Servlet的名字是example,可以有多个DispatcherServlet,是通过名字来区分的。每一个DispatcherServlet有自己的WebApplicationContext上下文对象。
在DispatcherServlet的初始化过程中,框架会在web应用的 WEB-INF文件夹下寻找名为[servlet-name]-servlet.xml 的配置文件,生成文件中定义的bean。
第二种写法:
<servlet> <servlet-name>springMVC</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>springMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
classpath*:/springMVC.xml 这段写不写有四种方式:
1、不写,使用默认值:/WEB-INF/-servlet.xml
2、/WEB-INF/classes/springMVC.xml
3、classpath*:springMVC-mvc.xml
4、多个值用逗号分隔
Servlet拦截匹配规则可以自已定义,拦截哪种URL合适?
@RequestMapping的用法如下:
当映射为@RequestMapping(“/user/add”)时,为例:
例子一:
@RequestMapping(value="/departments") public String simplePattern(){ System.out.println("simplePattern method was called"); return "someResult"; }
当访问//localhost/xxx/departments时,会用到。
例子二:
@RequestMapping(value="/departments") public String findDepatment( @RequestParam("departmentId") String departmentId){ System.out.println("Find department with ID: " + departmentId); return "someResult"; }
当访问//localhost/xxx/departments?departmentId=00时用到
例子三:
@RequestMapping(value="/departments/{departmentId}") public String findDepatment(@PathVariable String departmentId){ System.out.println("Find department with ID: " + departmentId); return "someResult"; }
当访问//localhost/xxx/departments/23时
例子四:
@Controller @RequestMapping ( "/test/{variable1}" ) public class MyController { @RequestMapping ( "/departments/{variable2}" ) public ModelAndView showView( @PathVariable String variable1, @PathVariable ( "variable2" ) int variable2) { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName( "viewName" ); modelAndView.addObject( " 需要放到 model 中的属性名称 " , " 对应的属性值,它是一个对象 " ); return modelAndView; } }
当访问//localhost/xxx/test/33/departments/23时
2.WebApplicationContext上下文
Spring会创建一个WebApplicationContext上下文,称为父上下文(父容器) ,保存在 ServletContext中,key是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值。
可以使用Spring提供的工具类取出上下文对象:WebApplicationContextUtils.getWebApplicationContext(ServletContext);
DispatcherServlet是一个Servlet,可以同时配置多个,每个 DispatcherServlet有一个自己的上下文对象(WebApplicationContext),称为子上下文(子容器),子上下文可以访问父上下文中的内容,但父上下文不能访问子上下文中的内容。 它也保存在 ServletContext中,key是”org.springframework.web.servlet.FrameworkServlet.CONTEXT”+Servlet名称。当一个Request对象产生时,会把这个子上下文对象(WebApplicationContext)保存在Request对象中,key是DispatcherServlet.class.getName() + “.CONTEXT”。
可以使用工具类取出上下文对象:RequestContextUtils.getWebApplicationContext(request);
说明 :Spring 并没有限制我们,必须使用父子上下文。我们可以自己决定如何使用。
方案一,传统型:
父上下文容器中保存数据源、服务层、DAO层、事务的Bean。
子上下文容器中保存Mvc相关的Action的Bean.
事务控制在服务层。
由于父上下文容器不能访问子上下文容器中内容,事务的Bean在父上下文容器中,无法访问子上下文容器中内容,就无法对子上下文容器中Action进行AOP(事务)。
当然,做为“传统型”方案,也没有必要这要做。
方案二,激进型:
Java世界的“面向接口编程”的思想是正确的,但在增删改查为主业务的系统里,Dao层接口,Dao层实现类,Service层接口,Service层实现类,Action父类,Action。再加上众多的O(vo\po\bo)和jsp页面。写一个小功能 7、8个类就写出来了。 开发者说我就是想接点私活儿,和PHP,ASP抢抢饭碗,但我又是Java程序员。最好的结果是大项目能做好,小项目能做快。所以“激进型”方案就出现了—–没有接口、没有Service层、还可以没有众多的O(vo\po\bo)。那没有Service层事务控制在哪一层?只好上升的Action层。
本文不想说这是不是正确的思想,我想说的是Spring不会限制你这样做。
由于有了父子上下文,你将无法实现这一目标。解决方案是只使用子上下文容器,不要父上下文容器 。所以数据源、服务层、DAO层、事务的Bean、Action的Bean都放在子上下文容器中。就可以实现了,事务(注解事务)就正常工作了。这样才够激进。
总结:不使用listener监听器来加载spring的配置文件,只使用DispatcherServlet来加载spring的配置,不要父子上下文,只使用一个DispatcherServlet,事情就简单了,什么麻烦事儿也没有了。*
3. 一个典型的servlet.xml结构
<?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:tx="http://www.springframework.org/schema/tx" 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-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <!-- 自动扫描的包名 包括如下常见注解 @Controller 声明Action组件 @Service 声明Service组件 @Service("myMovieLister") @Repository 声明Dao组件 @Component 泛指组件, 当不好归类时. @RequestMapping("/menu") 请求映射 @Resource 用于注入,( j2ee提供的 ) 默认按名称装配,@Resource(name="beanName") @Autowired 用于注入,(srping提供的) 默认按类型装配 @Transactional( rollbackFor={Exception.class}) 事务管理 @ResponseBody @Scope("prototype") 设定bean的作用域--> <context:component-scan base-package="com.app,com.core,JUnit4" ></context:component-scan> <!-- 默认的注解映射的支持 会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,是spring MVC为@Controllers分发请求所必须的。并提供了:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB),读写JSON的支持(Jackson)。--> <mvc:annotation-driven /> <!-- 视图解释类 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/><!--可为空,方便实现自已的依据扩展名来选择视图解释类的逻辑 --> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> </bean> <!-- 拦截器,可以有多个拦截器 --> <mvc:interceptors> <bean class="com.core.mvc.MyInteceptor" /> </mvc:interceptors> <!-- 对静态资源文件的访问 方案一 (二选一) --> <mvc:default-servlet-handler/> <!-- 对静态资源文件的访问 方案二 (二选一)--> <mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/> <!-- 匹配URL /images/** 的URL被当做静态资源,由Spring读出到内存中再响应http。--> <mvc:resources mapping="/js/**" location="/js/" cache-period="31556926"/> <mvc:resources mapping="/css/**" location="/css/" cache-period="31556926"/> </beans>
4. 如何让静态资源请求不被拦截
如果你的DispatcherServlet拦截”/”,为了实现REST风格,拦截了所有的请求,那么同时对.js,.jpg等静态文件的访问也就被拦截了。
方案一:
解决的办法是在web.xml中加入
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.jpg</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.css</url-pattern> </servlet-mapping>
在dispatchServlet前面,让tomcat自行去先过滤掉。
Tomcat, Jetty, JBoss, and GlassFish 自带的默认Servlet的名字 – “default”
Google App Engine 自带的 默认Servlet的名字 – “_ah_default”
Resin 自带的 默认Servlet的名字 – “resin-file”
WebLogic 自带的 默认Servlet的名字 – “FileServlet”
WebSphere 自带的 默认Servlet的名字 – “SimpleFileServlet”
方案二: 在spring3.0.4以后版本提供了mvc:resources
方案三 ,使用 <mvc:default-servlet-handler/>
会把”/**” url,注册到SimpleUrlHandlerMapping的urlMap中,把对静态资源的访问由HandlerMapping转到org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler处理并返回.
DefaultServletHttpRequestHandler使用就是各个Servlet容器自己的默认Servlet.
方案2的优先级要比方案3来的高,所以一个请求如果是请求静态的资源,是按优先级来的。
OK.看完了servlet.xml,我们来看下Controller这个类
5.Controller如何定义及含义
Controller 负责处理由DispatcherServlet 分发的请求,当一个请求到来时,spring怎么知道该用哪个函数去处理呢?
@Controller public class MyController { @RequestMapping ( "/showView" ) public ModelAndView showView() { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName( "viewName" ); modelAndView.addObject( " 需要放到 model 中的属性名称 " , " 对应的属性值,它是一个对象 " ); return modelAndView; } }
如上就是一个典型的Controller定义,spring会扫描加了@Controller前缀的类,并且,如果他的函数中有@RequestMapping字样,则会认为这是个处理类。
那么如何让spring去做这个动作?两个办法,一个是用之前说的context:component-scan标签。
第二种就是显式定义
<bean class="com.host.app.web.controller.MyController"/>
6. Spring中的拦截器
Spring为我们提供了:
org.springframework.web.servlet.HandlerInterceptor接口,
org.springframework.web.servlet.handler.HandlerInterceptorAdapter适配器,
实现这个接口或继承此类,可以非常方便的实现自己的拦截器。
有以下三个方法:
Action之前执行:
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler);
生成视图之前执行
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView);
最后执行,可用于释放资源
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
分别实现预处理、后处理(调用了Service并返回ModelAndView,但未进行页面渲染)、返回处理(已经渲染了页面)
在preHandle中,可以进行编码、安全控制等处理;
在postHandle中,有机会修改ModelAndView;
在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。
参数中的Object handler是下一个拦截器。
拦截器的定义有几种方式:
第一种,什么都栏,
<mvc:interceptors> <bean class="com.app.mvc.MyInteceptor" /> </mvc:interceptors>
第二种,拦一部分url匹配的
<mvc:interceptors > <mvc:interceptor> <mvc:mapping path="/user/*" /> <!-- /user/* --> <bean class="com.mvc.MyInteceptor"></bean> </mvc:interceptor> </mvc:interceptors>
第三种,指定我们自己的拦截器,前提是没有事先使用了< mvc:annotation-driven />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="interceptors"> <list> <bean class="com.mvc.MyInteceptor"></bean> </list> </property> </bean>
7,异常处理
<!-- 总错误处理--> <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="defaultErrorView"> <value>/error/error</value> </property> <property name="defaultStatusCode"> <value>500</value> </property> <property name="warnLogCategory"> <value>org.springframework.web.servlet.handler.SimpleMappingExceptionResolver</value> </property> </bean>
这里主要的类是SimpleMappingExceptionResolver类,和他的父类AbstractHandlerExceptionResolver类。
具体可以配置哪些属性,我是通过查看源码知道的。
你也可以实现HandlerExceptionResolver接口,写一个自己的异常处理程序。spring的扩展性是很好的。
通过SimpleMappingExceptionResolver我们可以将不同的异常映射到不同的jsp页面(通过exceptionMappings属性的配置)。
同时我们也可以为所有的异常指定一个默认的异常提示页面(通过defaultErrorView属性的配置),如果所抛出的异常在exceptionMappings中没有对应的映射,则Spring将用此默认配置显示异常信息。
注意这里配置的异常显示界面均仅包括主文件名,至于文件路径和后缀已经在viewResolver中指定。如/error/error表示/error/error.jsp
8.如何把全局异常记录到日志中
在前的配置中,其中有一个属性warnLogCategory,值是“SimpleMappingExceptionResolver类的全限定名”。我是在SimpleMappingExceptionResolver类父类AbstractHandlerExceptionResolver类中找到这个属性的。查看源码后得知:如果warnLogCategory不为空,spring就会使用apache的org.apache.commons.logging.Log日志工具,记录这个异常,级别是warn。
值:“org.springframework.web.servlet.handler.SimpleMappingExceptionResolver”,是“SimpleMappingExceptionResolver类的全限定名”。这个值不是随便写的。 因为我在log4j的配置文件中还要加入log4j.logger.org.springframework.web.servlet.handler.SimpleMappingExceptionResolver=WARN,保证这个级别是warn的日志一定会被记录,即使log4j的根日志级别是ERROR。
9.转发与重定向
可以通过redirect/forward:url方式转到另一个Action进行连续的处理。可以通过redirect:url 防止表单重复提交 。写法如下:return "forward:/order/add";return "redirect:/index.jsp";
10.处理ajax请求
1、引入下面两个jar包,我用的是1.7.2,好像1.4.2版本以上都可以,下载地址: http://wiki.fasterxml.com/JacksonDownload
jackson-core-asl-1.7.2.jar
jackson-mapper-asl-1.7.2.jar
2、spring的配置文件中要有这一行,才能使用到spring内置支持的json转换。如果你手工把POJO转成json就可以不须要使用spring内置支持的json转换。
3、使用@ResponseBody注解, 表示该方法的返回结果直接写入HTTP response body中
/** * ajax测试 * http://127.0.0.1/mvc/order/ajax */ @RequestMapping("/ajax") @ResponseBody public Object ajax(HttpServletRequest request){ List<String> list=new ArrayList<String>(); list.add("电视"); nbsp; list.add("洗衣机"); list.add("冰箱"); list.add("电脑"); list.add("汽车"); list.add("空调"); list.add("自行车"); list.add("饮水机"); list.add("热水器"); return list; }
11.可用的ViewResolver实现类(留待补充)
12.ModelAndView详解
ModelAndView, 顾名思义,代表了MVC Web程序中Model与View的对象,不过它只是方便一次返回这两个对象的holder,Model与View两者仍是分离的概念。
最简单的ModelAndView是持有View的名称返回,之后View名称被view resolver,也就是实作org.springframework.web.servlet.View接口的实例解析,例如 InternalResourceView或JstlView等等:
ModelAndView(String viewName)
如果要返回Model对象,则可以使用Map来收集这些Model对象,然后设定给ModelAndView,使用下面这个版本的ModelAndView:
ModelAndView(String viewName, Map model)
Map对象中设定好key与value值,之后可以在视图中取出,如果只是要返回一个Model对象,则可以使用下面这个ModelAndView版本:
ModelAndView(String viewName, String modelName, Object modelObject)
藉由modelName,可以在视图中取出Model并显示。
ModelAndView类别提供实作View接口的对象来作View的参数:
ModelAndView(View view)
ModelAndView(View view, Map model)
ModelAndView(View view, String modelName, Object modelObject)
- SpringMVC 知识点整理
- springmvc知识点整理
- 关于springmvc的知识点整理
- springMVC 知识点整理PART 1(基本概念)
- SpringMVC知识点
- SpringMvc知识点
- SpringMVC知识点
- springMVC 知识点
- springmvc知识点
- 知识点整理
- 知识点整理
- 知识点整理
- 整理知识点
- SpringMvc整理
- springMVC 知识点整理PART 2(控制器与视图之间数据的)
- springMVC知识点总结
- SpringMVC知识点小结
- SpringMVC-基础知识点(一)
- 对二维数组某一个字段相同的数组合并起来
- 单个应用流量统计实现和核对
- ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
- c/c++中指针与二维数组的关系demo程序
- 怎么查询端口被占用
- SpringMVC 知识点整理
- 单链表逆置
- Mac OS X中配置Apache
- Android开发之RecyclerView的不同position加载不同View详解
- 对C++的一点抱怨
- Chrome控制台使用小窍门
- linux 用freetds 连接mssql 2008
- 关于SQL中CTE(公用表表达式)(Common Table Expression)的总结
- QQ空间说说页面设计 练习