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

一、springmvc开发步骤

image.png

  1. cho1-hello-springmvc:第一个springmvc项目。
  2. 需求:用户在页面发起一个请求,请求交给springmvc的控制器对象,
  3. 并显示请求的处理结果(在结果页面显示一个欢迎语句)。
  4. 实现步骤︰
  5. 1.新建web maven工程
  6. 2.加入依赖
  7. spring-webmvc依赖,间接把spring的依赖都加入到项目
  8. jsp , servlet依赖
  9. 3.重点: 在web.xml中注册springmvc框架的核心对象DispatcherServlet
  10. 1)DispatcherServlet叫做中央调度器,是一个servlet ,它的父类是继承Httpservlet
  11. 2)Dispatcherservlet页叫做前端控制器(front controller )
  12. 3)Dispatcherservlet负责接收用户提交的请求,调用其它的控制器对象,并把请求的处理结果显示给用户
  13. 4.创建一个发起请求的页面index.jsp
  14. 5.创建控制器类
  15. 1)在类的上面加入@controller注解',创建对象,并放入到springmvc容器中
  16. 2)在类中的方法上面加入@RequestMapping注解。
  17. 6.创建一个作为结果的jsp,显示请求的处理结果。
  18. 7.创建springmvc的配置文件(spring的配置文件―样)
  19. 1)声明组件扫描器,指定@Contorller注解所在的包名
  20. 2)声明视图解析器。帮助处理视图的。

2.加入依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <groupId>com.bjpowernode</groupId>
  6. <artifactId>ch01-hellospringmvc</artifactId>
  7. <version>1.0-SNAPSHOT</version>
  8. <packaging>war</packaging>
  9. <properties>
  10. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  11. <maven.compiler.source>1.8</maven.compiler.source>
  12. <maven.compiler.target>1.8</maven.compiler.target>
  13. </properties>
  14. <dependencies>
  15. <!--servlet依赖-->
  16. <dependency>
  17. <groupId>javax.servlet</groupId>
  18. <artifactId>javax.servlet-api</artifactId>
  19. <version>3.1.0</version>
  20. <scope>provided</scope>
  21. </dependency>
  22. <!--springmvc的依赖-->
  23. <dependency>
  24. <groupId>org.springframework</groupId>
  25. <artifactId>spring-webmvc</artifactId>
  26. <version>5.2.5.RELEASE</version>
  27. </dependency>
  28. <dependency>
  29. <groupId>junit</groupId>
  30. <artifactId>junit</artifactId>
  31. <version>4.11</version>
  32. <scope>test</scope>
  33. </dependency>
  34. </dependencies>
  35. <build>
  36. </build>
  37. </project>

3.重点

<?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的核心对象Dispatcherservlet
        需要在tomcat服务器启动后,创建Dispatcherservlet对象的实例。
        为什么要创建Dispatcherservlet对象的实例呢?
        因为Dispatcherservlet在他的创建过程中,会同时创建springmvc容器对象,
        读取springmvc的配置文件,把这个配置文件中的对象都创建好,当用户发起
        请求时就可以直接使用对象了。|

    servlet的初始化会执行init ( )方法。Dispatcherservlet在init ( ) 中{
            //创建容器,读取配匿文件
             webApplicationcontext ctx = new ClassPathXmLApplicationcontext("springmMc.xml");
             //把容器对象放入到ServletContext中
                getservletcontext( ).setAttribute(key,ctx);

            }
    -->


    <servlet>
        <servlet-name>myweb</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--在tomcat启动后,创建Servlet对象
               load-on-startup:表示tomcat启动后创建对象的顺序。它的值是一个整数,数值越小,
                                 tomcat创建的时间越早。
                -->


           <!-- springmvc创建容器对象时,读取的配置文件默认是/WEB-INF/<servlet-name>-servlet.xml   -->



                     <!--自定义springmvc读取的配置文件的位置-->
                     <init-param>
                             <!--springmvc的配置文件的位置的属性-->

                        <param-name>contextConfigLocation</param-name>
                              <!--指定自定义文件的位置-->
                        <param-value>classpath:springmvc.xml</param-value>
                    </init-param>

                    <load-on-startup>2</load-on-startup>

    </servlet>

    <servlet-mapping>
                    <servlet-name>myweb</servlet-name>
            <!-->

        使用框架的时候,url-pattern可以使用两种值
        1,使用扩展名方式,语法*.xxx , xxx是自定义的扩展名。常用的方式*.do,*.action,*.mvc等等
            http://localhost:8080 /myweb/some.do
            http:// localhost : 8080/myweb/other.do        \
        2.  使用斜杠  "/"     <-->
                <url-pattern>*.do</url-pattern>
    </servlet-mapping>


