一、SpringMVC是什么

  • 是基于spring的一个框架,实际上就是spring的一个模块,专门做web开发的
  • 可以理解为Servlet的升级
  • web开发底层就是Servlet,框架是在Servlet基础上面添加一些功能,做web项目更方便
  • SpringMVC能够创建对象,放入到容器中(SpringMVC的容器) SpringMVC里面放的是控制器对象
  • 我们要做的是使用**@Controller**注解创建控制器对象,把对象放入到SpringMVC容器中,把创建的对象作为控制器使用
  • 这个控制器对象能接收用户的请求,显示处理结果,就当作是一个servlet使用【并不是servlet,就是普通对象】
    • 使用@Controller创建的对象,其实就是个普通的对象,springMVC赋予了他控制器的能力
  • Springmvc底层访问依然是DispatcherServlet他的两大作用:

    • 创建WebApplicationContext对象,读取配置文件,进而控制控制器对象
    • 本身就是一个Servlet,要接收请求,显示结果

      二、springMVC的工作模式

  • web开发底层时servlet,springmvc中有一个对象是Servlet:DispatcherServlet(中央调度器) 负责接收用户所有请求,然后把请求转发给Controller对象,最后是Controller对象处理请求

    • Index.jsp———>DispatherServlet———>转发,分配给——->Controller对象(@Controller注解创建的对象)

三、SpringMVC入门案例

1、创建maven项目,webapp

  1. 因为maven创建的web项目中的 web.xml文件是 2.3版本的,需要重新创建一下
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
  6. http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  7. version="4.0">
  8. </web-app>

2、加入依赖 spring-mvc 、servlet、

  1. <!--springMVC的依赖-->
  2. <dependency>
  3. <groupId>org.springframework</groupId>
  4. <artifactId>spring-webmvc</artifactId>
  5. <version>5.2.5.RELEASE</version>
  6. </dependency>
  7. 会间接的把spring的依赖都加入到项目中,

3、在web.mxl文件中,注册springmvc框架的核心对象 DispatcherServlet

  • DispatcherServlet :中央调度器【父类继承Servlet,本身就是Servlet,具备所有servlet的功能】
  • DispatcherServlet:也叫前端控制器

    • 负责去接收用户提交的请求,调用其他的控制器对象 ,并把请求的处理结果显示给用户

      1. <servlet>
      2. <!--springmvc在创建容器对象时,读取的配置文件默认是 /WEB-INF/<servlet-name>-servlet.xml
      3. 也就是说 读取的就是下面这个name 后面加 -servlet.xml,
      4. 因为这个规则不方便,所以就不用这个默认的规则,去自定义文件所在的位置-->
      5. <servlet-name>springmvc</servlet-name>
      6. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      7. <!--设置在服务器启动时,马上创建DispatcherServlet对象-->
      8. <!--load-on-startup:在启动时进行加载,
      9. 数字表示tomcat启动后创建的顺序,数制越小创建的对象时机越早 >=0的整数-->
      10. <!--自定义文件所在位置-->
      11. <init-param>
      12. <!--指定SpringMVC的配置文件的属性,必须是contextConfigLocation-->
      13. <param-name>contextConfigLocation</param-name>
      14. <!--自定义文件的位置 classpath:-->
      15. <param-value>classpath:springmvc.xml</param-value>
      16. </init-param>
      17. <load-on-startup>1</load-on-startup>
      18. </servlet>
      19. <!--设置servlet-mapping-->
      20. <servlet-mapping>
      21. <servlet-name>springmvc</servlet-name>
      22. <!--可以使用两种值,
      23. 1.使用扩展名的方式,语法*.xxxxxx是自定义的拓展名常用的有*.do*.action*.mvc
      24. 表示以.do结尾的请求,都会被该servlet-mapping处理 (没有/)
      25. http://localhost:8080/myweb/some.do
      26. http://localhost:8080/myweb/other.do
      27. 2.使用"/"的方式
      28. -->
      29. <url-pattern>*.do</url-pattern>
      30. </servlet-mapping>

      image.png

      4、创建发起请求的页面

      未命名图片.png

      5、创建控制器类/后端控制器 @Controller

  1. 在类的上面加入@Controller注解,创建对象,放入到SpringMVC容器中
  2. 在中的方法上加入@RequestMapping注解

    • 方法是自定义的,可以有多种返回值,多种参数,方法名称自定义
    • @RequestMapping注解修饰的方法叫处理器方法

      1. @RequestMapping("/login.do")
      2. public ModelAndView doSome(){
      3. ModelAndView wv = new ModelAndView();
      4. return wv;
      5. }

      6、创建springMVC的配置文件

      (和spring的配置文件一样)

  3. 声明组件扫描器,指定controller注解所在的包名

    • 在resources目录下创建springmvc配置文件,和spring配置文件一样
    • 声明组件扫描器 **<context:component-scan base-package="com.yixuexi"/>**
  4. 声明视图解析器,帮助开发人员设置视图文件的路径

    • 为了防止用户恶意访问show.jsp, 把show.jsp放到 WEB-INF目录下,这样用户不可能在地址框搜索到
    • 配置视图解析器

      1. <!--视图解析器-->
      2. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      3. <!--前缀,视图文件的路径-->
      4. <property name="prefix" value="/WEB-INF/view/"/>
      5. <!--后缀,视图文件的拓展名-->
      6. <property name="suffix" value=".jsp"/>
      7. </bean>
    • 在WEB-INF目录下有一个 view目录,里面放着 show.jsp

