springMVC nodes

springMVC:基于spring的一个框架,实际上就是spring的一个模块,专门做web开发的
理解为servlet的一个升级
springMVC能够创建对象,放到容器中(springMVC容器),springMVC容器中放的是控制器对象
@Controller创建控制器对象,把对象放在springMVC容器中,把创建的对象当作控制器使用,这个控制器对象能接受用户的请求,显示处理结果,就当做是一个servlet使用
@Contorller注解创建的是一个普通对象,不是servlet,springMVC赋予控制器对象一些额外的功能
springMVC中有一个对象是servlet:DispatherServlet:负责接受请求,之后DiapatherServlet把请求转发给Controller对象,最后是Controller对象处理

  1. 加入的依赖
<!--        servlet依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
<!--        springmvc依赖,带入spring依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
  1. springmvc.xml中声明组件扫描器
<!--    声明组件扫描器-->
    <context:component-scan base-package="com.yixia.controller"/>
<!--    声明springmvc框架中的视图解析器,帮助开发人员配置视图文件的路劲-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--        前缀:视图文件的路径-->
        <property name="prefix" value="/WEB-INF/view/"/>
<!--        后缀,视图文件的扩展名-->
        <property name="suffix" value=".jsp"/>

    </bean>
  1. web.xml中创建中央调度器
<?xml version="1.0" encoding="UTF-8"?>
<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的核心对象DispatherServlet
    需要在tomcat服务器启动后,创建DispatherServlet对象的示例,同时创建springmvc对象,
    读取springmvc的配置文件,当用户发送请求时,就可以访问对象了

-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--        自定义springmvc读取的配置文件的位置-->
        <init-param>
<!--            springmvc的配置文件的位置的属性-->
            <param-name>contextConfigLocation</param-name>
<!--            指定自定义文件的位置-->
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
<!--        在tomcat启动后,创建servlet对象
            load-on-startup:表示tomcat启动后创建对象的顺序,他的值时整数,数值越小,tomcat创建对象的时间越早
-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
<!--        使用框架的时候url-pattern可以使用两种值
            1.使用扩展名方式,语法*。xxxx,xxxx是自定义的扩展名,常用的方式是*.do,*.action,*.mvc等
            2.使用斜杠"/"

-->
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>


</web-app>

  1. 创建普通Controller类
@Controller
public class MyController {
    /**
     * 处理用户提交的请求,sprngmvc中是使用方法来处理的
     * 方法是自定义的额,有多种放回值,多种参数,方法名自定义
     */

    /**
     * 准备使用doSome方法处理some.do请求
     * @RequestMapping:请求映射,作用是把一个请求地址和一个方法绑定在一起
     *                  一个请求指定一个方法处理
     *       属性:1.value是String,表示请求的url地址的(some.do)
     *              value必须是唯一的,不能重复,在使用是,推荐地址以“/"
     *       位置:1.在方法的上面,常用的
     *              2。在类的上面
     *    说明:使用RequestMapping修饰的方法叫做处理器方法或者控制器方法
     *    使用@RequestMapping修饰的方法可以处理请求,类似于Servlet中的doGet,doPost
     * @return
     *      ModelAndView:表示本次的处理结果
     *          model:数据,请求处理完成后,要显示给用户的数据
     *          Viem:视图,比如jsp等
     *
     */
    @RequestMapping(value = "/some.do")
    public ModelAndView doSome(){
        ModelAndView modelAndView = new ModelAndView();
        //添加数据,框架在请求的最后把数据放到request作用域,
        //request.setAttribute("msg","欢迎使用springmvc做web开发");
        modelAndView.addObject("msg","欢迎使用springMvc做web开发");
        modelAndView.addObject("fun","执行的是dpSome方法");

        //指定视图,指定视图的完整路径
        //框架对视图执行的forward操作,request.getRequestDiapather("/show.jsp").forward();
        modelAndView.setViewName("/show.jsp");
        
        //当配置了视图解析器,可以使用逻辑名称(文件名),指定视图
        //框架会使用视图解析器前缀+后缀 组成完整路径,就是字符串连接
        modelAndView.setViewName("show");

        return modelAndView;
    }
}

WEB_INF下的文件对用户是不开放的

普通类Controller的注解介绍

  1. 设置模块名称和请求方式
/**
 1. @RequestMapping:
 2.      value:所有请求地址的公共部分,叫做模块名称
 3.      位置放在类上
 */
