SpringMVC入门概述,执行流程及基本知识点

SpringMVC是什么:

Spring家族的一员,属于SpringFrameWork的后续产品,是一种基于Java实现MVC设计模型的请求驱动类型的轻量级表现层框架。该框架可以接收浏览器的请求,对数据进行处理,然后响应。

MVC是软件的架构方式,把软件系统分为模型M(Model),视图V(View),控制器C(Controller),将数据,页面,代码进行分离。

而在SpringMVC中的MVC,M可以代表JavaBean,V可以代表页面,C则代表Controller类。

SpringMVC开发方式:

SpringMVC通过web.xml和springmvc.xml两个配置文件来进行相关配置,在服务器启动时进行初始化,通过调用各个组件来进行各种操作,最终执行Controller类中的方法处理数据。

web.xml需要配置的部分内容:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

  <!--配置前端控制器,用户发出的请求需要通过DispatcherServlet类,来找到我们自定义用于处理请求的类
  DispatcherServlet类是整个流程控制中心,所有请求都经过它来控制,它来决定下一步做什么。
  -->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--加载springmvc.xml配置文件,-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <!--配置启动加载,服务器启动时,就把该加载的配置文件(如springmvc.xml)和资源加载完毕-->
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <!--通用写法: /表示所有请求都会被该servlet处理,.jsp不会被处理,要想处理.jsp使用//*-->
    <url-pattern>/</url-pattern>
  </servlet-mapping>

    <!--配置解决中文乱码问题的过滤器filter-->
    <filter>
        <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>

</web-app>
        

springmvc.xml需要配置的部分内容:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 配置spring创建容器时要扫描的包(开启注解扫描) -->
    <context:component-scan base-package="cn.cx"/>

    <!-- 配置视图解析器,进行页面跳转
        当资源位置改变后,不修改源码,可以直接在配置文件中修改
    -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--跳转页面前面的路径-->
        <property name="prefix" value="/"></property>
        <!--跳转页面资源的后缀名-->
        <property name="suffix" value=".jsp"></property>
    </bean>

    <!--配置日期转换器,类型转换器的组件,把我们的日期转换器注入到组件中-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <!--把我们的日期转换器注入到组件中-->
                <bean class="cn.cx.demo1.StringToDate"/>
            </set>
        </property>
    </bean>
</beans>

一个简单Controller类:

/**
 *  用于处理用户发出请求的类,表现层,用@Controller配置,加入IOC容器
 * 使用@RestController修饰的类,其下所有方法不走视图解析器,直接返回字符串
 * */
@Controller
@RequestMapping("/user")
public class UserController {

    /**
     * RequestMapping也可以写在类上,代表一级路径,而类中方法上的RequestMapping则代表二级目录
     * path、value表示发送的请求名称(用哪个都行,value可以用直接写字符串)
     * method表示当前方法允许何种请求方式能访问  method = {RequestMethod.GET}表示只允许get方法
     * params表示请求路径上必须有指定的参数名称
     *
     * 请求参数绑定:当前端传递一个参数,我们只需要在方法中添加一个名称和前端name一致的参数,即可接收收到
     * springmvc框架底层通过反射方式绑定到了方法参数上
     * */
    @RequestMapping("/save")
    public String save(User user){
        //....业务逻辑代码
        
        //如果springmvc.xml配置了视图解析器,可以就只写资源名称,不用写路径和后缀名
        return "suc";
    }

    
}

SpringMVC执行流程图:

在这里插入图片描述
上图中映射器,适配器,解析器等等,我们称之为SpringMVC组件,上图仅包含SpringMVC中比较关键的组件,并不是全部组件,这些组件是“可插拔”的,可以在springmvc.xml中仅配置。

用文字描述其流程:

用户发出的请求需要通过DispatcherServlet类,来找到我们自定义用于处理请求的类(Controller类),
DispatcherServlet类是整个流程控制中心,所有请求都经过它来控制,它来决定下一步做什么。
1、当点击超链接,发出请求后,先调用映射器组件(解析出 /user/save请求)。
2、调用适配器组件(查找IOC容器中的所有类,找到对应类及其方法)。
3、调用控制器组件,返回ModelAndView对象(让找到的Controller类对应的方法执行,拿到需要返回资源的资源名)。
4、调用视图解析器组件,根据springmvc.xml中的视图解析器和返回资源名组成一个完整页面访问路径,然后将jsp翻译成Servlet生成html,进行请求转发。

SpringMVC相关注解:

@RequestMapping:表示映射请求,来指定该控制类可以处理哪些请求,相当于servlet中web.xml的下面这段配置:

<servlet>
    <servlet-name>UserServlet</servlet-name>
    <servlet-class>xx.xxx.UserServlet</servlet-class>
    
</servlet>

<servlet-mapping>
    <servlet-name>UserServlet</servlet-name>
    <url-pattern>/user/save</url-pattern>
</servlet-mapping>

@RequestParam:把请求中指定名称的参数传递给对应形参。(接收前端参数就加上这个注解)
注意:请求参数绑定实体类,形参直接是对应实体类对象即可(类中属性,前端传递name值要保持一致),springmvc底层自动封装
@RequestBody:获取请求体(get方法的不行),加在方法返回类型前,表示以json数据封装。
@ResponseBody:不会走视图解析器,会直接返回一个json字符串。(比如异步获取 json 数据,加上 @ResponseBody 后,会直接返回 json 数据)
@PathVariable:绑定@RequestMapping里url中的占位符(如/user/save/{id}),可实现RestFul风格。
@CookieValue:获取指定cookie名称的值。
@GetMapping:处理get方式请求
@PostMapping:处理post方式请求
@ResponseBody:将返回对象以json数据格式封装。

