springmvc笔记_1

1.概念

springMVC:是基于spring的一个框架, 实际上就是spring的一个模块, 专门是做web开发的。
理解是servlet的一个升级

web开发底层是servlet , 框架是在servlet基础上面加入一些功能,让你做web开发方便。

SpringMVC就是一个Spring。 Spring是容器,ioc能够管理对象,使用<bean>, @Component, @Repository, @Service, @Controller
SpringMVC能够创建对象, 放入到容器中(SpringMVC容器), springmvc容器中放的是控制器对象,

我们要做的是 使用@Contorller创建控制器对象, 把对象放入到springmvc容器中, 把创建的对象作为控制器使用
这个控制器对象能接收用户的请求, 显示处理结果,就当做是一个servlet使用。

使用@Controller注解创建的是一个普通类的对象, 不是Servlet。 springmvc赋予了控制器对象一些额外的功能。


web开发底层是servlet, springmvc中有一个对象是Servlet : DispatherServlet(中央调度器)
DispatherServlet: 负责接收用户的所有请求, 用户把请求给了DispatherServlet, 之后DispatherServlet把请求转发给我们的Controller对象, 最后是Controller对象处理请求。
 

springmvc请求的处理流程

浏览器发起地址请求

tomcat将这个请求给 DispatcherServlet(中央调度器,本质上是一个servlet,需要配置路径)

DispatcherServlet根据配置文件知道控制层里面的方法对应的路径,通过路径来调用方法

然后框架执行方法内容

简单来说就是:前端--------》DispatcherServlet------------》控制器

需要的配置:
首先需要在web.xml文件中配置DispatcherServlet这个servlet

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">


<!--    注册springmvc的核心对象DispatcherServlet,需要在tomcat服务器启动之后就创建实例-->
<!--    在DispatcherServlet创建过程中会在他的init初始化方法中创建容器对象,然后可以创建出controller对象,通过接收-->
<!--    到的地址和控制器对象来决执行某些方法-->

<!--    DispatcherServlet是一个servlet,servlet初始化的时候会执行init()方法,init中有-->
<!--    WebApplicationContext ctx=new ClassPathXmlApplicationContext("srpingmvc.xml");-->
<!--    getServletContext().setAttribute(key,value);-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--        在启动服务器的时候DispatcherServlet对象中的init方法会自动找WEB-INF/springmvc-servlet.xml文件(springmvc是这个servlet的名称)-->
<!--      加上这个之后,会按照这个指定的路径来寻找文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
<!--        加上这个标签可以,让tomcat启动的时候就创建这个servlet对象,数字越小启动越快-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>


</web-app>

然后需要在对应的路径配置扫描controller层的文件(这里指定的是resources下的)

<context:component-scan base-package="com.springmvc.controller"></context:component-scan>

然后配置环境就搭建完毕,只需要写控制层就可以开始使用了

springmvc执行过程源代码分析 (简单的原码分析)

1. tomcat启动,创建容器的过程
   通过load-on-start标签指定的1,创建DisaptcherServlet对象, 
   DisaptcherServlet它的父类是继承HttpServlet的, 它是一个serlvet, 在被创建时,会执行init()方法。
   在init()方法中
   //创建容器,读取配置文件
    WebApplicationContext ctx = new ClassPathXmlApplicationContext("springmvc.xml");
    //把容器对象放入到ServletContext中
    getServletContext().setAttribute(key, ctx);

  上面创建容器作用: 创建@controller注解所在的类的对象, 创建MyController对象,
   这个对象放入到 springmvc的容器中, 容器是map , 类似 map.put("myController",MyController对象)

2.请求的处理过程
  1)执行servlet的service()
首先执行protected void service(HttpServletRequest request, HttpServletResponse response)

然后 protected void doService(HttpServletRequest request, HttpServletResponse response)


最后 DispatcherServlet.doDispatch(request, response){

调用MyController的.doSome()方法
      }

   doDispatch:springmvc中DispatcherServlet的核心方法, 所有的请求都在这个方法中完成的。

 发起的请求是由哪些服务器程序处理的。

comcat服务器负责处理html,图片,js文件等资源

而  DispatcherServlet负责处理转发访问

@RequestParam注解

用法:请求中参数名和处理器方法的形参名不一样 属性;

value指定请求参数名称(前端传递过来的名称)

required,boolean类型用于指定该参数是否必须

框架调用request.getParameter()获取出前端传递来的值然后直接注入到参数中。 前端传递来的参数,框架会自动转换类型。注入的方式是根据命名。相同的名称参数会自动注入进去。 也可以使用实体类来接收前端传递来的参数。框架会自动创建对象