@RequestMapping("/test")
@Controller
public class MyController {
    /**
     *  @RequestMapping:请求映射
     *          属性:method,表示请求参数,他的值RequestMethod类枚举值
     *              get-》RequestMethod.GET
     *              如果没有表示method的值的话,对请求方式没有限制
     *
     * @return
     */
    @RequestMapping(value = "/some.do",method = RequestMethod.GET)
    public ModelAndView doSome(HttpServletRequest request,
                               HttpServletResponse response,
                               HttpSession session){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg","欢迎使用springMvc做web开发");
        modelAndView.addObject("fun","执行的是dpSome方法");
        modelAndView.setViewName("show");
        return modelAndView;
    }
}
  1. 接受请求参数

HttpServletRequest
HttpServletResponse
HttpSession
用户提交的数据
-----逐个接收
-----对象接收

    /**
     *  逐个接收请求参数:
     *      要求:处理器(控制器)的方法的形参名和请求中参数名必须一致
     *              同名的请求参数赋值给同名的形参
     *框架接收请求参数:
     *  1.使用request对象接受请求参数
     *      String strName = request.getParameter("name");
     *      String strAge = request.getParameter("age");
     *  2.springmvc框架通过DispatcherServlet 调用MyController的doSome()方法
     *      调用时,按名称对应,赋值给形参
     *      dosome(strName ,integer.valueof(strAge)
     *      框架会提供类型转换的功能,将string转化为其他类型
     *
     * 400状态码是客户端错误,表示提交请求参数的过程中出现了问题
     * @return
     */
    @RequestMapping(value = "/some.do",method = RequestMethod.POST)
    public ModelAndView doSome(String name,Integer age){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("myname",name);
        modelAndView.addObject("myage",age);
        modelAndView.setViewName("show");
        return modelAndView;
    }
  1. 设置过滤器,解决post乱码问题
<!--    注册声明过滤器,解决post请求乱码的问题-->
    <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>
<!--        强制请求对象(HttpServletRequest)使用encoding编码的值-->
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
<!--        强制应答对象(HttpServletResponse)使用encoding编码的值-->
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
<!--        表示强制所有的请求先通过过滤器处理-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  1. 解决请求中参数和形参名不一样的问题
    /**
     *  @RequestParam:解决请求方法中形参名不一样的问题
     *      属性:1.value:请求中的参数名称
     *           2.required 是一个boolean,默认是true
     *                  true:表示请求中必须包含此参数
     *      位置:在处理器方法的形参定义的前面
     *
     *
     * @param name
     * @param age
     * @return
     */
    @RequestMapping(value = "/some.do",method = RequestMethod.POST)
    public ModelAndView doSome(@RequestParam("pname") String name,
                               @RequestParam("page") Integer age){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("myname",name);
        modelAndView.addObject("myage",age);
        modelAndView.setViewName("show");
        return modelAndView;
    }
  1. 对象接收参数
    /**
     * 处理器方法形参是Java对象,这个对象的属性名和请求参数一样的
     * 框架会创建形参的Java对象,给属性赋值,请求中的参数是name,框架会调用setName() 
     * @return
     */
    @RequestMapping(value = "/some.do",method = RequestMethod.POST)
    public ModelAndView doSome(Student myStudent){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("myname",myStudent.getName());
        modelAndView.addObject("myage",myStudent.getAge());
        modelAndView.setViewName("show");
        return modelAndView;
    }
  1. 返回值ModelAndView

如果处理器方法处理完后,需要跳转到其他资源,且又要在跳转的资源间传递数据,此时处理器方法返回ModelAndView较好,需要在方法中添加ModelAndView对象,否则有的多余

  1. 返回值String
    String表示视图,可以逻辑名称,也可以是完整视图路径
    /**
     * 处理器方法返回String,表示逻辑视图名称,需要配置视图解析器
     *
     */
    @RequestMapping(value = "/some.do",method = RequestMethod.POST)
    public String doSome(Student myStudent){

        System.out.println("doReturnView,name="+myStudent.getName()+"age="+myStudent.getAge());
        //show :逻辑视图名称,项目中配置了视图解析器
        //如果使用完整的视图路径,项目中不能使用视图解析器
        //框架对视图执行forward转发操作
        return "show";
    }
  1. 返回值是void(可以用于ajax )

不能表示数据,也不能表示视图
处理ajax时,可以使用void返回值,通过HttpServletRequest输出数据。响应ajax
ajax请求服务端返回的就是数据,和视图无关

//使用json和ajax
  1. 返回对象Object
    返回对象,是数据和对象无关,可以响应ajax请求
/**
* 加入json依赖
* 在springmvc的配置文件中之间加入   
* 		<mvc:annotation-driven>注解驱动
* 		替代:json = om.writeValueAsString(student)
* 在处理器方法上面加上@ResponseBody注解
*      	response.setContentTyp("application/json;charset=utf-8”);
*		PrintWriter pw = response.getWriter();
*		pw.println(json);
**/

