首页 > 技术文章 > Springmvc笔记

kimi9py 2016-07-22 16:50 原文

1       springmvc的框架原理

1.1      b/s系统mvc原理

 

mvc是什么?mvc是设计模式。

1.2      springmvc是什么?

Mvc的框架,是spring框架的一个模块。

1.3      springmvc框架原理

1、  用户发起请求,请求到DispatcherServlet前端控制器

DispatcherServlet(中央调度),负责request和response,负责调用处理器映射器查找Handler,负责调用处理器适配器执行Handler,有了前端控制器降低了各各组件之间的耦合性,系统扩展性提高。

2、  DispatcherServlet前端控制器请求处理器映射器HandlerMapping查找Handler

根据用户请求的url,根据一定的规则去查找(比如:xml配置,注解)

3、  HandlerMapping处理器映射器将Handler返回给前端控制器

4、  DispatcherServlet前端控制器调用HandlerAdapter处理器适配器执行Handler

程序员编写的Handler是按照适配器要求的规则去执行Handler

 

5、  HandlerAdapter处理器适配器执行Handler

适配器按照一定规则去执行Handler

6、  Handler执行完成,返回ModelAndView

ModelAndView是springmvc的封装对象,将model和view封装在一起。

7、  HandlerAdapter处理器适配器将ModelAndView返回给前端 控制器

 

8、  前端控制器调用视图解析器,进行视图解析,解析完成给前端控制器返回View

View是springmvc的封装对象,是一个接口,实现类包括jspview,pdfview。。。。

9、  前端控制器调用view进行视图渲染

将模型数据填充到view(将model数据填充到request)响应给用户

10、前端控制器响应给用户。

 

 

2       与struts的不同

1、  springmvc的入口是servlet,struts是filter

2、  springmvc是基于方法开发,struts是基于类开发

action类中,一个url对应一个方法,对Handler对象,springmvc框架将一个方法封装到Handler中(只有一个method)。Struts对action类进行实例化。

Springmvc中的action可以使用单例也可以使用多例,建议使用单例(对相同的方法只new一个)。

Struts不能用单例,因为struts传递参数是通过成员变量。

 

Springmvc通过形参接收参数好处:更符合软件开发的思想,和service接口类似。

Struts采用值栈存储请求和响应的数据,通过OGNL存取数据, springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。

 

3       常用注解

 

3.1      @controller

标识该类为控制器类,@controller、@service、@repository分别对应了web应用三层架构的组件即控制器、服务接口、数据访问接口

 

3.2      @RequestMapping

进行url映射,一个方法对应一个url,定义方法:在action方法上定义requestMapping

 

3.2.1      根路径+子路径

需求:为了很好的管理url,为了避免url的冲突,使用根路径+子路径

根路径:

         在类名上边定义requestMapping

子路径:

         在方法上边定义requestMapping

最终访问路径:根路径+子路径:/stu/editstudent.action

 

3.2.2      URL模板模式映射

将参数在url中传递。

定义方法:

URI 模板模式映射好处:方便实现restful。

 

3.2.3      请求方法限定

测试,限定为post

可以限定为get、post、或两者都可以

限定GET方法

@RequestMapping(method = RequestMethod.GET)

 

如果通过Post访问则报错:

HTTP Status 405 - Request method 'POST' not supported

 

例如:

@RequestMapping(value="/useredit/{userid}",method=RequestMethod.GET)

限定POST方法

 

@RequestMapping(method = RequestMethod.POST)

 

如果通过Post访问则报错:

HTTP Status 405 - Request method 'GET' not supported

 

GET和POST都可以

@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})

 

 

4       请求参数绑定(重点)

Springmvc通过参数解析器,将客户端请求的key/value解析成方法形参数.

 

4.1      默认支持的参数类型

HttpServletRequest

通过request对象获取请求信息

HttpServletResponse

通过response处理响应信息

HttpSession

通过session对象得到session中存放的对象

Model

通过model向页面传递数据,如下:

model.addAttribute("user", new User("李四")); 

model也可以通过modelMap或map将数据传到页面。

 

4.2      表单对象-简单类型

Action方法的形参数默认支持:string、int、double等简单类型,建议使用包装类型(可以设置null)。

注意:对于date类型的参数需要注册属性编辑器。 

使用方法:

直接在形参上定义

也可以在pojo中通过属性传递简单类型

 

4.3      表单对象-pojo

4.3.1     使用pojo属性名传递

页面定义:

Action方法的定义:

在形参使用pojo接收上边的参数。

 

4.3.2      使用pojo点属性名传递

页面定义:

Action方法的定义:

在形参不能直接使用pojo接收上边的参数。

应该使用包装对象接收上边的参数。

Action形参的定义:

4.4      字符串数组绑定

4.5      字符串数组绑定

4.6      @RequestParam绑定单个请求参数

 

5      结果转发

Redirect:请求重定向

         浏览器中地址栏的url通过Redirect变了,重新定义了一个request。