未命名图片.png

  1. 注意:springmvc配置文件的名字要和web.xml文件中的这个属性中的值一致

为什么要在**tomcat**启动后,创建**DispatcherServlet**对象实例

  • 因为,DispatcherServlet在他创建的过程中,会同时创建springmvc容器对象,
  • 读取springmvc的配置文件,把配置文件中的对象都创建好,当用户发起请求时就可以直接使用对象了

    总结

  1. 先导入依赖
  2. 然后在web.xml文件中,创建DispachterServlet对象
  3. 然后创建类 在类上添加@Controller注解,
  4. 然后创建方法,方法返回值类型为M``odelAndView, 方法名随意
  5. 方法上添加@RequestMapping注解 value属性写 请求的uri地址,就是/login.do 或者 /register.do
  6. 在springmvc的配置文件中,声明组件扫描器,和视图解析器
  7. 然后处理完之后,可以在mv那个对象上,进行添加数据 addObject(key,value); setViewName(“视图文件”)

四、返回值ModelAndView对象使用

  1. ModelAndView mv = new ModelAndView();
  2. //指定数据,添加数据,框架在最后把数据放到了request作用域中
  3. //相当于 request.setAttribute("key","value"); 框架帮你做了
  4. mv.addObject("key","欢迎使用mvc做web开发");
  5. mv.addObject("function","执行的时doSome()方法");
  6. //指定视图,指定视图的完整路径
  7. //框架对视图执行的是forward操作,(请求转发)//request.getRequestDispatcher().forward() 框架帮你做了
  8. mv.setViewName("/show.jsp"); //没有配置视图解析器的时候,show.jsp还在webapp目录下
  9. //配置了视图解析器的时候,show.jsp在WEB-INF/view下,后缀也省了
  10. //直接使用文件的名称就可以了,框架自己去/WEB-INF/view/下去找show.jsp
  11. mv.setViewName("show")
  12. 说明:
  13. 使用@RequestMapping修饰的方法叫做处理器方法/通知器方法
  14. 使用@RequestMapping修饰的方法是可以处理请求的,类似于Servlet中的doGet() doPost()
  15. 返回值:ModelAndView 本次请求的处理结果
  16. Model:数据,请求处理完成后,要显示给用户的数据
  17. View:视图,比如jsp/html等等的

