我个人理解的springmvc框架是其实是对于web层的简化开发与处理,当然它也有自己的配置文件,需要注意的是我们用javaweb开发是通过web.xml文件的配置实现一定的前端请求与对应的控制层servlet方法的响应。而在springMVC框架里基本也是需要web.xml文件去实现一些很重要的配置的。与spring不同的是,专注在web层开发的springmvc框架是基于注解开发的,这大大的实现代码的简洁。

请求分发器DispatcherServlet

DispatcherServlet的请求与响应流程

  • 用户申请Tomcat处理web应用请求前端控制器DispatcherServlet。

  • DispatcherServlet收到请求并调用HanderMapping处理器映射器。

  • 处理器映射器找到具体的处理器(可以根据xml配置、注解查找),生成处理对象及处理器拦截器(如果有就生成)一并返回给前端控制器。

  • 前端控制器调用HanderAdapter处理器适配器。

  • 处理器适配器经过适配具体的处理器(通常是我们设置的controller层,也叫后端控制器)。

  • controller完成任务返回modelandview。

  • 处理器适配器将controller执行结果modelandview传给viewReslover视图解析器。

  • 视图解析器解析后返回具体view。

  • 由modelandview返回给Tomcat进行视图渲染返回客户

见下图:

DispatcherServlet的配置(web.xml文件配置)

<!-- 设置前端控制器DispatcherServet,让servlet服务里的公有行为去帮助我们访问其他的特定行为-->
  <servlet>
    <servlet-name>DispatcherServlet</servlet-name>
      <!--使用框架封装的请求分发器类-->
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
<!--同样的要想实现在前端控制器里对特定行为的访问,必须要将特定行为配置的资源设置为可以初始化读取的参数资源-->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
<!-- 映射,和servlet成对出现-->
  <servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

字符编码过滤器Filter

字符编码过滤器的自定义

import javax.servlet.*;
import java.io.IOException;
/*过滤器的生命周期:我们看到在测试中,Tomcat工件部署之前就进行了过滤器的初始化,说明过滤器的初始化与Tomcat的部署过程中,
* 而过滤器的销毁在本地web服务器销毁之后。*/
public class filters implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("测试过滤器能否读取设置的过滤器编码参数"+filterConfig.getInitParameter("encoding"));
        System.out.println(filterConfig.getFilterName()+"过滤器被初始化!");
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletResponse.setCharacterEncoding("UTF-8");
        System.out.println("已经过滤服务名:"+servletRequest.getServerName());
        filterChain.doFilter(servletRequest,servletResponse);
    }
    @Override
    public void destroy() {
        System.out.println("过滤器被销毁!");
    }
}

自定义字符编码过滤器的配置(web.xml文件):

<!--注册字符过滤器-->
    <filter>
        <filter-name>filter1</filter-name>
        <filter-class>filters</filter-class>
        <!--设置字符过滤器的放行字符类型参数-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>filter1</filter-name>
        <!--拦截路径设置,这个路径下面的包文件会被字符过滤器过滤-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

字符编码过滤器的配置(框架封装配置在web.xml文件里)

<!--  编码过滤 utf-8,解决中文乱码的问题-->
  <filter>
    <description>char encoding filter</description>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
<!--    所有资源都过滤-->
    <url-pattern>/*</url-pattern>
  </filter-mapping>

字符编码过滤器的生命周期

具体解释见文章:http://t.csdn.cn/oDyw9

生命周期的区域关系:服务器-监听器-过滤器的初始化-正常工作-过滤器的销毁-监听器-服务器。

监听器ContextLoaderListener

全局上下文参数的配置

<!--  配置spring监听器与上下文参数applicationContext-->
<!--  上下文参数-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
      <!--一般配置进去的内容是需要读取的spring核心配置文件,因为我们需要让Tomcat服务器帮助我们在初始化这个应用的时候将我们的spring容器也实例化出来,同时我们的注入的Bean也会被注入进去,只不过这个Bean的生命周期与作用域还受到一定因素的影响-->
    <param-value>classpath:/applicationContext.xml</param-value>
  </context-param>

监听器的作用机制

生命周期的区域关系:服务器-监听器-过滤器的初始化-正常工作-过滤器的销毁-监听器-服务器。

监听器的配置

自定义监听器与配置

public class listeners implements ServletContextListener, HttpSessionListener {
    /*定义会话人数参数p*/
    private int p = 0;
 
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("初始化监听器");
        ServletContext servletContext = sce.getServletContext();
        /*读取全局参数can并输出测试servletContext监听器的作用是否起到*/
        String context = servletContext.getInitParameter("can");
        System.out.println(context);
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("销毁监听器!");
    }
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        p++;
        /*将这个p存到当前的会话上下文里,由页面接收并输出会话人数!*/
        se.getSession().setAttribute("person",p);
        /*控制台测试!*/
        System.out.println("当前会话人数为"+p);
    }
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("销毁会话!");
    }
 
}

web.xml中配置

<!--  设置全局参数can=ssss给监听器识别测试输出  -->
    <context-param>
        <param-name>can</param-name>
        <param-value>sssss</param-value>
    </context-param>
 
    <!--配置监听器-->
    <listener>
        <listener-class>listeners</listener-class>
    </listener>

框架封装监听器的配置(web.xml文件配置)

<!--  监听器ContextLoaderListener-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

视图解析器InternalResourceViewResolver

视图解析器的作用机制

见DispatcherServlet工作流程图,后续的工作原理会在我的spring源码深入总结里提到。

