SpringMVC学习笔记

本文主要探讨了Spring MVC中三种常见的HandlerMapping实现:BeanNameUrlHandlerMapping、SimpleUrlHandlerMapping和ControllerClassNameHandlerMapping,详细解释了它们的工作原理和使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

SpringMVC框架是一个 MVC框架,通过实现Model-View-Controller模式来很好的将数据、业务与展现进行分离。

SpringMVC的设计是围绕 DispatcherServlet展开, DispatcherServlet负责请求派发到特定的 handler

通过可配置的 HandlerMapping(映射处理器)controller(控制器)ViewResolver(视图解析器)进行MVC的模式的体现

SpringMVC的C层框架的核心是 DispatcherServlet,它的作用是将 请求分发 给不同的 后端处理器(Controller)

SpringMVC的C层框架使用了后端控制器、映射处理器、视图解析器来共同完成C层框架的主要工作。并且真正的把业务层处理的 数据结果相应的视图拼成一个对象,即 ModelAndView 对象。


原理

1、客户端向服务器发送 请求,被Spring前端控制器 DispatcherServlet捕获
2、 DispatcherServlet 解析 URL,得到 URI(资源标识符),根据URI调用 HandlerMapping 来获得Handler配置的对象( Handler对象 以及 对应的拦截器),以 HandlerExecutionChain对象的形式返回
3、 DispatherServlet 根据 Handler选择 HandlerAdapter。执行对应的 Controller。(如果有拦截器,则先执行拦截器的preHandler() 方法)
4、提取Request中的模型数据, 将Handler填入参数,开始 执行Handler(Controller) ,此时根据配置先执行如下工作:
      ①HttpMessageConveter:将请求消息(Json、xml等)转换为一个对象,将对象转换为指定的响应消息
      ②数据转换:对请求消息进行数据转换。如String转Integer、Double等
      ③数据格式化:如将字符串转换成格式化数字或格式化日期
      ④数据验证:验证数据的有效性(长度、格式),验证结果存储到BindingResult或Error中。
5、 Handler执行完成后,向 DispatcherServlet返回一个 ModelAndView对象
6、根据返回的 ModelAndView,选择合适 ViewResolver (已注册到spring的ViewResolver-即配置在xml文件中的viewResolver) 返回给 DispatcherServlet
7、 ViewResolver 结合 ModelView ,来 渲染视图
8、将渲染结果返回客户端
                           

处理器 映射 HandlerMapping

spring MVC中,映射处理器 HandlerMapping可以把web请求映射到正确的处理器上,常用的有
  • BeanNameUrlHandlerMapping(默认) 官方推荐使用
  • SimpleUrlHandlerMapping
  • ControllerClassNameHandlerMapping


1 . BeanNameUrlHandlerMapping
       DispatcherServlet会查找spring容器中 和请求的url同名的bean不需要配置,spring在找不到handlerMapping的情况下会使用BeanNameUrlHandlerMapping。

例如请求url为:     
localhost:8080/SpringMVCStudy/index.html
spring配置为:  
<!-- 配置handlerMapping -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">     <!--可以不配置-->
<!-- 配置controlller -->
<bean name="index.html" class="com.mj.TestController">


2 . SimpleUrlHandlerMapping
        SimpleUrlHandlerMapping可以让开发者 自由的配置请求的 url 和 handler的映射关系          

例如spring配置为:
<!-- 配置HandlerMapping -->
<bean id="simplerUrlHandlerMapping" class="com.springframework.web.servlet.handler.SimplerUrlHandlerMapping">
  <list>                                                 <!-- 配置多个interceptor -->
    <ref bean="interceptor1" />
    <ref bean="interceptor2" />
  </list>
  <property name="mappings">
    <props>
      <prop key="/index">indexController</prop>          <!-- 为不同的url配置不同的handler -->
    </props>
  </property>
  <property name="order" value="1"/>
</bean>

<!-- 配置controller -->
<bean id="indexController" class="com.springframework.web.servlet.mvc.ParameterizableViewController">
     <property name="viewName" value="index"/>
