栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JavaWeb学习笔记-part10-SpringMVC

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaWeb学习笔记-part10-SpringMVC

1 概述

springmvc是基于spring的一个servlet升级版,实际上是spring的一个模块,专门做web开发的。

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

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

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

web开发底层是servlet,springmvc中有一个对象是servlet:DispatcherServlet。

DispatcherServlet:负责接收用户的所有请求,用户吧请求给了DispatcherServlet,之后DispatcherServlet把请求转发给我们的Controller对象,最后是Controller对象处理请求。

1.1 简介

SpringMVC又称Spring Web MVC。是spring框架的一部分。

1.2 优点
  1. 基于MVC架构:功能分工明确。解耦合

  2. 容易理解,上手快,使用简单:SpringMVC是轻量级的,可以快速开发一个注解的SpringMVC项目。

  3. 作为Spring框架的一部分,能够使用Spring的IoC和Aop。方便整合其他框架

  4. SpringMVC强化注解的使用,在控制器,Service,Dao都可以使用注解,方便灵活。

1.3 第一个注解的SpringMVC项目 1.3.1 新建web maven工程

这次我们创建的maven-apache-webapp骨架的项目

1.3.2 加入依赖

    
        junit
        junit
        4.11
        test
    
​
    
        javax.servlet
        javax.servlet-api
        3.1.0
        provided
    
​
    
        org.springframework
        spring-webmvc
        5.2.5.RELEASE
    
1.3.3 中央调度器(DispatcherServlet)
  1. DispatcherServlet叫做中央调度器,是一个servlet,它的父类是集成HttpServlet

  2. DispatcherServlet也叫做前端控制器(front controller)

  3. 负责创建springmvc容器对象,读取xml配置文件,创建文件中的Controller对象

  4. DispatcherServlet负责接收用户提交的请求,调用其他的自定义控制器对象,并把请求的处理结果显示给用户

中央调度器(DispatcherServlet)的配置:

在web.xml中配置servlet信息



​
    
    
    
        myweb
        org.springframework.web.servlet.DispatcherServlet
​
        
        
            
            contextConfigLocation
            
            classpath:springmvc.xml
        
​
        
        
        1
    
​
    
        myweb
        
        *.do
    
1.3.4 创建发送请求的页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


    

第一个springmvc项目

   

发起some.do请求

1.3.5 创建控制器类(Controller)
  1. 在类的上面加入@Controller注解,创建对象,并放入到springmvc容器中

  2. 在类中的方法上面加入@RequestMapping注解

package com.pjh.controller;
​
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
​

@Controller
public class MyController {
​
    
​
    
    @RequestMapping(value = {"/some.do", "/first.do"})
    public ModelAndView doSome() {
        //创建返回mv对象
        ModelAndView mv = new ModelAndView();
        //添加数据,框架在请求最后把数据放入到request作用域
        //request.setAttribute()
        mv.addObject("msg", "some.do请求已处理,来自SpringMVC");
        mv.addObject("fun", "执行的doSome方法");
​
        //指定视图,完整路径
        //框架对视图执行的forward操作,即
        //request.getRequestDispather().forward()
        //mv.setViewName("/show.jsp");
​
        //当配置视图解析器后,可以使用逻辑名称(文件名字),指定视图路径
        //框架会使用视图解析器的前缀+逻辑名称+后缀 组成完整路径,这里是字符串连接操作
        mv.setViewName("show");
        //返回mv
        return mv;
    }
}
1.3.6 创建显示结果的页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


    show.jsp获得的结果
   msg:${msg}
   fun:${fun}
1.3.7 创建springmvc的配置文件(spring的配置文件一样)
  1. 声明组件扫描器,指定@Controller注解所在的包名

  2. 声明视图解析器,帮助处理视图的。



​
    
    
    
    
        
        
        
        
    
1.3.8 分析springmvc请求的发送过程
  1. 发起some.do

  2. tomcat ( Web.xml ---- url-pattern知道*.do的请求发送给DispatcherServlet )

  3. DispatcherServlet ( 根据springmvc.xml配置知道some.do ---- doSome方法 )

  4. DispatcherServlet把some.do转发给MyController.doSome()方法

  5. 框架执行doSome()把得到ModelAndView进行处理,转发到show.jsp

1.3.9 分析springmvc执行过程
  1. tomcat启动,创建springmvc容器:核心在于DispatcherServlet的init方法,他会创建一个spring容器并且把它加入到ServletContext中成为全局变量

  2. 请求的处理过程:核心方法是DispatcherServlet的doDispatch方法,它会调用请求对应控制器中的对应方法

2 注解式开发 2.1 @RequestMapping 2.1.1 在类的上方使用