</web-app>

4.创建一个发起请求的页面index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <p>第一个springmvc项目</p>
    <p><a href="some.do">发起some.do的请求</a></p>


</body>
</html>

5.创建控制器类

package com.bjpowerndoe.controller;

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

/**
 * 创建处理器对象,对象放在了springmvc中
 * 位置:在类的上面
 *
 * 和spring讲的@Service,@Compinent
 *
 * 能处理请求的都是控制器(处理器) Mycontroller能处理请求 后端控制器
 */
@Controller
public class MyController {
    /*
    处理 用户提交的请求,springmvc中是使用方法来处理的
    方法是自定义的,可以有多种返回值,多种参数,方法名称自定义
     */



    /*
    准备使用doSome方法处理some.do请求。
    @RequestMapping  请求映射,作用是把一个请求地址和一个方法绑定在一起。
                             一个请求指定一公分方法处理.

        属性: 1. value 是一个string ,表示请求的uri地址的( some. do ) 。
                   value的值必须是唯一的,不能重复。在使用时,推荐地址以"/”
        位置:1.在方法的上面,常用的。
               2.在类的上面
说明:使用RequestMapping修饰的方法叫做处理器方法或者控制器方法。
使用@RequestMapping修饰的方法可以处理请求的,类似servlet中的doGet,doPost


    返回值:ModelAndview表示本次请求的处理结果
    Model:数据,请求处理完成后,要显示给用户的数据
    View:视图,比如jsp等等。


     */

    @RequestMapping(value = "/some.do")
    public ModelAndView doSome(){   //doGet()
        //处理some.do请求了。  相当于service调用处理完成了。
ModelAndView mv = new ModelAndView();
//添加数据,框架在请求的最后把数据放入到request作用域。
// request.setAttribute( "msg" , "欢迎使用springmvc做web开发");
mv.addObject("msg","欢迎使用springmvc做web开发");
mv.addObject( "fun","执行的是doSome方法");

//指定视图,指定视图的完整路径
// 框架对视图执行的forward操作,request.getRequestDispather( "/ show.jsp) . forward( ...)

        mv.setViewName("/show.jsp");

        //返回mv
        return mv;

    }
}

6.创建一个作为结果的jsp,显示请求的处理结果。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h3>show.jsp从request作用域获取数据</h3>
<h3>msg数据:${msg}</h3><br/>
<h3>fun数据:${fun}</h3>


</body>
</html>

7.创建springmvc的配置文件(spring的配置文件―样)

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

    <!--声明组件扫描器-->

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


</beans>

1.1spring请求的处理流程

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

上面的过程简化的方式
some.do—-DispatcherServlet—-MyController

image.png

1.2.spring执行过程源代码分析

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的核心方法, 所有的请求都在这个方法中完成的。



没有加入注解驱动标签时的状态
org.springframework.http.converter.ByteArrayHttpMessageConverter
org.springframework.http.converter.StringHttpMessageConverter
org.springframework.http.converter.xml.SourceHttpMessageConverter
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter


加入注解驱动标签时的状态
org.springframework.http.converter.ByteArrayHttpMessageConverter
org.springframework.http.converter.StringHttpMessageConverter
org.springframework.http.converter.ResourceHttpMessageConverter
org.springframework.http.converter.ResourceRegionHttpMessageConverter
org.springframework.http.converter.xml.SourceHttpMessageConverter
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter

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