</bean>
请求的url就可以为:
localhost:8080/SpringMVCStudy/index

3 . ControllerClassNameHandlerMapping
       ControllerClassNameHandlerMapping 只要我们的Controller的 命名方式是以 XXXController的方式命名,则将控制器类名的 Controller后缀删除转换成小写之后作为请求url的前缀
例如spring配置为:
<bean id="controllerClassNameHandlerMapping" class="org.springframework.web.servlet.handler.ControllerClassNameHandlerMapping" />     
如果是普通的Controller,则映射规则为
localhost:8080/SpringMVCStudy/home           // 映射到 HomeController
localhost:8080/SpringMVCStudy/helloworld     // 映射到 HelloWorldController
如果是MultiActionController,则映射规则为
localhost:8080/SpringMVCStudy /userinfo/valid          //映射到 UserInfoControllervalid 方法


控制器  Controller 

1 . AbstractController
2 . MultiActionController
3 . SimpleFormController

1 . AbstractController 

属性
/** Set of supported HTTP methods */
private Set<String>  supportedMethods;

private boolean requireSession = false;

/** Use HTTP 1.0 expires header? */
private boolean useExpiresHeader = true;

/** Use HTTP 1.1 cache-control header? */
private boolean useCacheControlHeader = true;

/** Use HTTP 1.1 cache-control header value "no-store"? */
private boolean useCacheControlNoStore = true;

private int cacheSeconds = -1;

要继承AbstractController,则需要实现 handleRequest方法

public ModelAndView handleRequest( HttpServletRequest request, HttpServletResponse response){
     ModelAndView mav = new ModelAndView();        //返回值是一个ModelAndView对象
     mav.setViewName("dictionary/index.html");     //设置返回的视图文件(相对于Servlet路径)
     mav.addObject("username","Michael");          //设置返回的对象
     mav.addAllObjects(Map modelMap);               //设置返回的对象map
     return mav;     
}

2 . MultiActionController
     MutilActionController 控制器将 多个请求处理方法合并在一个处理器中,可以把相关的功能组合在一起
      方法一: 让自定义的控制器继承 MultiActionController
public class MyMultiActionController extends MultiActionController{
     public ModelAndView method1(HttpServletRequest request,HttpServletResponse response){}
     public ModelAndView method2(HttpServletRequest request,HttpServletResponse response){}
}         
配置参数 MethodNameResolver 进行方法名的调用
① InternalPathMethodNameResolver
<!-- 配置Controller -->
<bean id= "multiActionController" class ="com.springmvc.controller.MyMultiActionController">
  <property name ="methodNameResolver">
     <bean class ="org.springframework.web.servlet.mvc.multiaction. InternalPathMethodNameResolver">
     </bean>
  </property>
</bean>

访问的url为: localhost:8080/SpringMVCStudy /multi/method1     //访问MyMultiActionController的method1方法
             localhost:8080/SpringMVCStudy /multi/method2     //访问MyMultiActionController的method2方法          
②ParameterMethodNameResolver

<!-- 配置Controller -->
<bean id= "multiActionController" class ="com.springmvc.controller.MyMultiActionController">
  <property name ="methodNameResolver">
     <bean class ="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">     
        <property name="paramName" value="method" />     <!-- value代表方法的参数  -->
     </bean>
  </property>
</bean>
访问的url为: localhost:8080/SpringMVCStudy/multi/xxx.action?method=index     //只需要method为上面配置的value
            localhost:8080/SpringMVCStudy/multi/xxx.action?method=hello     

          ③PropertiesMethodNameResolver
                不常用,必须与SimpleUrlHandlerMapping配合使用,一个定位controller,一个定位method
     方法二 :  使用代理对象;不用继承MultiActionController类,定义MultiActionController的 delegate属性即可
<!--  配置包含多方法的controller -->
<bean id=" multiMethodController" class="com.springmvc.controller.MultiMethodController">    //自己定义的
</bean>