属性value中,写所有请求地址的公共部分,叫做模块名称。

2.1.2 method属性

可以设置请求的方式:GET、POST等

它的值是RequestMethod的枚举值,例如:

表示get请求方式,RequestMethod.GET; 表示post请求方式,RequestMethod.POST;

@RequestMapping(value = {"/some.do", "/first.do"}, method = RequestMethod.GET)
@RequestMapping(value = {"/other.do", "/second.do"}, method = RequestMethod.POST)

没有设置该属性时,访问目标方法没有限制。

2.2 控制器处理用户参数
  1. 为方法增加上HttpServletRequest、HttpServletResponse、HttpSession的形参

  2. 直接为方法增加上请求中携带的请求参数

2.2.1 逐个接收参数
package com.pjh.controller;
​
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
​
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
​
@Controller
public class MyController {
    
    @RequestMapping(value = "/receiveproperty.do")
    public ModelAndView doReceiveProperty(String name, int age) {
        //可以在方法中直接使用name,age
        ModelAndView mv = new ModelAndView();
        mv.addObject("myname", name);
        mv.addObject("myage", age);
        mv.setViewName("show");
​
        return mv;
    }
}

注意:

  1. 在框架进行类型转换时,可能出现无法转换的情况,例如age为空时和age不为整数时,这时服务器会阻止请求调用方法,可以用Integer替换形参int,来避免为空的情况

  2. 如果采用post请求方式,输入中文参数会出现乱码,这时需要手动设置response的encoding为utf-8,如果存在多个方法,可能就要设置多次,这时可以采用过滤器来解决重复代码。 过滤器可以自定义,也可以使用框架自带的 CharacterEncodingFilter。 在web.xml中声明字符编码过滤器:

    
        characterEncodingFilter
        org.springframework.web.filter.CharacterEncodingFilter
        
        
            encoding
            utf-8
        
        
        
            forceRequestEncoding
            true
        
        
        
            forceResponseEncoding
            true
        
    
    
    
        characterEncodingFilter
        
    @RequestMapping(value = "/receiveparam.do")
    public ModelAndView doReceiveParam(@RequestParam(value="rname", required = false) String name,@RequestParam(value = "rage", required = false) int age) {
        //可以在方法中直接使用name,age
        ModelAndView mv = new ModelAndView();
        mv.addObject("myname", name);
        mv.addObject("myage", age);
        mv.setViewName("show");
        return mv;
    }

2.2.2 对象参数接收
package com.pjh.controller;

import com.pjh.vo.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class MyController {
    
    @RequestMapping(value = "/receiveobject.do")
    public ModelAndView doReceiveObject(Student student) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("myname", student.getName());
        mv.addObject("myage", student.getAge());
        mv.addObject("mystudent", student);
        mv.setViewName("show");

        return mv;
    }
}

注意:使用对象参数接收,@RequestParam没有任何效果

2.3 处理器方法的返回值 2.3.1 ModelAndView

Model储存要返回的数据,最后存到resquest里面;View储存要转发的页面,使用forward。

如果当前请求既要返回数据,又要跳转页面,使用MV是非常合适的。

但是如果只需要其中一部分(Model或者View),就有些多余了。

2.3.2 String

如果只是要跳转页面,返回String是最恰当的。

如果没有@ResponseBody注解,字符串表示视图名称。

package com.pjh.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;

@Controller
public class MyController {

    
    @RequestMapping("/returnString-view.do")
    public String doReturnview(HttpServletRequest request, String name, Integer age) {
        System.out.println("myName: " + name + " myAge: " + age);
        //可以自己手动添加数据到request
        request.setAttribute("myname", name);
        request.setAttribute("myage", age);
        //show 逻辑视图名称,需要项目中配置了视图解析器
        //框架对视图执行forward转发操作
        return "show";
    }

    
    @RequestMapping("/returnString-view.do")
    public String doReturnview2(HttpServletRequest request, String name, Integer age) {
        System.out.println("myName: " + name + " myAge: " + age);
        //可以自己手动添加数据到request
        request.setAttribute("myname", name);
        request.setAttribute("myage", age);
        //完整视图路径,项目中不能配置视图解析器
        //框架对视图执行forward转发操作
        return "/WEB-INF/view/show.jsp";
    }
}

如果有@ResponseBody注解,字符串表示数据。

文件的格式datatype应该是text/plain,此时要自行设置响应头的编码集:

@RequestMapping(value = "...", produces="text/plain;charset=utf-8")

2.3.3 void

不能表示数据,也不能表示视图。

在处理ajax的时候可以使用void返回值。通过Responce输出数据。响应ajax请求。