//springmvc处理器方法返回object,可以转为json输出到浏览器,响应ajax的内部原理
/**1.<mvc:annotation-driven> 注解驱动
 1. 注解驱动实现的功能,完成java对象到json,xml,text,二进制等数据格式的转换
 2. HttpMessageConverter接口:消息转换器
 3. 功能:定义了Java转化为json,xml等数据格式的方法,这个接口有很多的实现类
 4. 这些实现类完成java对象多json,java对象到xml,java对象到二进制数据的转换
 5. 
 6.     boolean canWrite(Class<?> var1, @Nullable MediaType var2);
 7. 检查对象是为能转换为var2
 8. 	void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3)
 9.  
**/
  1. 返回List对象
//跟返回对象的方式是一样的
  1. 返回Map(一般不用)
  2. 返回String数据
/**
 1. 处理器方法返回的是String,String表示数据,不是视图
 2. 区分返回值是数据还是视图,看有没有@ResponseBody注解
 3. 如果有注解,就是数据,不是视图
 4.  5. 出现乱码问题,
 6. 默认使用“text/plain;charset=iso-8859-1"作为contentType,导致有乱码
 7. 解决方案:给ReuqestMapping增加一个属性produces,使用这个属性指定新的contentType
**/

补充:web中有一个default配置,加载静态资源和未映射到其他servlet的请求

访问静态资源的问题
中央调度器的地址使用"/"

当项目中使用了"/",会代替tomcat中的default,tomcat不会自动加载静态资源和未映射到其他servlet的请求

  1. 第一种静态资源处理方式
    <!--    第一种处理静态资源的方式
            需要在springmvc配置文件加入        <mvc:default-servlet-handler/>
            原理:加入这个标签后,框架会创建控制类对象DefaultServletHttpRequestHandler(类似于mycontroller)
            DefaultServletHttpRequestHandler 可以将请求转给tomcat处理

    -->
    <mvc:default-servlet-handler/>
  1. 第二种静态资源处理方式
<!--    第二种处理静态资源的方式
             <mvc:resources 加入后框架会创建ResourceHttpRequestHandler对象
             让这个对象访问静态资源,不依赖tomcat
             mapping : 访问静态资源的uri地址,使用通配符**
             location:静态资源在你的项目种的目录位置
-->
    <mvc:resources mapping="/image/**" location="/image/" />
    <mvc:resources mapping="/html/**" location="/html/" />
    <mvc:resources mapping="/js/**" location="/js/" />
    <!--    mvc:resources 和@RequestMapping有一定冲突-->
    <mvc:annotation-driven/>

地址分类

  1. 绝对地址:带有协议名称的是绝对地址:http://www.baidu.com
  2. 相对地址:没有协议开头的,例如:user/some.do
    相对地址不能独立使用,必须有一个参考地址,通过参考地址+相对地址本身才能指定资源

在index.jsp发起user/some.do请求,访问地址变为http://localhost:8080/ch06_path/user/some.do
当你的地址没有斜杠开头,例如user/some.do,当你点击链接时,访问的地址是当前页面的地址,加上链接的地址
http://localhost:8080/ch06_path/+user/some.do
当访问的地址加斜杠的话,/user/some.do,参考地址为http://localhost:8080/需要使用/ch06_path/user/some.do

解决访问地址的问题

  1. 加入${pageContext.request.contextPath},可以获得当前页面名称
  2. 加入一个base标签,是html语言中的标签,表示当前页面中,访问地址的基地址。界面中所有没有”/" 开头的地址,都是以base标签中的地址为参考地址
    使用base中的地址+user/some.do
<% 
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/";
%>

<base href="<%basePath%>" />

异常处理

  1. springmvc框架采用的是统一的,全局的异常处理
    2.把controller中的所有异常处理都集中到一个地方,采用aop的思想,把业务逻辑和异常处理的代码分开,解耦合
    3.使用两个注解:

/**
 * @ControllerAdvice:控制器增强
 *          位置:类的上面
 *     特点:必须让框架知道注解所在的包名,需要在springmvc中声明文件声明组件扫描器
 *          指定@ControllerAdvice所在的包名
 *
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    //定义方法,处理发生的异常
    /**
     *      处理异常的方法和控制器方法的定义一样,可以有多个参数,可以有ModelAndView
     *            String,void,对象类型的放回值
     *      形参:Exception,表示Controller中抛出的异常对象
     *      通过形参可以获取发生的异常信息
     *
     * @ExceptionHandler:表示异常的类型,当发生这个异常时,由当前方法处理
     */
    @ExceptionHandler(NameException.class)
    public ModelAndView doNameException(Exception ex){
        //处理NameExceeptin异常
        /**
         * 异常发生处理逻辑,
         *  1.需要把异常记录下来,记录到数据库,日志文件
         *      记录日志放生的时间,放个方法发生的,异常错误内容
         *   2.发送通知,把异常的信息通过邮件,短信,微信发送给相关人员
         *   3,给用户友好提示
         */
        return new ModelAndView();
    }

    //处理其他异常,不知到的类型异常
    @ExceptionHandler
    public ModelAndView doOtherException(Exception ex){
        return new ModelAndView();
    }
}