<!--  配置代理controller对象  -->
<bean id="proxyController" class="org.springframework.web.servlet.mvc.multiaction.MultiActionController">
   <property name="methodNameResolver">     //配置methodName解析器
      <bean class ="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver">
      </bean>
   </property>
    <property name="delegate">               //配置delegate属性,指向自定义的多方法的controller
     <ref bean="multiMethodController" />
   </property>
</bean>


视图解析器  ViewResolver

在SpringMVC中可以同时 定义多个ViewResolver 视图解析器,然后会组成一个 ViewResolver链,当Controller处理器方法返回一个逻辑视图名称后,ViewResolver链将根据其中ViewResolver的 优先级来进行处理。所有的ViewResolver实现了Ordered接口,在ViewResolver通过 order属性来制定顺序,值越小,优先级越高。

InternalResourceViewResolver 可以 解析所有的视图,永远返回一个 非空的View对象,一定要 放在ViewResolver链的最后

1 . InternalResourceViewResovler     
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
     <property name="prefix" value="/WEB-INF/jsp" />     //前缀
     <property name="suffix" value=".jsp" />             //后缀
</bean>

例如: Controller返回一个ViewName为 index 的 ModelAndView 对象
     则视图解析器将根据配置的前缀后后缀寻找到 /WEB-INF/jsp/index.jsp     //根据配置的前缀和后缀拼成

2 . AbstractCachingViewResolver

3 . UrlBasedViewResolver

4 . XmlViewResolver

5 . BeanNameViewResolver

6 . ResourceBundleViewResolver

7 . FreeMarkerViewResolver

8 . VolocityViewResolver




基于注解的SpringMVC


-- Spring可已通过 @Controller 注解自动发现你的控制器类以及 @RequestMapping 注解中的请求映射

1 . 免去了在Bean配置文件中的配置,
2 . 控制器和处理程序方法在访问上下文资源(请求参数、模型属性、会话属性)也会更加灵活

1 . 注解配置


需要引入mvc命名空间
<mvc:annotation-driven />     //自动注册RequestMappingHandlerMapping 与 RequestMappingHandlerAdapter
     -RequestMappingHandlerMapping  匹配HandlerMapping的关系
     -RequestMappingHandlerAdapter  调用method前对参数进行处理
<context:component-scan base-package="com.mj.controller" />     //扫描包中的注解.

2 .  具体使用

2.1 @Controller 
      @Controller对应的是 后端控制器(Controller)的Bean,使用注解@Controller标记的Bean 不需要继承SpringMVC框架提供的类或实现接口, 一切使用了@Controller标记的类都是Spring容器管理的Controller,此时在Spring容器中会存在一个名字为首字母小写的控制器。如果指定value值,则使用value值做bean的名字
       
      对于一个普通的POJO(Bean),只有@Controller注解时,只是向spring容器申明了它是一个 Controller,但此时 并不具有真正controller的功能。真正让其具有SpringMVC Controller功能的是@RequestMapping注解


2.2 @RequestMapping
      @RequestMapping请求路径映射
          ① 标注在类处:    将Controller与特定的请求关联起来
          ② 标注在方法处: 对请求进行进一步的分流(分配到不同的方法上)
      参数:
          value:    指定请求的实际url
          method:指定请求的method类型,GET,POST等 (RequestMethod.POST)
          params: 设置参数必须包含的内容,才会处理该方法
          headers:设置请求头必须包含的内容
          consumes : 指定请求的提交内容(Content-Type) 例如 : application/json , text/html 
          produces :   指定返回的内容类型 例如: text/plain
      方法的返回值可以为多种类型
     @RequestMapping支持的 Ant风格和带{xxx}占位符的URL:

/user/*/login     :   匹配/user/aaa/login, /user/任意字符/login等
/user/**/login    :   匹配/user/login, /user/aaa/bbb/login等
/user/login??     :   匹配/user/loginAA , /user/loginbb 等
/user/{userId}    :   匹配 /user/123 , /user/234等
/user/**/{userId} :   匹配/user/aaa/bbb/123 , /user/aaa/234等