Action方法通过Redirect重定向到另一个方法,方法形参无法带到另一个方法。

 

 

Forward:页面转发

         浏览器中地址栏的url通过Forward不变,没有重新定义了一个request。

    Action方法通过Forward转发到另一个方法,方法形参可以带到另一个方法。

 

6       @RequestBody @ResponseBody实现json数据交互

 

Json数据在企业中使用好处:

Json在企业开发中已经作为通用的接口参数类型。

Json数据在页面(客户端)解析很方便。

 

Json定义:

var obj={”name”:”张三”,”age”:12}//key/value格式

Json数据解析:

obj.name

 

页面提交数据时,需要将提交的数据传成json进行提交。

Action方法中将json串转成java对象赋值形参

可以使用@RequestBody将请求的json串转成java对象。

 

6.1      实现

6.1.1      Json转换器配置:

1、  将json转换的jar包加入工程

2、  在处理器适配器上配置Json转换器

6.1.2      编写需求1的代码:

请求json响应json

页面代码:

引入 :jquery-1.4.4.min.js

 

7       拦截器

拦截器是针对handlerMapping的拦截器,由handlerMapping查找Handler后,将拦截器返回给前端控制器。

 

7.1      配置拦截器

针对某一个handlerMapping配置拦截器

<bean

    class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">

    <property name="interceptors">

       <list>

           <ref bean="handlerInterceptor1"/>

           <ref bean="handlerInterceptor2"/>

       </list>

    </property>

</bean>

    <bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/>

    <bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>

 

 

 

 

间接配置全局拦截器:让springmvc框架自动向每个handlerMapping中注册拦截器

<!--拦截器 -->

<mvc:interceptors>

    <!--多个拦截器,顺序执行 -->

    <mvc:interceptor>

       <mvc:mapping path="/**"/>//拦截所有请求

       <bean class="cn.itcast.springmvc.interceptor.HandlerInterceptor1"></bean>

    </mvc:interceptor>

    <mvc:interceptor>

       <mvc:mapping path="/**"/>

       <bean class="cn.itcast.springmvc.interceptor.HandlerInterceptor2"></bean>

    </mvc:interceptor>

</mvc:interceptors>

 

7.1      定义拦截器

实现HandlerInterceptor接口。

 

public class HandlerInterceptor1 implements HandlerInterceptor {

 

   //handler,springmvc根据url找到Handler(只有一个方法)

   //执行时机:进入Handler方法之前执行,如果返回false表示拦截,如果返回true表示放行

   //使用场景:用于用户身份校验,用户权限拦截校验

   @Override

   public boolean preHandle(HttpServletRequest request,

         HttpServletResponse response, Object handler) throws Exception {    

      System.out.println("HandlerInterceptor1..preHandle");  

      return false;

   }

   //执行时机:进入Handler方法之后 ,在返回modelAndView之前

   //使用场景:使用modelAndView,向页面传递通用数据,使用统一的view

   @Override

   public void postHandle(HttpServletRequest request,

         HttpServletResponse response, Object handler,

         ModelAndView modelAndView) throws Exception {

      System.out.println("HandlerInterceptor1..postHandle");

     

   }

   //执行时机:Handler方法执行完成,(modelAndView已经返回)

   //使用场景:统一异常处理,统一记录系统日志,用于action方法执行监控(在preHandle记录一个时间点,在afterCompletion记录执行结束时间点,将结束时间点减去开始执行时间点,得到执行时长)

   @Override

   public void afterCompletion(HttpServletRequest request,

         HttpServletResponse response, Object handler, Exception ex)

         throws Exception {

      System.out.println("HandlerInterceptor1..afterCompletion");

     

   }

 

7.2      测试

7.2.1      两个拦截器都放行

HandlerInterceptor1..preHandle

HandlerInterceptor2..preHandle

HandlerInterceptor2..postHandle

HandlerInterceptor1..postHandle

HandlerInterceptor2..afterCompletion

HandlerInterceptor1..afterCompletion

 

结论:

preHandle是按照拦截器定义顺序执行,

postHandle和afterCompletion是按照拦截器定义逆向执行。

 

7.2.2      第一个放行第二个不放行

HandlerInterceptor1..preHandle

HandlerInterceptor2..preHandle

HandlerInterceptor1..afterCompletion

 

结论:

只要有一个拦截器不放行,action方法无法完成。

如果拦截器放行,afterCompletion才会执行。

只要有一个拦截器不放行,postHandle不执行

 

7.2.3      两个都不放行

HandlerInterceptor1..preHandle

 

结论:

只要有一个拦截器不放行,action方法无法完成。

只要有一个拦截器不放行,postHandle不执行。

 

7.3    拦截器应用

案例:

用户身份认证拦截,用户登陆成功后,系统记录session(用户身份信息),用户去操作url时,拦截器需要校验用户身份是否合法(查看session中是否有用户身份信息,如果没有说明用户身份不合法,不合法重新登陆)

 

8      <mvc:annotation-driven />

用来替换上边定义的处理器引射器和适配器

 

推荐阅读