简单配置SpringMVC

  SpringMVC的实现原理是通过Servlet拦截所有URL达到控制目的,所以web.xml的配置是必须的

    ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息,它实现了ServletContextListener接口,在启动容器时,就会执行它实现的方法。

    使用ServletContextListener接口,开发者能够在为客户端提供服务之前向ServletContext中添加任意对象。

  • contextConfigLocation

    Spring的核心就是配置文件,可以说配置文件是Spring中必不可少的东西。而这个参数就是使Web与Spring的配置文件相结合的一个关键配置

    包含了SpringMVC的请求逻辑,Spring用此类拦截Web请求并进行相应的逻辑处理

  <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:applicationContext-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

    <!-- 通过listener 像Servlet容器注册 Web容器启动时 初始化context-param的配置信息。-->

    <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

  在classPath下面建立一个applicationContext-mvc.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: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-4.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"> <!--会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter -->
<mvc:annotation-driven></mvc:annotation-driven> <!-- 批量扫描 注册成Spring的bean -->
<context:component-scan base-package="com.sk.service"></context:component-scan> <!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/"></property>
<property name="suffix" value=".html"></property>
</bean> <!-- 全局的异常处理 -->
<bean class="com.sk.util.CustomExceptionResolver"></bean> </beans>

ContextLoaderListener

  因为ContextLoaderListener实现了 ServletContextListener接口。

  在web.xml配置这个监听器,启动容器时就会默认执行contextInitialized()方法。通过初始化WebApplicationContext实例,装配ApplicationContext的配置信息。

DispatcherServlet

DispatcherServlet有点类似HttpServlet接口中用于转发的接口RequestDispatcher

DispatcherServlet的初始化过程主要是将当前的Servlet类型实例转换为BeanWrapper类型实例,以便使用Spring提供的注入功能进行对应属性的注入。

  下面是API中对DispatcherServlet的解释

  1. 它可以使用任何HandlerMapping实现(预先构建或作为应用程序的一部分提供)来控制请求到处理程序对象的路由。默认是BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping。HandlerMapping对象可以在servlet的应用程序上下文中定义为bean,实现HandlerMapping接口,在出现时覆盖默认的HandlerMapping。HandlerMappings可以提供任何bean名
  2. 它可以使用任何HandlerAdapter;这允许使用任何处理程序接口。默认适配器分别是HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter,用于Spring的HttpRequestHandler和控制器接口。还将注册一个默认的AnnotationMethodHandlerAdapter。HandlerAdapter对象可以作为bean添加到应用程序上下文中,覆盖默认的HandlerAdapter。与HandlerMappings一样,handleradapter可以提供任何bean名称
  3. 可以通过HandlerExceptionResolver指定dispatcher的异常解析策略,例如将某些异常映射到错误页面(也可以以rest形式抛出一个JSON)。默认是annotationmethodhandlertionresolver、ResponseStatusExceptionResolver和DefaultHandlerExceptionResolver。可以通过应用程序上下文覆盖这些HandlerExceptionResolvers。HandlerExceptionResolver可以提供任何bean的名称
  4. 它的视图解析策略可以通过ViewResolver实现指定,将符号视图名称解析为视图对象。默认是InternalResourceViewResolver。可以将ViewResolver对象作为bean添加到应用程序上下文中,覆盖默认的ViewResolver。可以给ViewResolvers赋予任何bean名称

下面分别解释上面三个关键接口

HandlerMapping

当客户端发出Request时DispatcherServlet会将Request提交给HandlerMapping,然后HandlerMapping根据WebApplicationContext(applicationContext-mvc.xml)的配置传回来给相应的Controller(就是Handler)。(利用了HanderAdapter)

handlerMapping的作用就是帮助我们管理URL和处理类之间的映射关系,简单的理解就是将一个或多个URL映射到一个或多个Spring Bean中。 它初始化完成的最重要的两个工作就是:

  • 将URL与handler对应的关系保存在handlerMap集合中
  setUrlMap(Map<String,?> urlMap) 
          Set a Map with URL paths as keys and handler beans (or handler bean names) as values.
  • 前端控制器(DispatcherSerlvet)根据Request中的url去查找Handler, 返回 HandlerExecutionChain对象,而且在这个HandlerExecutionChain对象中将包含用户自定义的多个HandlerInterceptor
    接口中的preHandler和postHandler分别在当前Handler执行前和执行后执行。类似Servlet规范中的Fliter。
  getHandler(HttpServletRequest request) 
          Return a handler and any interceptors for this request. 

工作中常用RequestMappingHandlerMapping去查找Handler(通过Handler的适配器去查找)

HandlerInterceptor

  用户自定义的Interceptor实现HandlerInterceptor,放在HandlerExecutionChain,HandlerExecutionChain中会有多个handlerInterceptor对象。采用的责任链的模式的规则

  前端控制器(DispatcherSerlvet)根据Request中的url去查找Handler之前执行handlerExecutionChain中所有handlerInterceptor拦截器的preHandle()方法,请求之后执行postHandler()。

  处理器前方法采用先注册先执行,处理器后方法采用先注册后执行

  利用HandlerInterceptor我们可以实现简单的权限处理。

HandlerAdapter

  • HandlerAdapter初始化时会将这个HandlerAdapter对象保存在Dispatcher的HandlerAdapters集合中。当SpringMVC将某个URL对应到某个Handler时,将对应的Handler返回。

  作为总控制器的派遣器Servlet通过处理映射得到处理器后,会轮询处理器适配器模块,查找能够处理当前HTTP请求的处理器适配器的实现。

  处理器适配器模块根据处理映射返回的处理器类型,列如简单的控制器类型,注解控制器类型,或者远程调用处理器类型,来选择一个适当的处理器适配器的实现,从而适配当前的HTTP请求。

   SpringMVC HandlerAdapter机制可以让Handler的实现更加灵活 可以参考适配器的设计模式

  HandlerAdaptor接口的handle方法

  public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {
    return ((Controller)handler).handleRequest(request, response);
  }

  handle(HttpServletRequest request, HttpServletResponse response, Object handler) 
          Use the given handler to handle this request.