视图解析器的配置(配置在MVC的核心配置mvc.xml文件里)

<!--    内部资源视图解析器-->
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver">
      <property name="prefix" value="/WEB-INF/jsp/"/>
      <property name="suffix" value=".jsp"/>
  </bean>

实现HandlerInterceptor接口的自定义HL拦截器

Spring MVC 的拦截器类似于 Servlet 中的过滤器 Filter,用于对处理器进行预处理和后处理。 将拦截器按一定的顺序联结成一条链,这条链叫做拦截器链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP面向切面编程思想的一个具体实现。

拦截器的配置

public class MyHandlerInterceptor1 implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse
response, Object handler) {
System.out.println("preHandle running...");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse
response, Object handler, ModelAndView modelAndView) {
System.out.println("postHandle running...");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse
response, Object handler, Exception ex) {
System.out.println("afterCompletion running...");
}
}

配置在mvc.xml文件里:

<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
    <!--拦截路径范围设置-->
<mvc:mapping path="/**"/>
<bean class="com.hlc.interceptor.MyHandlerInterceptor1"/>
</mvc:interceptor>
</mvc:interceptors>
  • preHandle() 方法将在请求处理之前进行调用,该方法的返回值是布尔值Boolean类型的, 当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会 再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方 法

  • postHandle() 该方法是在当前请求进行处理之后被调用,前提是preHandle 方法的返回值为 true 时才能被调用,且它会在DispatcherServlet 进行视图返回渲染之前被调 用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象 进行操作

  • afterCompletion() 该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图 之后执行,前提是preHandle 方法的返回值为true 时才能被调用

异常处理器SimpleMappingExceptionResolver

异常处理器的配置(框架封装,配置在mvc.xml文件里)

<!--    配置异常处理器-->
<!--配置使用springmvc的简单异常处理器,这里注意我们也可以自己设置异常处理方法;采用springmvc给我们的HandlerExceptionResolver
接口并实现方法去设置我们的异常处理方式-->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" id="exceptionResolver">
<!--        默认的异常错误视图,error是自定义的视图名称,因为我配置了内部资源视图解析器会自动补全路径和后缀-->
        <property name="defaultErrorView" value="error"/>
<!--        异常映射。 异常类型 -> 错误视图页面 -->
        <property name="exceptionMappings">
            <map>
<!--                指定这个key对应的异常出现时 跳转的视图页面是error视图-->
                <entry key="com.hlc.exception.myException" value="error"/>
<!--                这个就是指定的类型转换异常的跳转视图是error1-->
                <entry key="java.lang.ClassCastException" value="error1"/>
            </map>
        </property>
    </bean>

自定义实现HandlerExceptionResolver接口的异常处理器

实现接口的java类

public class myException extends Throwable implements HandlerExceptionResolver {
//    方法中的参数Exception:异常对象
//    显然返回值就是我要跳转的视图信息model and view
 
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
 
        ModelAndView modelAndView = new ModelAndView();
//        判断异常,对应操作,相当于简单的异常处理器的原理
        if(ex instanceof ClassCastException){
            modelAndView.addObject("info",ex.toString());
            modelAndView.setViewName("error1");
        }
        return modelAndView;
    }
}

配置在mvc配置文件里

<!--    配置自定义异常处理器-->
    <bean class="com.hlc.exception.myException" id="exception"/>

区别于spring注解的MVC新注解

  • @RequestMapping 作用:用于建立请求URL和处理请求方法之间的对应关系,位置:可以放在类上,也可以放在方法上。注意路径的变化。属性:value:设置的静态路由的值,也叫URL与path的作用一样。method:指定请求方式,默认是GET请求方式。params:用于指定带参数访问的条件。

  • @RequestParam 请求参数,可以变换URL输入的字符指定为方法体里的某个参数。value就是替换参数之后的值(加入用n替换name,这样在浏览器URL里输入n=XXX就可以了),required = true或者false,作用就是必须输入参数或者可以不输入参数。defaultValue的值是后面参数的默认值,不输入时默认。

  • @RequestHeader value就是指定的头信息名,这个注解的作用就是请求头信息。required同上。

  • @cookieValue 获取指定的cookie值,用法与上请求头信息一致。

  • @ResponseBody 可以使方法返回的字符串按照json格式直接回写到空视图

文件上传

请点击查看这篇文章:http://t.csdn.cn/zm1fq

springMVC框架xml文件常用配置集合

组件扫描

<!--组件扫描-->
    <context:component-scan base-package="com.hlc.controller"/>

注解驱动

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

静态资源访问开启

<!--    静态资源访问权限-->
    <mvc:default-servlet-handler/>

视图解析器

<!--    内部资源视图解析器-->
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver">
      <property name="prefix" value="/WEB-INF/jsp/"/>
      <property name="suffix" value=".jsp"/>
  </bean>

错误页面处理(通常自己写一个错误页面在controller代码里体现出来错误处理)

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" id="exceptionResolver">
<!--        默认的异常错误视图,error是自定义的视图名称,因为我配置了内部资源视图解析器会自动补全路径和后缀-->
        <property name="defaultErrorView" value="error"/>
<!--        异常映射。 异常类型 -> 错误视图页面 -->
        <property name="exceptionMappings">
            <map>
<!--                指定这个key对应的异常出现时 跳转的视图页面是error视图-->
                <entry key="com.hlc.exception.myException" value="error"/>
<!--                这个就是指定的类型转换异常的跳转视图是error1-->
                <entry key="java.lang.ClassCastException" value="error1"/>
            </map>
        </property>
    </bean>

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