五、SpringMVC web.xml 固定配置

web.xml 固定代码

  1. <!--web.xml固定代码-->
  2. <servlet>
  3. <servlet-name>springmvc</servlet-name>
  4. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  5. <!--设置在服务器启动时,马上拆功能键DispatcherServlet对象-->
  6. <!--load-on-startup:在启动时进行加载,
  7. 数字表示tomcat启动后创建的顺序,数制越小创建的对象时机越早>=0的整数-->
  8. <init-param>
  9. <!--指定SpringMVC的配置文件的属性,必须是contextConfigLocation-->
  10. <param-name>contextConfigLocation</param-name>
  11. <!--自定义文件的位置classpath:-->
  12. <param-value>classpath:springmvc.xml</param-value>
  13. </init-param>
  14. <load-on-startup>1</load-on-startup>
  15. </servlet>
  16. <!--设置servlet-mapping-->
  17. <servlet-mapping>
  18. <servlet-name>springmvc</servlet-name>
  19. <!--可以使用两种值,
  20. 1.使用扩展名的方式,语法*.xxxxxx是自定义的拓展名常用的有*.do*.action*.mvc
  21. 表示以.do结尾的请求,都会被该servlet-mapping处理(没有/)
  22. http://localhost:8080/myweb/some.do
  23. http://localhost:8080/myweb/other.do
  24. 2.使用"/"的方式
  25. -->
  26. <url-pattern>/</url-pattern>
  27. </servlet-mapping>
  28. <!--注册过滤器,解决post请求中文乱码问题 web.xml文件配置-->
  29. <filter>
  30. <filter-name>characterEncodingFilter</filter-name>
  31. <!--CharacterEncodingFilter-->
  32. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  33. <!--设置项目中使用的字符编码-->
  34. <init-param>
  35. <param-name>encoding</param-name>
  36. <param-value>utf-8</param-value>
  37. </init-param>
  38. <!--强制请求对象,使用encoding编码的值-->
  39. <init-param>
  40. <param-name>forceRequestEncoding</param-name>
  41. <param-value>true</param-value>
  42. </init-param>
  43. <!--强制响应对象,使用encoding编码的值-->
  44. <init-param>
  45. <param-name>forceResponseEncoding</param-name>
  46. <param-value>true</param-value>
  47. </init-param>
  48. </filter>
  49. <filter-mapping>
  50. <filter-name>characterEncodingFilter</filter-name>
  51. <!--表示强制所有的请求先通过过滤器处理-->
  52. <url-pattern>/*</url-pattern>
  53. </filter-mapping>

springmvc.xml 固定代码

  1. <!--组件扫描器,用来扫描注解创建对象的-->
  2. <context:component-scan base-package="com.yixuexi"/>
  3. <!--视图解析器-->
  4. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  5. <!--前缀,视图文件的路径-->
  6. <property name="prefix" value="/WEB-INF/view/"/>
  7. <!--后缀,视图文件的拓展名-->
  8. <property name="suffix" value=".jsp"/>
  9. </bean>
  10. <!--springmvc响应AJAX 请求返回一个json数据的对象 添加注解驱动-->
  11. <mvc:annotation-driven/>
  12. <!--url-pattern是/时,配置访问静态文件,目录要求:静态文件都在static文件下-->
  13. <!--同时也需要上面那一句 <mvc:annotation-driven>-->
  14. <mvc:resources mapping="/static/**" location="/static/"/>
  15. 拦截器
  16. <!--声明拦截器,在框架中拦截器可以有0或多个-->
  17. <mvc:interceptors>
  18. <!--声明第一个-->
  19. <mvc:interceptor>
  20. <!--指定拦截的请求uri地址的
  21. path:就是uri地址,可以使用通配符 **
  22. **:表示任意的字符,文件,或者多级目录和目录中的文件
  23. /** : 表示所有的请求都会被拦截
  24. -->
  25. <mvc:mapping path="/**"/>
  26. <!--声明拦截器对象,表示访问上面那个地址的时候都由下面这个拦截器处理-->
  27. <bean class="com.yixuexi.handler.MyInterceptor"/>
  28. </mvc:interceptor>
  29. </mvc:interceptors>

六、@RequestMapping注解

准备使用doSome()方法处理前端页面发来的login.do的请求
@RequestMapping:请求映射,作用是把一个请求地址和一个方法绑定在一起

一个请求指定一个方法处理

1、属性:

1.**value**: 表示请求的uri地址 唯一值【login.do】

  • 在使用时,推荐以“/”开头
  • 可以是数组,{“/xxx”,”/xxx”,”/xxx”} (多个请求一个方法处理)

2.method:表示请求的方式,他的值是RequestMethod的枚举值

  • 如果没有指定的话,所有的请求方式都可以访问
  • 例如表示get请求方式,RequestMethod.GET ``或者``.POST
  • 如果该方法用的post请求,那么请求必须是post才能访问该方法【表单可以发post请求】 不按照对应的请求方式 报错 405
  • 前端发送请求 开头不需要 /

未命名图片.png

2、位置

  1. 在方法的上面【表示这个方法处理这个请求】
  2. 在类的上面 【集中的定义,把公用的提取出来】
    1. value: 所有请求地址的公共部分 ,也叫模块名称
    2. 如果请求是这样的 test/login.do test/register.do 的话就可以在类的上面添加@RequestMapping("/test") 注解,那么他的方法就不用加 “/test” 了 直接 /login.do就行了

image.png

七、请求的处理流程

1、springmvc请求的处理流程

第⼀步:⽤户发送请求⾄前端控制器DispatcherServlet
第⼆步:DispatcherServlet收到请求调⽤HandlerMapping处理器映射器
第三步:处理器映射器根据请求Url找到具体的Handler(后端控制器),⽣成处理器对象及处理器拦截器(如果 有则⽣成)⼀并返回DispatcherServlet
第四步:DispatcherServlet调⽤HandlerAdapter处理器适配器去调⽤Handler
第五步:处理器适配器执⾏Handler
第六步:Handler执⾏完成给处理器适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回 ModelAndView,ModelAndView 是SpringMVC 框架的⼀个底层对 象,包括 Model 和 View
第⼋步:前端控制器请求视图解析器去进⾏视图解析,根据逻辑视图名来解析真正的视图。
第九步:视图解析器向前端控制器返回View
第⼗步:前端控制器进⾏视图渲染,就是将模型数据(在 ModelAndView 对象中)填充到 request 域
第⼗⼀步:前端控制器向⽤户响应结果

image.png

2、springmvc执行过程分析 init源码分析

2.1 tomcat启动,创建容器的过程

  1. tomcat启动,先执行web.xml文件,然后通过load-on-startup标签中的1创建DispatcherServlet对象
  2. DispatcherServlet他的父类是继承HttpSerlvet的,他是一个Serlvet,在被创建时,会执行init方法。
  3. 在inut方法中会执行 new ClassPathWebApplicationContext(“文件地址”); 并把它放到全局作用域中
  4. 创建了容器,容器同时也创建了@Controller注解所在的对象,
  5. 这个controller对象放入到了springmvc的容器中,

3、组件说明

  1. **DispatcherServlet**

    前端控制器 用户请求到达前端控制器,它就相当于mvc中的c,DispatcherServlet是整个流程控制的中心,由他调用其他组件处理用户的请求,DispatcherServlet的存在降低了组件之间的耦合度

  1. **HandlerMapping**

    处理器映射器 HandlerMapping 负责根据用户发送的请求 uri 来找到对应的controller中的方法 springmvc提供了不同的映射器实现不同的映射方式,HandlerMapping会把找到映射返回给DispatcherServlet

  1. **Handler / controller**

    后端控制器 在DispatcherServlet的控制下,Handler对具体的用户请求进行处理

  1. **HandlerAdapter**

    通过HandlerAdapter对处理器进行执行,处理器适配器

  1. **ViewResolver**

    View Resolver 负责将结果转换成view 视图

  1. **View**

    SpringMVC框架提供了很多的View视图类型的支持 包括:jstlView,freemarkerView,pdfView,我们最常用的视图就是JSP

八、处理器方法的形参

处理器方法可以包含以下4类参数,这些参数springmvc会给自动赋值,直接使用就行
直接在处理器方法里面定义形参即可

  1. HttpServletRequest 请求
  2. HttpServletResponse 响应
  3. HttpSession 会话
  4. 请求中锁携带的请求参数
    1. @RequestMapping(value="/login.do",method=RequestMethod.POST)
    2. //直接在这里声明 上请求对象,响应对象,session对象就行
    3. Public ModelAndView test(HttpSession session,
    4. HttpServletRequest request,
    5. HttpServletResponse response){
    6. //从请求中得到数据 getParameter()
    7. String username = request.getParameter("username");
    8. ModelAndView mv=new ModelAndView();
    9. //添加到mv对象中,也就是请求作用域对象
    10. mv.addObject("key",username);
    11. //请求转发,到login.jsp, 这里配置了视图解析器,本来应该写 /WEB-INF/view/login.jsp的
    12. mv.setViewName("login");
    13. returnmv;
    14. }

    1、获取请求中携带的请求参数

    1.1 逐个获取

    要求:
  • 处理其方法的形参名,和请求中参数的name必须一致。
  • 同名的请求参数会自动赋值给同名的形参 ```java @RequestMapping(value=”/login.do”,method=RequestMethod.POST) //逐个接收,形参名必须和参数名一致才行 public ModelAndView login(String username,String password){ ModelAndView mv=new ModelAndView(); mv.addObject(“key”,username); mv.setViewName(“login”); return mv; }
  1. - 框架内部完成了 `String username = request.getParameter("username");`
  2. - 框架会提供类型转换的功能,能把`String`转换成`int`,`long`,`float`,`double `等类型和他的包装类型。
  3. - 注意:当提交的是空字符串 "",或者是"abc"时,无法进行int类型转换,所以会报错400
  4. - **状态码400:所有4xx报错都是客户端问题,400表示提交请求参数的时候,发生了问题。**
  5. - 建议使用包装类,不要使用基本数据类型,容易出错(但还是不能转换adc这种的,"" 不会报错)
  6. <a name="Kc1qV"></a>
  7. ### 1.2 对象接收
  8. > (参数多的话,使用对象接收会比较好)
  9. 创建一个类,类中的属性名和参数名一致,提供get set 方法和无参构造。<br />框架自动调用无参构造创建对象,再调用set方法 设置值。<br />前端发来的参数名称是name,框架自动调用 `setName()`方法<br />形参中也可以有多个对象,比如`Student`, `School`,`Address`
  10. <a name="puXaI"></a>
  11. ## 2、解决请求中参数和方法形参不一致
  12. 前端发来的请求,参数名是 `xingming`,`mima`<br />只能用在逐个接收的方案中
  13. <a name="c58e7047"></a>
  14. #### 2.1 `@RequsetParam`注解:
  15. 解决请求中参数名形参名不一致的问题<br />**属性:**<br />value:请求中参数的名称。<br />required:是要给布尔类型 [必须的]<br />true:表示这个请求中必须包含此参数。<br />false:如果没有这个参数也可以
  16. **位置**:在处理器方法的形参定义前面
  17. ```java
  18. @RequestMapping("/login")
  19. public String login(@RequestParam("xingming") String username
  20. @RequestParam("mima") String password
  21. ){
  22. }

九、处理器方法的返回值

1、返回ModelAndView

  1. ModelAndView mv = new ModelAndView();
  2. 返回数据部分 mv.addObject("key","zhangsan"); 最后是放到了request作用域中
  3. 返回视图部分 mv.setViewName("show");前提是SpringMvc配置了视图解析器。
  4. 如果页面发送的是AJAX请求,页面不会进行跳转,那么setViewName()方法就显得很多余,所以这里使用ModeAndView作为返回值就不在合适。
  5. 同时需要保存数据,同时需要跳转页面,这样的话就使用ModelAndView

2、返回String表示视图部分

如果本次请求,仅仅是要做的一个页面跳转的功能,那么使用String作为返回值最好
可以使用逻辑名称【文件名】,也可以是完整路径。

程序内部执行的是 forward() 请求 请求转发

使用逻辑名称:

  • return "doSome" 【配置了视图解析器,拼接后的完整路径为/WEB-INF/view/doSome.jsp

使用过完整视图路径

  • 项目中不能配置视图解析器
  • return "/WEB-INF/view/doSome.jsp"

请求转发:

  • return "redirect:/doSome"; 【调转到doSome路由】

3、返回值void

既不能表示数据,也不能表示视图
在处理AJAX时,可以使用void,通过HttpServletResponse来输出数据,响应AJAX请求。
AJAX请求服务器端返回的就是数据,和视图无关。
当接受到ajax请求时,需要返回数据,只需要往HttpServletResponseprint();方法里写就行。

  1. 修改响应字符集
  2. response.setContentType("text/html,charset=utf-8");
  3. PrintWriter writer = response.getWriter();
  4. writer.print("响应AJAX请求");

4、返回值Object 【处理AJAX】

返回:StringIntegerMapListStudent等等都是对象。
对象有属性,属性就是数据,所以返回Object表示返回数据,和视图无关
可以使用对象表示的数据,来响应AJAX请求

现在做AJAX,主要是使用JSON的数据格式,处理器返回Json数据实现步骤:

①、加入Json

springmvc默认使用的是jackson 【一个自动生成json的jar包】

  1. <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
  2. <dependency>
  3. <groupId>com.fasterxml.jackson.core</groupId>
  4. <artifactId>jackson-databind</artifactId>
  5. <version>2.11.0</version>
  6. </dependency>

②、把java对象转换成json

在springmvc配置文件中加入**<mvc:annotation-driven>** 注解驱动。这样就好了

在加入到springmvc中,会自动创建HttpMessageConverter接口,和他的7个实现类对象

未命名图片.png

③、在处理器方法的上面加入 @ResponseBody注解

放在处理器方法的上面,通过HttpServletResponse来输出数据,响应AJAX请求的
处理器方法返回一个Student,通过框架转为json,响应ajax请求

@ResponseBody

  • 作用:把处理器方法返回的对象转换为json数据后,通过HttpServletResponse输出给浏览器
  • 位置:在方法定义的上面

例如:处理器方法返回一个Student对象,通过框架转为json,响应ajax请求

  1. @ResponseBody
  2. @RequestMapping("/test")
  3. public Student test(){
  4. return new Student();
  5. }

例如:返回一个List集合,里面是Student
未命名图片.png

4、处理器方法返回一个String,并不是视图信息,而是数据

  • 区分返回值字符是数据还是视图,看有没有@ResponseBody注解
  • 如果有就是数据,如果没有就是视图
    1. @RequestMapping("处理地址")
    2. @ResponseBody
    3. public String returnString(){
    4. return "登录失败";
    5. } //有@ResponseBody注解,是数据,不是视图
    出现的问题: 返回中文的时候出现乱码问题 “???”
    解决方案:给@RequestMapping注解增加一个属性
    **@RequestMapping(value = "/returnStudentJson.do",produces = "text/html;charset=utf-8")**
    未命名图片.png