例外処理
Spring MVCは、ハンドラーマッピング、データバインディング、ターゲットメソッドの実行時に発生する例外など、HandlerExceptionResolverを介してプログラム例外を処理します。
SpringMVCが提供するHandlerExceptionResolver
の実装クラス実装クラスの1つを見てみましょう。
DefaultHandlerExceptionResolver
内部の処理メソッドを見てください。戻り値はModelAndViewです
。mvc構成ファイルで構成されている例外処理をカスタマイズすることもできます。
<!-- prop的key写异常类型的全限类名,prop的值就是一个视图名称,出现对应异常要跳转的页面
而且会将异常信息默认放在request作用域里面,在页面可以${
exception}进行取值
-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.NullPointerException">error</prop>
</props>
</property>
</bean>
プロセスを実行する
1) 用户向服务器发送请求,请求被SpringMVC 前端控制器 DispatcherServlet捕获;
2) DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI):
判断请求URI对应的映射
① 不存在:
再判断是否配置了mvc:default-servlet-handler:
如果没配置,则控制台报映射查找不到,客户端展示404错误
如果有配置,则执行目标资源(一般为静态资源,如:JS,CSS,HTML)
② 存在:
执行下面流程
3) 根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
4) DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。
5) 如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法【正向】
6) 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
① HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
② 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
③ 数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
④ 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
7) Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
8) 此时将开始执行拦截器的postHandle(...)方法【逆向】
9) 根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet,根据Model和View,来渲染视图
10) 在返回给客户端时需要执行拦截器的AfterCompletion方法【逆向】
11) 将渲染结果返回给客户端
SpringとSpringMVCの統合
統合の理由
統合されていない場合、発生する問題:
統合されて
いない場合、これを管理するためにSpringが管理する必要のあるすべてのコンポーネントがspringmvcに渡されることは不可能ではありませんが、この方法で、springmvcは、一般的に使用されるSpringトランザクション、データソース、mybatisなどの多くのものを管理します。この種のspringmvcのオブジェクトは乱雑すぎるため、統合されています
springmvcに統合する場所
mvcが制御層を書き込むとき、サービス層の物を自動的に組み立てる必要があり、サービス層とdao層の物はスプリングコンテナによって管理されるため、プロジェクト全体の開始時にスプリングを統合してロードする必要があるという結論になります。さて、
プロジェクトの開始時にロードする方法は何ですか?
Webのロード順序は次のとおりです。最後に最初の訪問でサーブレットがロードされ、プロジェクトの開始時に最後のサーブレットがロードされます。最初の1つがフィルター、最初の1つがリスナーである
ため、フィルター内でとリスナーの
どちらかを選択しますが、フィルターはアクセスされるたびに新しいオブジェクトを作成します
が、Springコンテナーはそれほど多くを作成する必要はなく、1つだけ作成する必要があるため、プロジェクトの開始時にservletContextでリスナー(リスニングイベント)を選択します。作成時に、servletContextのライフサイクルを監視するリスナーを作成し、作成時にスプリングコンテナを作成します。
たとえば、
package com.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringListener implements ServletContextListener
{
public SpringListener()
{
}
public void contextDestroyed(ServletContextEvent arg0)
{
}
public void contextInitialized(ServletContextEvent sce)
{
ApplicationContext ac=new ClassPathXmlApplicationContext("spring.xml");
/*
* 有时候我们的bean不是在配置文件里面配置好就行,虽然会自动装配
* 但是有时候我们还需要在手动获得bean对象来操作
* 所以将ac放在request作用域里面,就能获取了
*/
ServletContext servletContext = sce.getServletContext();
servletContext.setAttribute("ac", ac);
}
}
次に、web.xmlで構成します
<!--
如果只加了listener这个标签加载别人写好的ContextLoaderListener
那么就会去默认的位置去加载,就是WEB-INF下面的applicationContext.xml
那么想配置contextConfigLocation这个参数,可以利用<context-param>标签
这个是servletcontext的参数设置,项目启动时就会加载这个标签,是最先加载的
-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
ヒントを使用して作成することもできます
<!-- needed for ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
<!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>