拦截器
1>拦截器是springmvc中的一种,需要实现HandlerInterceptor接口
2.拦截器和过滤器类似,过滤器是用来处理编码集和处理请求参数的
拦截器是用来拦截请求,对请求做判断处理的
3.拦截器是全局的,可以对多个Controller做拦截
一个项目可以有一个或者多个拦截器,通常用来用户登陆处理,权限检查,记录日志

拦截器的使用步骤
1.定义类实现HandlerInterceptor接口
2.在springmvc中声明拦截器

拦截器的执行时间
1.在请求处理之前,也就是controller类中方法的执行之前先被拦截
2.在控制器方法执行之后也会执行拦截器
3.在请求处理完成后也会执行拦截器

1.springmvc配置文件

<!--        拦截器声明:可以有一个或者多个-->
    <mvc:interceptors>
<!--        声明一个拦截器-->
        <mvc:interceptor>
<!--            指定拦截的请求uri地址
                    path:就是url地址,可以使用通配符 **
-->
            <mvc:mapping path="/test/**"/>
            <bean class="com.yixia.handler.MyInterceptor">

            </bean>
        </mvc:interceptor>
    </mvc:interceptors>

2.拦截器中方法的介绍

    /**
     *      perHander:预处理方法
     *      参数:
     *          Object handler:被拦截的控制器对象
     *      返回值:boolean
     *          false:
     *          true:
     *      特点:1.方法在控制器方法(MyController的dosome)之前先执行的
     *                  用户的请求首先到达此方法
     *           2.在这个 方法中可以获取请求信息,验证请求是否符合要求
     *              可以验证用户是否登录,是否有权力访问某个拦截地址
     *              验证失败,拦截请求,请求不被处理
     *              验证成果,请求放行,控制器方法才能执行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器的MyInterceptor的preHandle方法");
        return true;

    }

    /**
     * postHandle:后处理方法
     *      参数:
     *          Object handler:被拦截的控制器对象
     *          ModelAndView mv:处理器方法的返回值
     *
     *      特点:
     *          1,在处理器方法之后执行的(MyController,doSome())
     *          2。能够获取到处理方法的fanhuizhiModelAndView,可以修改ModelAndView中的
     *          数据和视图,可以影响到最后的执行结果
     *          3.主要是原来的执行结果做二次修正
     *
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器的MyInterceptor的postHandle方法");
    }

    /**
     *  afterCompletion:最后执行的方法
     *      参数:
     *          Object handler:被拦截的控制器对象
     *          Exception ex:程序中发生的异常
     *       特点:
     *          1.在请求处理完成后执行的,框架中规定是当你的视图处理完成后,对视图执行forward,就认为请求处理完成
     *          2.一般做资源回收工作,程序请求过程中创建了一些对象,在这里可以删除,把占用的内存回收
     *
     *
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("拦截器的MyInterceptor的afterCompletion方法");
    }

3.多个拦截器的执行顺序
有先后顺序

4.拦截器和过滤器的区别

1.过滤器是servlet中的对象,拦截器是框架中的对象
2.过滤器是tomcat服务器创建的对象,拦截器是springmvc容器中创建的对象
3.过滤器有一个执行点,拦截器有3个执行点
4.过滤器实现filter接口,拦截器实现HandlerInterceptor接口
5.过滤器是在拦截器之前先执行的,只有通过post方法才会通过中央调度器
6.过滤器可以处理jsp,js,html等,拦截器主要是针对Controller对象,如果请求不能被DispatcherServlet接收,这个请求不会被拦截器接收

springmvc内部处理请求的流程

1.用户发起请求
2.DispatcherServlet接受请求,把请求转发给处理器映射器,
-------处理器映射器,是springmvc中的对象,框架把实现了HandlerMapper的类都叫做映射器
------处理器映射器的作用,根据请求从springmvc容器中获取处理器对象,getbean,把找到的对象放到一个叫做处理器执行链的类中保存
---------HandlerExcutionChain:类中保存着,处理器对象(controller)和羡慕中所有的拦截器list
3.DispatcherServlet把执行链中的对象交给处理器适配器对象,
------处理器适配器:springmvc中的对象,需要是实现HandlerAdapter接口
处理器适配器作用,执行处理器方法,(Controller.dosome()方法执行)
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十六进一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值