2.3 @PathVariable
     @PathVariable 标记为请求路径 变量,即在url中的 参数的标记
         ① 在RequestMapping中使用 { }包含变量名
         ② 在方法的参数中,在对应的变量前注解 @PathVariable
         ③ 若两个参数不同名,则将RequestMapping中的变量名赋给PathVariable: @PathVariable("xxx");

2.4 @RequestParam 
     @RequestParam也是用来传递参数的,但是是从 request 的参数里取值,
         相当于 request.getParameter("参数名")的方法,取值规则和@PathVariable一样

以 2.1  2.2  2.3 2.4共同举例

@Controller                                 //为类注解@Controller
@RequestMapping("/blog")                    //为类注解@RequestMapping,指定请求为/blog
public class AnnotationController{          //普通POJO
     
     
      /* 最普通的注解方式 */
      @RequestMapping("index")               //为方法注解RequestMapping,指定请求方法url为/index
     public String index(HttpServletRequest request,HttpServletResponse response){
          ....
          return "index"; 
     }
     
      /* 带有参数的注解,使用PathVariable */
      @RequestMapping("/detail/{name}")        //为方法注解RequestMapping,并带有参数id,指定请求方法为/detail/
     public String detail( @PathVariable String name){          //为方法参数注解@PathVariable,对应url参数
          ...
          return "detail";    
     }  
     
      /* 带有参数注解,使用PathVariable("param")来申明参数 */
      @RequestMapping("/content/{id}")          //注解RequestMapping,定有url参数id
     public String content( @PathVariable("id") String contentID){
          ...                              //由于参数名与上面不同,则@PathVariable中申明对应url参数
          return "content";
     }

      /* 带有两个或多个参数的注解,分别对每个参数使用@PathVariable */
      @RequestMapping("/dictionary/{name}/{id}")     //注解RequestMapping,带有两个参数name,id
     public String dictionary( @PathVariable String name , @PathVariable String id){
          ...                                       //配置PathVariable,分别对应url的不同参数
          return "dictionary";
     }
     
      /* 使用RequestParam传值,无需再RequestMapping中配置,只需在方法的参数里申明*/
      @RequestMapping("/comment")
     public String comment(@RequestParam int id ,@RequestParam("name") String username){
          ...                                        //配置@RequestParam,默认从request中取值
          return "comment";
     }
}  
 
2.5 @ModelAttribute
     @ModelAttribute通过在Controller方法的参数上使用该注解来实现模型与页面数据的绑定,要求表单数据的name属性与Model的属性名称相同。
     
//相关的Controller
@Controller
@RequestMapping("/course")
public class Course{
     @RequestMapping("/add")
     public String add( @ModelAttribute Course course){
          ....
          return "/course/detail";
     }
}

//相关的Model
public class Course{
     private String courseName;
     private String courseType;
     private String courseIntro;
     
     public String getCourseName(){
          return this.courseName
     }
     ....
     ....    
}

//相关的表单
<form action="course/add" method="post">
     <input type="text" name=" courseName" />     <!-- name属性与Model中的属性对应 -->
     <input type="text" name=" courseType" />
     <input type="textarea" cols="10" name=" courseIntro" />
     <input type="submit" value="提交" />
</form>


     
异常处理

SpringMVC处理异常有三种方式:
(1) 使用SpringMVC提供的简单的异常处理器   SimpleMappingExceptionResolver
(2) 实现Spring的异常处理接口 HandlerExceptionResolver 自定义自己的异常处理器;
(3) 使用 @ExceptionHandler 注解实现异常处理

1 . SimpleMappingExceptionResolver

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
     <!-- 定义 默认的异常处理页面,当异常发生时跳转至该页面 -->
     <property name=" defaultErrorView" value="error" />
     <!-- 定义异常处理页面中用于获取 异常信息的变量名, 默认exception -->
     <property name=" exceptionAttribute" value="ex" />
     <!-- 定义需要 特殊处理的异常,用类名或全路径名作为key,异常页名作为值 -->
     <property name=" exceptionMappings">
          <props>
               <prop key="com.springmvc.MyException">error-my</prop>
          </props>
     </property