SpringMVC方法响应数据类型:

String:直接走视图解析器,转发返回字符串的地址(请求转发forward:、重定向redirect:)。
void:默认去查询@RequestMapping中路径页面,可以手动获取request,response参数转发。
ModleAndView:可以通过addObject()和setViewName返回对象,设置视图(返回地址),返回给前端。

SpringMVC文件上传组件:

<!--配置文件上传的解析器组件。id的名称是固定,不能乱写-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
      <!--设置上传文件的最大兆:1024*1024*8,8MB-->
      <property name="maxInMemorySize" value="8388608"/>
</bean>

SpringMVC异常处理组件:

在这里插入图片描述
首先需要自定义异常类,继承Exception。

/**
 * 自定义异常类
 * */
public class SysException extends Exception {

    private String message;

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public SysException(String message){
        this.message = message;
    }
}

然后自己编写异常处理组件的类,实现HandlerExceptionResolver。

/**
 * 自定义异常处理器,需要实现HandlerExceptionResolver接口
 * 当我们配置异常处理器后,Springmvc会自己调用该类方法
 * */
public class SysExceptionResolver implements HandlerExceptionResolver{
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {

        e.printStackTrace();
        
        SysException exception = null;

        if(e instanceof SysException){
            //如果类型是我们自定义的异常,直接转换
            exception = (SysException) e;
        }
        //如果不是我们自定义的异常,自己创建一个
        exception = new SysException("系统可能正在维护,出现错误,不好意思呀");

        //创建返回对象,存入异常信息
        ModelAndView mv = new ModelAndView();
        mv.addObject("message", e.getMessage());

        mv.setViewName("exception");
        return mv;

    }
}

最后在springmvc.xml中将异常处理器类控制反转。

<!--将异常处理器控制反转-->
<bean id="sysExceptionResolver" class="xx.xxx.SysExceptionResolver"/>

SpringMVC拦截器:

用于对处理器进行预处理和后处理的技术,拦截器也是AOP思想的一种体现方式,想要自定义拦截器,需要实现HandlerInterceptor接口。

实现HandlerInterceptor的类,需要复写3个方法:

preHandle():在controller中方法执行前拦截,return true表示放行,反之表示拦截。
postHandle():在controller中方法执行后拦截。
afterCompletion():当跳转页面执行后,最后执行该方法。

/**
 * 自定义拦截器,需要实现HandlerInterceptor接口,重写里面的方法
 *
 * */
public class MyInterceptor1 implements HandlerInterceptor {
    /**
     * preHandle方法在controller中的方法执行前拦截,只有return true,才能执行其中方法
     * 可以使用request或者response跳转到指定的页面
     * */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器MyInterceptor1,preHandle方法执行...");
        //request.getRequestDispatcher("/exception.jsp").forward(request,response);
        //true放行,false拦截
        return true;
    }
    /**
     * controller中方法执行后,进行拦截
     * */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器MyInterceptor1,拦截器postHandle...");
        // 也是可以进行页面的跳转
        //request.getRequestDispatcher("/index.jsp").forward(request,response);
        return;
    }
    /**
     * 跳转的jsp页面都执行完成了,最后执行该方法
     * */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("拦截器MyInterceptor1,afterCompletion方法执行...");
    }
}

涉及方法执行顺序(preHandle放行是前提):

preHandle方法→controller方法→postHandle方法→页面→afterCompletion方法。

springmvc.xml拦截器配置:

	<!--配置拦截器组,如果有多个拦截器,在遵循拦截器方法执行顺序的前提下,
    preHandle方法按照拦截器配置顺序执行,其他方法按照拦截器配置倒序执行,
    与java Web Filter执行效果相同,如下:

        拦截器MyInterceptor1,preHandle方法执行...
        拦截器MyInterceptor2,preHandle方法执行...
        拦截器MyInterceptor3,preHandle方法执行...
        DeptController类内,findAll方法执行...
        拦截器MyInterceptor3,拦截器postHandle...
        拦截器MyInterceptor2,拦截器postHandle...
        拦截器MyInterceptor1,拦截器postHandle...
        jsp页面执行
        拦截器MyInterceptor3,afterCompletion方法执行...
        拦截器MyInterceptor2,afterCompletion方法执行...
        拦截器MyInterceptor1,afterCompletion方法执行...

    -->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--该拦截器拦截哪些资源,此处表示/dept下的所有方法-->
            <mvc:mapping path="/dept/**"/>

            <!--该拦截器不拦截哪些资源-->
            <mvc:exclude-mapping path=""/>
            
            <!--应用拦截器对象-->
            <bean class="xx.xxx.MyInterceptor1"/>
        </mvc:interceptor>

        <mvc:interceptor>
            <mvc:mapping path="/dept/**"/>
            <bean class="xx.xxx.MyInterceptor2"/>
        </mvc:interceptor>

        <mvc:interceptor>
            <mvc:mapping path="/dept/**"/>
            <bean class="xx.xxx.MyInterceptor2"/>
        </mvc:interceptor>
    </mvc:interceptors>

SpringMVC的拦截器和Servlet中的过滤器功能很相似,但也有区别:

1、过滤器是Servlet的一部分,任何框架都可以使用,但拦截器是SpringMVC独有的。
2、过滤器配置/*,可以拦截所有资源,但拦截器只对控制器中方法进行拦截。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值