对于获取适配器的逻辑无非是遍历所有的适配器,返回合适的适配器并返回它,而某个适配器是否适用当前的Handler逻辑被封装在具体的适配器当中。

工作中常用的SimpleControllerHandlerAdapter此适配器能执行实现Controller接口的handler。

Resolver

HandlerExceptionResolver

  当后台捕捉到的业务异常时,可以自定义的异常,然后通过实现HandlerExceptionResolver(处理异常解析器)来抛出自定义异常的信息

  • 自定义一个异常
public class CustomException extends Exception{  public String msg;
public CustomException(String msg) {
super(msg);
this.msg=msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}

Spring的主要工作就是把逻辑引导至HandlerExceptionResolver的resolveException()方法。

如果方法返回了null,则Spring会继续寻找其他实现了HandlerExceptionResolver接口的Bean,直到所有Bean都执行完成,或者返回了一个ModelAndView对象。

public class CustomExceptionResolver implements HandlerExceptionResolver{

    @Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception exception) {
//handler 就是处理器适配器执行的Handler对象
response.setContentType("application/json;charset=UTF-8");
try {
PrintWriter writer = response.getWriter();
Map<String, Object> map = new HashMap<String, Object>();
map.put("success", false);
// 为安全起见,只有业务异常我们对前端可见,否则统一归为系统异常
if (exception instanceof CustomException) {
map.put("errorMsg", exception.getMessage());
} else {
map.put("errorMsg", "系统异常!");
}
writer.write(JSON.toJSONString(map));
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

在这里,我们不想让错误跳转到一个错误页面,所以 return null。(以JSON的数据格式 通过response write到前端)接到错误信息想怎么去做,前端自行处理。

ViewResolver

  视图解析器  将把逻辑视图名解析为具体的View(我比较崇尚rest风格,和前端只是json交互 跳转页面交给前端控制而不是后台)

  应用程序中,我们的页面经常统一放在某个包下(/WEB-INF/page/),而且统一以某个名字结尾(.jsp或者.html),会统  实现类UrlBasedViewResolver:其中有两个方法

      setSuffix 设置在构建URL时附加到视图名称的后缀。

   setPreffix 在构建URL时,设置前缀以查看名称。

  通过这两个方法,我们在return一个字符串时,可以把页面的前缀和后缀省略,简化了编码。

注:MappingJackson2JsonView视图不是逻辑视图,不需要ViewResolver去定位视图,它会将数据模型渲染为Json数据集展示给用户查看。

SessionLocaleResolver

将国际化的信息设置在Session中,这样就能读取Session中的信息去确定用户的国际化区域。

这是最常用让用户选择国际化的手段

MappingJacksonHttpMessageConverter

SpringMVC进入控制器方法前,当遇到@ResponseBody后,处理器就会记录这个方法的响应类型为JSON数据集。

当执行完控制器返回后,处理器就会启用结果解析器(ResultResolver)去解析这个结果。

它会轮询注册给SpringMVC的HttPMessageConverter接口的实现类。因为MappingJacksonHttpMessageConverter这个实现类已经被SpringMVC注册,

加上SpringMVC将控制器的结果类型标明为JSON。当然有时候会轮询不到匹配的HttpMessageConverter,那么它就会交由SpringMVC后续流程去处理。

如果控制器返回结果被MappingJacksonHttpMessageConverter进行了转换,那么后续的模型和视图(ModelAndView)就返回null,这样视图解析器和视图渲染就不在会被执行

最新文章

  1. django manytomany
  2. An invalid form control with name=&#39;&#39; is not focusable.
  3. java 19 -14 File类的判断并输出案例
  4. winform 多线程中ShowDialog()步骤无效的解决办法
  5. [LeetCode]题解(python):109-Convert Sorted List to Binary Search Tree
  6. Java多线程之synchronized(三)
  7. 【&#9733;】Web精彩实战之&lt;智能迷宫&gt;
  8. 新概念英语(1-51)A pleasant climate
  9. MySQL如何修改密码
  10. ZooKeeper Dynamic Reconfiguration (dynamicConfigFile) ZooKeeper动态配置
  11. oracle odbc mysql 字段不全
  12. HttpClient后台post 请求webapi
  13. mysql left join 查询
  14. RESET MASTER和RESET SLAVE使用场景和说明
  15. 20155211实验2 Windows口令破解
  16. ASP.NET 中 POST 数据并跳转页面(译自 Redirect and POST in ASP.NET)
  17. C#操作mysql数据库,往mysql读取或者写入数据
  18. netstat命令的用法
  19. centos7下安装mysql8.0.12及设置权限
  20. PAT 天梯赛 L1-002 【递归】

热门文章

  1. 如何通过SSH工具(SecureCRT、XShell)连接Vmware虚拟机中的Linux(CentOS7)
  2. 识别手机浏览器代码【C#和JS两种语言】
  3. Qt跨平台开发Wince5.0和Android程序
  4. Python并发解决方案
  5. mybatis学习笔记1.零碎记录
  6. idea实现热部署并且开启自动编译
  7. ArrayAdapter构造方法中的textViewResourseId
  8. 【转】TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端)、UDP客户端
  9. es6数值
  10. Lambda表达式按字段名字排序