@RequestMapping("/some.do")
    public ModelAndView somedo( @RequestParam("name")String name, @RequestParam("sex")String sex, @RequestParam("age")Integer age){

        ModelAndView m=new ModelAndView();
        m.addObject("name",name);
        m.addObject("sex",sex);
        m.addObject("age",age);
        m.setViewName("show");
        return m;
    }

返回json数据

在目前的使用中,一般后台和前端都是使用ajax的交互方式,所以数据格式使用的就是json的数据格式。控制层方法一般会返回一个json数据(Student),一般这个过程由框架来实现。

框架将数据转换为json首先调用 ArrayList<HttpMessageConverter>中每个类的canWrite()方法检查,HttpMessageConverter接口的实现类能处理Student类型的数据--MappingJackson2HttpMessageConverter 2.框架会调用实现类的write(), MappingJackson2HttpMessageConverter的write()方法 把李四同学的student对象转为json,调用Jackson的ObjectMapper实现转为json contentType: application/json;charset=utf-8 3.框架会调用@ResponseBody把2的结果数据输出到浏览器, ajax请求处理完成

简单来说,想要使用mvc的转换功能需要的步骤:

  • 首先添加相关的依赖
    <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-core</artifactId>
          <version>2.9.0</version>
        </dependency>
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <version>2.9.0</version>
        </dependency>
  • 添加驱动,在中央调度处理器获取的xml文件里面添加
        <mvc:annotation-driven />
  • 添加注解@ResponseBody,在控制器上

前端ajax的使用

 $(function () {
        $("#button").click(function () {
            $.ajax({
                url:"some.do",
                data:{name:"zhangsan",
                      sex:"nan",
                      age:12
                },
                type:"post",
                dataType:"json",
                success:function (res) {
                    alert(res.name+res.sex+res.age)
                },
            })
        })

    })

这如果返回值是string的话可能会出现乱码,只需将dataType的类型设置为text就行。 

处理器方法返回的是String , String表示数据的,不是视图。 区分返回值String是数据,还是视图,看有没有@ResponseBody注解 如果有@ResponseBody注解,返回String就是数据,反之就是视图

将中央调度器设置为/路径

这样做之后就会发现静态资源无法访问,原因是因为tomcat处理静态资源借助的就是default servlet,这个servlet的路径就是/,如果中央调度处理器使用同一个就会将原本的覆盖。
<!--第一种处理静态资源的方式:

需要在springmvc配置文件加入 <mvc:default-servlet-handler> 原理是: 加入这个标签后,框架会创健控制器对象DefaultServletHttpRequestHandler(类似我们自己创建的MyController). DefaultServletHttpRequestHandler这个对象可以把接收的请求转发给 tomcat的default这servlet。

这种方式任然需要default来工作

<!--第二种处理静态资源的方式