</bean>

2 . 实现 HandlerExceptionResolver覆写resolveException,跟据参数Exception的类型进行view的跳转

public class MyExceptionHandler implements HandlerExceptionResolver{
     @Override
     public ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response , Object handler , Exception ex){
          if(ex instanceof MyException){
               return new ModelAndView("error_my");
          }else{
               return new ModelAndView("error");
          }
     }
}

然后在xxx-servlet.xml中配置该异常处理器ExceptionHandler
<bean id = "myExceptionHandler" class="com.springmvc.exception.MyExceptionHandler" />

3 . @ExceptionHandler 注解

     @ExceptionHandler注解 应该注解在一个Controller的方法里,当该Controller中任何一个方法发生异常,则会被该方法拦截。
     
@Controller
public class MyController{
     
     @ExceptionHandler(Exception.class)
     public String catchException(Exception exception, ModelMap modelMap){
           
          return "error";  
     }
}

使用注解的方法,则需要在xxx-servlet.xml中配置
<context-component-scan base-package="com.springmvc.exception" />

四大注解类(Controller / Component / Service / Repository)

① Controller           标注web控制器 ,在上面已介绍过
② Component        通用标注
③ Service                标注Service层的服务
④ Respository         标注DAO层的数据访问




拦截器 Interceptor

SpringMVC中的Interceptor 拦截请求时通过HandlerInterceptor类实现。在SpringMVC定义Interceptor:
     ① 定义Interceptor类,实现 HandlerInterceptor接口                                                   推荐
     ② 定义Interceptor类,继承Spring提供的 抽象类 HandlerInterceptorAdapter;             推荐
     ③ 定义Interceptor类,实现WebRequestInterceptor接口

1 . 实现 HandlerInteceptor 接口
     ① preHandler()     在 业务处理器处理请求之前被调用,对request进行处理,
                                  返回值若为 false,则 拦截该请求,不再继续向下传递
                                  返回值若为 true,则 继续向下执行
          参数:Object arg2 为被拦截的请求的目标对象

     ② postHandler()   在 业务处理器处理请求之后被调用,也就是在 Controller方法调用之后执行,可以对ModelAndView
                              进 行操作, 在当前Interceptor的 preHandler返回值为true才会执行。 
          参数:ModelAndView arg3 为请求处理后返回的ModelAndView对象,可拦截该对象改变显示的视图和Model

     ③ afterCompletion()  在 DispatcherServlet完全处理完请求之后被调用,可以进行一些资源清理的操作。需要当前对应
                              的Interceptor的 preHandler方法返回值为true
          

2 . 注册拦截器
通过mvc:interceptors 标签注册或HandlerMapping上拦截

<!-- 通过mvc标签注册 -->
<mvc:interceptors>
     <mvc:interceptor>
          <mvc:mapping path="/user/*" />                                   //需要拦截的url地址
          <bean class="com.springmvc.interceptor.MyInterceptor"/>          //自定义的Interceptor
     </mvc:interceptor>
</mvc:interceptors>

<!-- 在HandlerMapping上拦截 -->
<bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
     <property name="interceptors">
          <list>
               <bean class="com.springmvc.interceptor.MyInterceptor" />
          </list>
     </property>
</bean>

3 . 多个拦截器协同工作时


4 . 使用场景

使用原则:处理所有请求的共同问题
1、解决乱码问题
2、解决权限验证问题


SpringMVC 文件上传



SpringMVC & JSON

ContentNegotiatingViewResolver

ResponseEntity

@ResponseBody / @RequestBody

相关网页收藏

http://haohaoxuexi.iteye.com/blog/1753271                                           SpringMVC Controller 
http://www.admin10000.com/document/6436.html                                史上最强SpringMVC
http://www.iteye.com/blogs/subjects/springMVC                                   SpringMVC介绍



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值