SpringMVC 应知应会

本文深入讲解SpringMVC的工作原理,包括处理器映射器、处理器适配器和视图解析器等核心组件,以及如何配置和使用SpringMVC进行Web开发。

springMVC 是表现层技术,可以用来代替 struts2,下面是简略图:主要是处理器和视图,只有这两个部分需要编写代码。

image

 

springMVC 三大组件:处理器映射器,处理器适配器,视图解析器。

下面是 SpringMVC的细节图:

image_thumb[3]

整个流程:

  1. 客户端的请求到达前端控制器 DispatcherServlet
  2. DispatcherServlet 收到请求后调用 HandlerMapping 处理器映射器
  3. 处理器映射器根据请求的 url 找到具体的处理器,生成处理器对象以及处理器拦截器【不一定有,但是有的话一定会生成】,并将生成的对象交给 DispatcherServlet
  4. DispatcherServlet 接收到处理器映射器反馈的信息,通过 HandlerAdapter 处理器适配器找到对应的处理器
  5. 执行处理器的逻辑【处理器也叫后端控制器,Controller 】
  6. Controller 执行完毕后返回 ModelAndView 对象【也可以返回 String】
  7. 再次回到 HandlerAdapter,HandlerAdapter 将 Controller 的执行结果 ModelAndView 返回給  DispatcherServlet,
  8. DispatcherServlet 接收到 ModelAndView 之后,调用 ViewReslover 视图解析器
  9. ViewReslover 解析猴年返回具体的 View 对象
  10. DispatcherServlet 对返回回来的 View 对象进行渲染【即将模型数据填充至视图】
  11. DispatcherServlet 响应客户端的请求

上述的十一个步骤,其中需要编写代码的只有处理器【Handler 即 Controller】和 视图【View】,其他的只需要配置即可。

 

处理器的编写:

1 . 处理器类需要添加配置成 bean,因为是在表现层,所有使用的是 @Controller注解,

2 . 处理器中的方法需要使用 @RequestMapping(“url”)注解

3 . 处理器中方法的形参列表支持的几个特殊的对象:HttpServletRequest,HttpServletResponse,HttpServletSession,

     见名知意,前端控制器会自动将这三个对象进行封装,便于方法内部获取请求参数和设置参数。

4 . 参数列表还支持一个参数——Modle【这个类是个接口,其子类 ModelMap】 ,但是它不是用来获取请求参数,

     而是通过它向 request域存储数据,向视图传递数据【视图可以理解为 jsp,但视图不只是 jsp】,

5 . 处理器类中方法支持的返回值类型有:

  • ModelAndView —— 携带了数据和要响应的视图【数据存储在 request域中】
  • String —— 携带了响应的视图,一般结合 Model形参使用,一个携带响应的视图,一个携带数据【数据存储在 request域中】
  • void —— 一般用于处理 AJAX 的请求,返回的数据由 Model形参来携带数据【或者其子类 ModelMap】,然后使用 request的转发或者 response进行重定向

小小总结:使用 ModelAndView,Model,ModelMap携带数据都是存储在了 request域中了,【 此时请求还未结束,也就是request对象还存活着 】,在 jsp页面使用 JSTL即可获取数据。

例子:

@Controller
public class ItemController {

    @Autowired
    private ItemService itemService;

    /**
     * 显示商品列表
     * 
     * @return
     */
    @RequestMapping("/itemEdit")
    public String queryItemById(HttpServletRequest request, ModelMap model) {
        // 从request中获取请求参数
         String strId = request.getParameter("id");
        Integer id = Integer.valueOf(strId);

        // 根据id查询商品数据
         Item item = this.itemService.queryItemById(id);
 
       // 第一种方式:使用 ModelAndView ----------------------------
       // 把结果传递给页面
        // ModelAndView modelAndView = new ModelAndView();
       // 把商品数据放在模型中
        // modelAndView.addObject("item", item);
       // 设置逻辑视图
        // modelAndView.setViewName("itemEdit");
       // 返回携带数据和视图的 ModelAndView对象
       // return modelAndView;
 
       // 第二种方式:使用 Model --------------------------------------
       //   把商品数据放在模型中,其实是放在了 request域中
        model.addAttribute("item", item);
       // 返回视图的名字,也就是 jsp的名字【jsp视图的路径前缀和后缀需在 springmvc.xml中配置】
        return "itemEdit";
    }
}