http://localhost:8080/ch05_url_pattern/index.jsp :tomcat(jsp会转为servlet)
http://localhost:8080/ch05_url_pattern/js/jquery-3.4.1.js : tomcat
http://localhost:8080/ch05_url_pattern/images/p1.jpg : tomcat
http://localhost:8080/ch05_url_pattern/html/test.html: tomcat
http://localhost:8080/ch05_url_pattern/some.do : DispatcherServlet(springmvc框架处理的)


tomcat本身能处理静态资源的访问, 像html, 图片, js文件都是静态资源


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

default
org.apache.catalina.servlets.DefaultServlet

debug
0


listings
false

1



default
/ 表示静态资源和未映射的请求都这个default处理



default这个servlet作用:
The default servlet for all web applications, that serves static
resources. It processes all requests that are not mapped to other
servlets with servlet mappings (defined either here or in your own
web.xml file).

1.处理静态资源
2.处理未映射到其它servlet的请求。

1.3配置视图解析器

在springmvc中

 <!--声明springmvc框架中的视图解析器,帮助开发人员设置视图文件的路怪-->
    <bean class="org.springframework.web.servlet.view.InternalResourceView">
    <!--前缀:视图文件的路怪-->
   <property name="prefix" value="/WEB-INF/view" />
        <!--后缀:视图文件的扩展名-->
    <property name="suffix" value=".jsp" />
    </bean>

在myController中

   //框架会使用视图解析器的前缀+逻辑名称+后缀组成完成路备,这里就是字符连接操作// /WEB- INF/view/: : show + .isrl
        mv.setViewName( "show" );

Springmvc注解式开发

2.1@RequestMapping放在类上面

@RequestMapping:
value :所有请求地址的公共部分,叫做模块名称位置:放在类的上面

2.2指定请求方式method属性

@RequestMapping :请求映射
属性:method ,表示请求的方式。它的值RequestMethod类枚举值。
例如表示get请求方式,RequestMethod.GET
post方式,RequestMethod.POST

@RequestMapping(value = "/some.do",method = RequestMethod.GET)

2.3处理器方法的参数

处理器方法可以包含以下四类参数,这些参数会在系统调用时由系统自动赋值,即程序
员可在方法内直接使用。
➢ HttpServletRequest
➢ HttpServletResponse
➢ HttpSession
➢ 请求中所携带的请求参数

@RequestMapping(value = "/first.do")
        public ModelAndView doFirst(HttpServletRequest request,
            HttpServletResponse response,
                HttpSession session){
    ModelAndView mv = new ModelAndView();
    mv.addObject("msg","===欢迎使用springmvc做web开发==="+ request.getParameter("name"));
            return mv;
        }

2.4 逐个参数接收

分析:
逐个接收请求参数:
要求:处理器(控制器)方法的形参名和请求中参数名必须一致。
同名的请求参数赋值给同名的形参
框架接收请求参数
1.使用request对象接收请求参数
String strName = request.getParameter( “name””);string strAge = request.getParameter( “age”);
2. springmvc框架通过Dispatcherservlet调用MyController的doSome()方法
调用方法时,按名称对应,把接收的参数赋值给形参
dosome ( strName , Integer.valueof(strAge))
框架会提供类型转换的功能,能把string转为 int ,long , float , double等类型。

只要保证请求参数名与该请求处理方法的参数名相同即可。
项目:receiveParameters-property。在 requestMapping-method 基础上修改。
Step1:修改 index 页面
image.png
Step2:修改处理器类 MyController
image.png
Step3:添加 show 页面
在/WEB-INF/jsp 下添加 show.jsp 页面。

image.png

2.4.1请求参数中文乱码问题

(1) 解决方案
在 web.xml 中注册字符集过滤器,即可解决 Spring 的请求参数的中文乱码问题。不过,
最好将该过滤器注册在其它过滤器之前。因为过滤器的执行是按照其注册顺序进行的。
直接在项目 receiveParameters-property 上进行修改。

image.png