ajax请求服务端返回的就是数据,和视图无关。

2.3.4 对象Object

这个Object可以是Integer、String、自定义对象、Map、List等,但是不能是逻辑视图。可以使用这个对象表示的数据,响应ajax请求。

ajax主要接收json的数据格式:

  1. 首先需要加入依赖,springmvc默认使用jackson

  2. 在springmvc的配置文件中加入注解驱动

    注意:此处的annotation-driven一定选择mvc的

  3. 在处理器上面加上@ResponseBody注解

    @RequestMapping("/returnObject.do")
    @ResponseBody
    public Student doReturnObject(String name, Integer age){
        System.out.println("myName: " + name + " myAge: " + age);
        //处理ajax,使用json做数据的格式
        Student student = new Student();
        student.setAge(age);
        student.setName(name);
    
        return student;
    }

内部原理:

  1. 注解驱动。

    注解驱动实现的功能是完成java对象到json,xml,text,二进制等数据格式的转换。

    该标签加入配置文件后,会自动创建HttpMessageConverter接口的7个实现类对象,包括

     HttpMessageConverter接口:消息转换器

    功能:

    定义了java转为json,xml等数据格式的方法;这个接口有很多的实现类,这些实现类完成java对象的转换。

    查看HttpMessageConverter源码,可以找到下面两个方法,是给控制器类把结果输出给浏览器时使用:

    //canWrite:作用检查处理器方法的返回值,能不能转为mediaType表示的数据格式 
    boolean canWrite(Class clazz, @Nullable MediaType mediaType);
    
    //write:把处理器方法的返回值对象,调用jackson中的ObjectMapper转为json字符串
    void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)			throws IOException, HttpMessageNotWritableException;

    常用的实现类有:StringHttpMessageConverter和MappingJackson2HttpMessageConverter。

  2. @ResponseBody注解

    放在处理器方法上面,通过Responce输出数据,响应ajax请求的。

注意:

  1. 返回List对象时,是转换成json数组再传递给浏览器

2.4 中央调度器中的url-pattern

tomcat本身能够处理静态资源的访问,例如html、image、js文件等。

这源于tomcat的web.xml文件有一个servlet名称是default,在服务器启动时自动创建。

它能被所有web应用使用,主要服务于静态资源文件,能够处理所有未被映射(mapping)的请求。


    default
    org.apache.catalina.servlets.DefaultServlet
    
        debug
        0
    
    
        listings
        false
    
    1



    default
    /

注意,default的mapping用的是斜杠"/",这就表示静态资源文件和未被映射的请求都由这个default处理。

如果,在自己的项目中的中央调度器中url-pattern标签中使用斜杠,会替代tomcat提供的default servlet。这就导致所有对静态资源的访问都交给中央调度器处理,但是一般情况下,它不能够处理静态资源,没有控制器对象能够处理静态资源的访问。

如果使用了斜杠,那么我们需要处理静态资源的访问请求,有两种方式:

  1. 需要在springmvc配置文件中加入

    原理是,在加入这个标签之后,控制器会创建一个DefaultServletRequestHandler的处理器对象。

    DefaultServletRequestHandler处理器对象:可以把接收的请求转发给tomcat的default这个servlet。

    但是这个标签和@RequestMapping注解有冲突,所以需要加入注解驱动(见2.3.4)来解决冲突。

  2. 在配置文件中加入

    原理是,加入后会创建一个ResourceHttpRequestHandler这个处理器对象。

    ResourceHttpRequestHandler处理器对象:可以处理对静态资源的访问

    标签有两个属性:

    mapping:访问静态资源的uri地址,使用通配符**

    location:静态资源在你的项目中的目录位置

    例如:

4.3 拦截器
  1. 拦截器是SpringMVC中的一种,需要实现HandlerIntercepter接口

  2. 拦截器给过滤器类似,功能方向侧重点不同。过滤器是用来过滤请求参数的,设置编码字符集等工作。 拦截器是拦截用户的请求,做请求要做判断处理的。

  3. 拦截器是全局的,可以对多个Controller做拦截。 一个项目种可以由0个或多个拦截器,一起拦截用户的请求。 拦截器常用在:用户登陆处理,权限检查,记录日志。

    一个过滤器可以拦截多个用户请求,也是aop思想

使用步骤:

  1. 定义类实现HandlerInterceptor接口

  2. 在springmvc配置文件中,声明拦截器,让框架知道拦截器的存在

拦截器的执行时间:

  1. 在请求处理之前,也就是controller类中的方法执行之前先被拦截。

  2. 在控制器方法执行之后也会执行拦截器

  3. 在请求处理完成后也会执行拦截器

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/390221.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号