上面代码中写到的视图路径前缀和后缀的配置如下:【也就是配置视图解析器

<!-- 配置视图解析器 -->
<bean
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 配置逻辑视图的前缀 -->
    <property name="prefix" value="/WEB-INF/jsp/" />
        <!-- 配置逻辑视图的后缀 -->
    <property name="suffix" value=".jsp" />
</bean>

需要的配置:

1 . 添加 springmvc.xml文件,配置包扫描器,用于扫描 Controller

<?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:p="http://www.springframework.org/schema/p"
    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-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- 配置controller扫描包,多个包之间用,分隔 -->
    <context:component-scan base-package="com.msym.springmvc.controller" />

</beans>

2 . 配置前端控制器,在 web.xml 中配置 DispatcherServlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>springmvc-first</display-name>
    <!-- 配置 SpringMVC 前端控制器 -->
    <servlet>
        <servlet-name>springmvc-first</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 指定 SpringMVC 配置文件 -->
        <!-- SpringMVC 的配置文件的默认路径是 /WEB-INF/${servlet-name}-servlet.xml -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>springmvc-first</servlet-name>
        <!-- 设置所有以 action结尾的请求进入 SpringMVC -->
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
</web-app>

3 . 创建 Controller ,Controller只是一个普通 Java 类,需要使用 @Controller 进行注解,其中的方法使用 @RequestMapping 进行注解

4 . 在 springmvc.xml 中配置处理器映射器,处理器适配器,视图解析器【下面的第五步可以替代这一步

<!-- 配置处理器映射器 -->
<bean
    class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
<!-- 配置处理器适配器 -->
<bean
    class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />

5 . 可以采用注解驱动的方式,代替了处理器映射器,处理器适配器的配置。【第五步可以完全替代第四步

<!-- 注解驱动 -->
<mvc:annotation-driven />

 

 

 

SpringMVC 的拦截器:

Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。

之所以有预处理和后处理,是因为拦截器在处理器前后都会执行,只不过执行的方法不一样。

自定义拦截器需要实现 HandlerIntercept 接口,下面是【爱上笔记】中的一个拦截器类:

package cn.evelynn.cloudnote.interceptors;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.fasterxml.jackson.databind.ObjectMapper;

import cn.evelynn.cloudnote.entity.User;
import cn.evelynn.cloudnote.util.JsonResult;

/**
 * 拦截器:用于拦截未登录的用户
 * @author 码上猿梦
 *  http://www.cnblogs.com/daimajun/
 */
@Component
public class AccessInterceptor implements HandlerInterceptor {

    
    /**
     * 用于判断用户是否登录,
     * 未登录则拦截,
     * 已登录就放行
     */
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object obj) throws Exception {
        HttpSession session = req.getSession();
        //判断用户是否登录
        User user = (User) session.getAttribute("user");
        if (user == null) {
            // 利用response对象返回结果,告诉浏览器是Json格式,编码为UTF-8
            res.setContentType("application/json;charset=UTF-8");
            PrintWriter out = res.getWriter();
            //ObjectMapper能将java对象转换为匹配Json的结构
            ObjectMapper om = new ObjectMapper();
            //将字符串转换为Json格式的字符串
            String json = om.writeValueAsString(new JsonResult("请重新登录!"));
            out.write(json);
            //刷新缓冲区,向浏览器写出数据
            res.flushBuffer();
            return false;
        }
        //放行
        return true;
    }

    // controller执行后但未返回视图前调用此方法
    // 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        // TODO Auto-generated method stub
        
    }

                // controller执行后且视图返回后调用此方法
    // 这里可得到执行controller时的异常信息
    // 这里可记录操作日志
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // TODO Auto-generated method stub
        
    }
}

然后就是配置拦截器了,需要在 springmvc.xml 文件中配置拦截器:

<!-- 配置Interceptor -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!-- 请求 /note/ 和 /notebook/ 资源的请求都进入拦截器 -->
            <mvc:mapping path="/note/*" />
            <mvc:mapping path="/notebook/*" />
            <!-- AccessInterceptor 类采用了注解注册bean -->
            <ref bean="accessInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>

自定义异常类:

转载于:https://www.cnblogs.com/daimajun/p/7092083.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值