mvc:resources 加入后框架会创建 ResourceHttpRequestHandler这个处理器对象。 让这个对象处理静态资源的访问,不依赖tomcat服务器。 mapping:访问静态资源的uri地址, 使用通配符 ** location:静态资源在你的项目中的目录位置。 images/**:表示 images/p1.jpg   images/user/logo.gif , images/order/history/list.png -->

<mvc:resources mapping="/static/**" location="/static/" />

使用ssm整合项目

这里的配置文件详解放到一个单独的文档

ssm框架的配置文件完整方式_洛空_的博客-CSDN博客ssm配置解析https://blog.csdn.net/m0_64589497/article/details/127311493

请求转发forward和重定向redirect

从上述能够知道可以使用视图解析器来访问WEB-INF目录下的jsp文件,时候如果指定了试图解析器的前缀是WEB-INF/view,这时候需要访问WEB-INF下的另一个目录就需要用到forward

@RequestMapping("/forward.do")
    public ModelAndView forward(Student student){
        ModelAndView m=new ModelAndView();
        m.addObject("msg",student);
        m.setViewName("forward:/WEB-INF/forward/show.jsp");
        return m;
    }

 这样就可以访问到需要的其他目录,需要写完整的目录。

重定向

@RequestMapping("/redirect.do")
    public ModelAndView redirect(Student student){
        ModelAndView m=new ModelAndView();
        m.addObject("msg",student);
        m.setViewName("redirect:/hellow.jsp");
        return m;
    }

 重定向无法和视图解析器一起使用(无法访问WEB-INF目录下的jsp文件),使用重定向的时候,相当于一次新的请求,所以无法获取到m对象中的参数。ModelAndView是存放在reques请求域里面的数据,如果使用重定向的访问方式,那会生成一个新的request,所以无法获取数据。

 

使用全局异常处理

实际上就是一种全局的aop处理方式

只需要创建一个全局处理类,然后直接加上 @ControllerAdvice注解就可以了,然后可以选特定的异常类型捕捉使用不同的处理方式。这个类必须交给容器管理。

@ControllerAdvice
public class GlobalExceptionHander {

    @ExceptionHandler(value= NameException.class)
    public ModelAndView doNameException(Exception ex){
        ModelAndView m=new ModelAndView();
        m.addObject("msg","姓名必须是张三,其他用户不可以访问");
        m.addObject("ex",ex);
        m.setViewName("nameError");
        return m;
    }

    @ExceptionHandler(value= AgeExecption.class)
    public ModelAndView doAgeException(Exception ex){
        ModelAndView m=new ModelAndView();
        m.addObject("msg","年龄不能为空");
        m.addObject("ex",ex);
        m.setViewName("nameError");
        return m;
    }

    @ExceptionHandler()
    public ModelAndView doOtherException(Exception ex){
        ModelAndView m=new ModelAndView();
        m.addObject("msg","其他异常!");
        m.addObject("ex",ex);
        m.setViewName("nameError");
        return m;
    }
}



public class MyException extends Exception {
    public MyException(String message) {
        super(message);
    }

    public MyException() {
        super();
    }
}

里面的异常你可以自己定义,也可以用存在的,有一个全局的处理方式。

配置文件扫描

<context:component-scan base-package="com.ssm.handler"></context:component-scan>

拦截器

拦截器是springmvc中的一种,需要实现HandlerInterceptor接口,

拦截器和过滤器类似,功能方向不一样,过滤器是用来设置编码的

拦截器是全局的,可以对多个controller拦截。拦截器通常用在,验证身份,权限检查,日志

拦截器使用的步骤

首先定义一个类来实现HandlerInterceptor接口,然后再springmvc的配置文件中声明拦截器的位置以及访问路径

拦截器的执行时间,和过滤器一样,会在方法前后都执行

 

public class MyInterceptor implements HandlerInterceptor {
    /**
     *
     * @param request
    	 * @param response
    	 * @param handler  被拦截的控制器对象
     * @return 返回值是一个boolean对象,true通过,反之拦截
     * @author liujun
     * @date  这个方法是在控制器方法的前面执行,可以在这个方法里面获取请求信息,可以验证登录信息
     */

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String name = request.getParameter("name");
        String age = request.getParameter("age");
        if ("张三".equals(name)){
            return true;
        }
        return false;
    }

    /**
     * 后处理方法,控制器执行之后执行
     * @param request
    	 * @param response
    	 * @param handler 被拦截的控制器对象
    	 * @param modelAndView  处理方法的返回值
     * @return
     * @author liujun
     * @date  可以对原本的执行结果修改
     */

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        modelAndView.addObject("msg","拦截器修改之后的modelAndView");
    }

    /**
     *
     * @param request
    	 * @param response
    	 * @param handler 被拦截器的处理器对象
    	 * @param ex 程序中的异常
     * @return
     * @author liujun
     * @creed: Talk is cheap,show me the code
     * @date  在请求处理完成后执行,框架中规定是当你视图处理完成后,对视图转发。
     * 一般是用来资源回收,删除对象等
     */

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
          throw ex;
    }
}
  <!--    声明拦截器,可以声明多个-->
    <mvc:interceptors>
<!--        第一个-->
        <mvc:interceptor>
<!--            将拦截器和拦截路径绑定-->
            <mvc:mapping path="/**"/>
            <bean class="com.ssm.handler.MyInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

拦截器和过滤器

过滤器是servlet中的对象,拦截器是框架中的对象

过滤器是实现Filter接口的对象,拦截器是实现HandlerInteceptor接口的

过滤器是用来解决字符集的问题的额,拦截器是用来验证请求的

过滤器是tomcat创建的,拦截器是框架创建的

过滤器只有一个执行时间点,但是存在初始化和 销毁方法,而拦截器存在三个执行点

过滤器在servlet之前执行,而拦截器在中央调度的servlet之后执行

执行流程

  1.  浏览器发起请求some.do到DispatcherServlet
  2. 中央调度器将请求转发到处理器映射器
  3. 处理器映射器:框架吧实现了HandlerMapper接口的类都叫映射器,根据请求从springmvc容器中获取处理器对象(MyController controller=cx.getbean(“文件”))。将处理器对象和拦截器对象放到一个处理器执行链HandlerExecutionChain中保存,返回给中央调度处理器
  4. 中央调度处理器将这个执行链给处理器适配器(实现了HandlerAdapter接口的),用来执行处理器方法返回一个ModelAndView给中央调度处理器
  5. 中央调度处理器将这个给视图解析器(需要实现ViewResoler接口,也就是mvc中配置的),用来组成视图的完整路径,使用前缀。后缀创建view对象
  6. DispatcherServlet将上面的view对象获取到之后调用一个方法,将model中的数据存放到request域中,请求结束。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值