当前位置:   article > 正文

SpringMVC基础(2):SpringMVC基础

springmvc

目录

1、SpringMVC 概述

1.1 SpringMVC 基本说明

1.2、SpringMVC中的核心Servlet – DispatcherServlet

1.3、SpringMVC注解开发

1.4、SpringMVC请求的处理过程

1.5、Web开发中配置文件的说明

以上 1, 2. 都是项目启动的过程, 没有执行任何的用户请求。

1.6、SpringMVC内部的执行流程

2、SpringMVC 注解式开发

2.1 @RequestMapping注解的使用

2.2、接收请求中的参数

2.2.1 逐个接收

2.2.2 CharacterEncodingFilter使用:

2.2.3 请求中参数名和形参名不一样,使用@RequestParam

2.2.4 对象接收

2.3 控制器方法的返回值

2.3.1 ModelAndView 数据和视图

2.3.2 String 视图

2.3.3 void 没有数据和视图

2.3.4 Object

2.4 静态资源处理

2.4.1 tomcat的default servlet

2.4.2 中央调度器设置 “/”

2.4.3 第一种方式处理静态资源

2.4.4 第二种静态资源的处理方式


0、写在前面

     来源:动力节点

     项目:SpringMVC

1、SpringMVC 概述

1.1 SpringMVC 基本说明

  • SpringMVC是基于Spring的, 是Spring中的一个模块,做web开发使用的。 SpringMVC 叫做Spring Web MVC。
  • SpringMVC是Spring的核心技术, 做Web开发,SpringMVC内部是使用mvc架构模式。
  • SpringMVC 是一个容器, 管理对象的,使用IoC核心技术。
  • SpringMVC管理界面层中的控制器对象。
  • SpringMVC底层也是Servlet。 以Servlet为核心接收请求,处理请求,显示处理结果给用户

处理用户的请求:

  • 用户发起请求----SpringMVC----—Spring-----—MyBatis–------mysql数据库。

SpringMVC三层架构理解:SpringMVC教程 - 动力节点

1.2、SpringMVC中的核心Servlet – DispatcherServlet

  • DispatcherServlet 是框架一个Servlet对象。 负责接收请求, 响应处理结果
  • DispatcherServlet 父类是 HttpServlet
  • DispatcherServlet 也叫 前端控制器

SpringMVC是管理控制器对象, 原来没有SpringMVC之前使用 Servlet作为控制器对象使用。

现在通过SpringMVC容器创建一种叫做控制器的对象,代替Servlet行驶控制器的角色

1.3、SpringMVC注解开发

需求:用户提交一个请求,服务端处理器接收该请求后给一条欢迎信息,在相应页面显示该信息。

SpringMVC 主要使用注解的方式, 创建控制器对象, 处理请求:

1、加依赖项:

  1. <dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-webmvc</artifactId>
  4. <version>5.2.5.RELEASE</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>javax.servlet</groupId>
  8. <artifactId>servlet-api</artifactId>
  9. <version>3.0-alpha-1</version>
  10. </dependency>

加入webmvc后自动导入spring核心依赖: 

2、配置web.xml

  1. <servlet>
  2. <servlet-name>myweb</servlet-name>
  3. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  4. <!--自定义配置文件的位置-->
  5. <init-param>
  6. <param-name>contextConfigLocation</param-name>
  7. <param-value>classpath:springmvc.xml</param-value>
  8. </init-param>
  9. <!--
  10. 表示服务器tomcat创建对象的顺序, 是个整数值, 大于等于0.
  11. 数值越小,创建对象的时间越早。
  12. -->
  13. <load-on-startup>1</load-on-startup>
  14. </servlet>
  15. <servlet-mapping>
  16. <servlet-name>myweb</servlet-name>
  17. <!--
  18. url-pattern 作用: 把一些请求交给指定的servlet处理
  19. 使用中央调度器(DispatcherServlet)
  20. 1. 使用扩展名方式, 格式 *.xxx , xxx是自定义的扩展名。
  21. 例如 *.do , *.action, *.mvc 等等. 不能使用*.jsp
  22. http://localhost:8080/myweb/some.do
  23. http://localhost:8080/myweb/user/list/queryUser.do
  24. http://localhost:8080/myweb/user/list/list.do
  25. 2. 使用斜杠 "/"
  26. -->
  27. <url-pattern>*.do</url-pattern>
  28. </servlet-mapping>

3、配置tomcat

4、启动tomcat

5、访问   http://localhost:8080/ch01_springmvc/mymvc

  1. 类型 异常报告
  2. 消息 Servlet[springmvc]的Servlet.init()引发异常
  3. 描述 服务器遇到一个意外的情况,阻止它完成请求。
  4. 例外情况
  5. javax.servlet.ServletException: Servlet[springmvc]的Servlet.init()引发异常
  6. org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:544)
  7. org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
  8. org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:698)
  9. org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:364)
  10. org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:624)
  11. org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
  12. org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:831)
  13. org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1650)
  14. org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
  15. org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
  16. org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
  17. org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  18. java.lang.Thread.run(Thread.java:748)
  19. 根本原因。
  20. org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from ServletContext resource [/WEB-INF/springmvc-servlet.xml]; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/springmvc-servlet.xml]
  21. org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:340)
  22. org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:305)
  23. org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188)
  24. org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:224)
  25. org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:195)
  26. org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
  27. org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94)
  28. org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:133)

6、问题分析:

1、其中<load-on-startup>1</load-on-startup>的作用是:在容器启动的时候创建DispatcherServlet对象。

2、url-pattern 作用: 把一些请求交给指定的servlet处理 使用中央调度器(前段控制器):DispatcherServlet:

  • 使用扩展名方式, 格式 *.xxx , xxx是自定义的扩展名。 例如 *.do , *.action, *.mvc 等等. 不能使用*.jsp http://localhost:8080/myweb/some.do http://localhost:8080/myweb/user/list/queryUser.do http://localhost:8080/myweb/user/list/list.do
  • 使用斜杠 "/" 

3、配置的自定义配置文件的位置的变量 contextConfigLocation在DispatcherServlet父类 FrameworkServlet中。 

  1. public class DispatcherServlet extends FrameworkServlet {
  2. }
  3. public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
  4. public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet";
  5. public static final Class<?> DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;
  6. public static final String SERVLET_CONTEXT_PREFIX = FrameworkServlet.class.getName() + ".CONTEXT.";
  7. private static final String INIT_PARAM_DELIMITERS = ",; \t\n";
  8. @Nullable
  9. private String contextAttribute;
  10. private Class<?> contextClass;
  11. @Nullable
  12. private String contextId;
  13. @Nullable
  14. private String namespace;
  15. @Nullable
  16. private String contextConfigLocation;
  17. }
  1. <!DOCTYPE web-app PUBLIC
  2. "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  3. "http://java.sun.com/dtd/web-app_2_3.dtd" >
  4. <web-app>
  5. <!-- 声明springmvc核心对象
  6. 当访问 mymvc后,报错:文件没有找到,文件是[/WEB-INF/springmvc-servlet.xml]
  7. 当修改servlet-name为 web时,显示文件没找到,文件是[/WEB-INF/web-servlet.xml]
  8. 错误原因:
  9. DispatcherServlet的一个作用就是:
  10. 在servlet的init方法中,会创建springmvc使用的容器对象WebApplicationContext,
  11. WebApplicationContext context = new WebApplicationContext(配置文件);
  12. 且该配置文件的默认路径:/WEB-INF/</servlet-name>-servlet.xml
  13. 解决方法:一般不使用默认路径,都是 自定义配置文件的位置,见如下:
  14. -->
  15. <servlet>
  16. <servlet-name>springmvc</servlet-name>
  17. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  18. <!--自定义配置文件的位置
  19. 原理:DispatcherServlet会读取变量 contextConfigLocation,取出变量的值:
  20. classpath:springmvc.xml 当作容器的入参WebApplicationContext(classpath:springmvc.xml);
  21. -->
  22. <init-param>
  23. <param-name>contextConfigLocation</param-name>
  24. <param-value>classpath:springmvc.xml</param-value>
  25. </init-param>
  26. <!--
  27. 表示服务器tomcat创建对象的顺序, 是个整数值, 大于等于0.
  28. 数值越小,创建对象的时间越早。
  29. -->
  30. <load-on-startup>1</load-on-startup>
  31. </servlet>
  32. <!--
  33. url-pattern 作用: 把一些请求交给指定的servlet处理
  34. 使用中央调度器(DispatcherServlet)
  35. 1. 使用扩展名方式, 格式 *.xxx , xxx是自定义的扩展名。
  36. 例如 *.do , *.action, *.mvc 等等. 不能使用*.jsp
  37. http://localhost:8080/myweb/some.do
  38. http://localhost:8080/myweb/user/list/queryUser.do
  39. http://localhost:8080/myweb/user/list/list.do
  40. 2. 使用斜杠 "/"
  41. -->
  42. <servlet-mapping>
  43. <servlet-name>springmvc</servlet-name>
  44. <url-pattern>/mymvc</url-pattern>
  45. </servlet-mapping>
  46. </web-app>

1.4、SpringMVC请求的处理过程

DispatcherServlet作用:

1、在Servlet的init()方法中创建springmvc的容器对象 WebApplicationContext。创建springmvc配置文件里的所有java对象,就是controller对象。

2、DispatcherServlet是一个Servlet,能够接受请求。

注意:只有DispatcherServlet可以接收请求,然后将请求交给自定义的各种Controller处理

  • 用户发起请求some.do—>Tomcat接收了请求—DispatcherServlet–分配MyController(doSome()返回mv对象)–mv显示给用户了。
  • 省略tomcat
    • 用户some.do--------------DispatcherServlet--------------MyController
  • 如果使用servlet处理请求
    • 用户发起请求--------------------没有其他对象------------------------Servlet

用户发起some.do—DispatcherServlet(Servlet接收请求)—转给MyController:

  1. public class DispatcherServlet extends HttpServlet{
  2. public void service(HttpServletRequest request, HttpServletResponse response){
  3. if(“some.do”.equals(request.getURI())){
  4. //从容器中获取MyController
  5. MyController c = ctx.getBean(“some”));
  6. c.doSome();
  7. } else if( “other.do”.equals(request.getURI())){
  8. OtherController c = ctx.getBean(“other”));
  9. c.doOther();
  10. ​ }
  11. ​ }
  12. }

1.5、Web开发中配置文件的说明

  • 1、web.xml 部署描述符文件 , 给服务器(tomcat):
    • 作用:服务器在启动的时候,读取web.xml 根据文件中的声明创建各种对象,根据文件中的声明 知道 请求和servlet等对象的关系
  1. <!DOCTYPE web-app PUBLIC
  2. "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  3. "http://java.sun.com/dtd/web-app_2_3.dtd" >
  4. <web-app>
  5. <!-- 声明springmvc核心对象
  6. 当访问 mymvc后,报错:文件没有找到,文件是[/WEB-INF/springmvc-servlet.xml]
  7. 当修改servlet-name为 web时,显示文件没找到,文件是[/WEB-INF/web-servlet.xml]
  8. 错误原因:
  9. DispatcherServlet的一个作用就是:
  10. 在servlet的init方法中,会创建springmvc使用的容器对象WebApplicationContext,
  11. WebApplicationContext context = new WebApplicationContext(配置文件);
  12. 且该配置文件的默认路径:/WEB-INF/</servlet-name>-servlet.xml
  13. 解决方法:一般不使用默认路径,都是 自定义配置文件的位置,见如下:
  14. -->
  15. <servlet>
  16. <servlet-name>myweb</servlet-name>
  17. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  18. <!--自定义配置文件的位置
  19. 原理:DispatcherServlet会读取变量 contextConfigLocation,取出变量的值:
  20. classpath:springmvc.xml 当作容器的入参WebApplicationContext(classpath:springmvc.xml);
  21. -->
  22. <init-param>
  23. <param-name>contextConfigLocation</param-name>
  24. <param-value>classpath*:springmvc.xml</param-value>
  25. </init-param>
  26. <!--
  27. 表示服务器tomcat创建对象的顺序, 是个整数值, 大于等于0.
  28. 数值越小,创建对象的时间越早。
  29. -->
  30. <load-on-startup>1</load-on-startup>
  31. </servlet>
  32. <!--
  33. url-pattern 作用: 把一些请求交给指定的servlet处理
  34. 使用中央调度器(前段控制器):DispatcherServlet:
  35. 1. 使用扩展名方式, 格式 *.xxx , xxx是自定义的扩展名。
  36. 例如 *.do , *.action, *.mvc 等等. 不能使用*.jsp
  37. http://localhost:8080/myweb/some.do
  38. http://localhost:8080/myweb/user/list/queryUser.do
  39. http://localhost:8080/myweb/user/list/list.do
  40. 2. 使用斜杠 "/"
  41. -->
  42. <servlet-mapping>
  43. <servlet-name>myweb</servlet-name>
  44. <url-pattern>*.do</url-pattern>
  45. </servlet-mapping>
  46. </web-app>
  • 2、框架的配置文件, springmvc的配置文件:
    • 作用:声明框架创建的项目中的各种对象, 主要是创建Controller对象的。
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. 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">
  6. <!-- springmvc配置文件 -->
  7. <!-- 注解扫描 -->
  8. <context:component-scan base-package="com.crane.springmvc"></context:component-scan>
  9. <!-- 声明视图解析器: 帮助处理视图
  10. 作用:简化controller中的写法:
  11. 之前: modelAndView.setViewName("WEB-INF/view/show.jsp");
  12. 现在: modelAndView.setViewName("show");
  13. -->
  14. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  15. <!-- 前缀:指定视图文件的路径-->
  16. <property name="prefix" value="/WEB-INF/view/"></property>
  17. <!-- 后缀:指定视图文件的扩展名-->
  18. <property name="suffix" value=".jsp"></property>
  19. </bean>
  20. </beans>

3、配置文件的加载顺序和功能

  • 1、tomcat服务器启动, 读取web.xml。根据web.xml文件中的说明,创建对象:
  1. <servlet>
  2. <servlet-name>myweb</servlet-name>
  3. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  4. <!--自定义配置文件的位置-->
  5. <init-param>
  6. <param-name>contextConfigLocation</param-name>
  7. <param-value>classpath:springmvc.xml</param-value>
  8. </init-param>
  9. <!--
  10. 表示服务器tomcat创建对象的顺序, 是个整数值, 大于等于0.
  11. 数值越小,创建对象的时间越早。
  12. -->
  13. <load-on-startup>1</load-on-startup>
  14. </servlet>

        根据load-on-startup的值为1,在tomcat启动时会创建DispatcherServlet的对象, 然后执行init()方法。 在init()方法中会执行 springmvc容器对象创建:WebApplicationContext ctx = new ClassPathXmlApplicationContext(“classpath:springmvc.xml”)

  • 2、springmvc框架, new ClassPathXmlApplicationContext()读取springmvc的配置文件。
  1. <context:component-scan base-package="com.bjpowernode.controller" />
  2. <!--声明视图解析器:帮助处理视图-->
  3. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  4. <!--前缀:指定视图文件的路径-->
  5. <property name="prefix" value="/WEB-INF/view/" />
  6. <!--后缀:视图文件的扩展名-->
  7. <property name="suffix" value=".jsp" />
  8. </bean>

        使用组件扫描器base-package=“com.crane.controller” ,遍历controller包中的所有类,MyController类, 找到这个类中的@Controller, @RequestMapping注解, 就能创建MyContoller对象。知道some.do的请求是执行doSome()方法。

以上 1, 2. 都是项目启动的过程, 没有执行任何的用户请求。

3、用户发起请求some.do----DispatcherServlet

DispatcherServlet里面有 WebApplicationContext 。 WebApplicationContext 里面有MyController对象。请求some.do ,DispatcherServlet 就知道是 MyController处理的。

1.6、SpringMVC内部的执行流程

1、用户发起请求给DispatcherServlet。

2、DispatcherServlet把请求(request)交给了 处理器映射器。

        处理器映射器: springmvc框架中的对象, 需要实现HandlerMapping接口。

        映射器作用: 从springmvc容器中,获取控制器对象(MyController),把找到的控制器和拦截器对象都放到 处理器执行链对象中保存,并返回给中央调度器。(MyController controller = ApplicationContext.getBean())

3、DispatcherServlet把获取到的处理器执行链中的控制器对象,交给了处理器适配器。

     处理器适配器:是springmvc框架中的对象, 实现HandlerAdapter接口。

     适配器作用: 执行控制器的方法, 也就是执行MyController.doSome()方法。得到结果ModelAndView。

4、DispatcherServlet把控制器执行结果mv交给了 视图解析器

       视图解析器: springmvc中的对象,需要实现ViewResolver接口。

       视图解析器作用: 处理视图的, 组成视图的完整路径。 能创建View类型的对象。

5、DispatcherServlet调用View类的方法, 把Model中的数据放入到request作用域。 执行request.setAttribute(), 对视图执行forward()转发行为, request.getRequestDispather("/show.jsp").forward(request,response)

2、SpringMVC 注解式开发

2.1 @RequestMapping注解的使用

  • 属性: value 请求的uri地址。
  • 位置: 1) 在方法的上面, 必须的。 2)在类的上面作为模块名称
  1. @RequestMapping(value ="/some.do")
  2. public ModelAndView doSome(){
  3. }
  • 属性 method 请求的方式, 使用RequestMehtod类的枚举,表示请求方式:
  1. @RequestMapping(value ="/other.do",method = RequestMethod.POST)
  2. public ModelAndView doOther(){
  3. }

post: 添加修改,适用参数多时。

get: 查询,适用参数少时,get有缓存当查询的数据长时间不变化使用。

2.2、接收请求中的参数

  • 对应HttpServletRequest, HttpServletResponse, HttpSession 只需要在控制器方法的形参列表中,定义就可以了。框架会给参数赋值, 在控制器方法内部可以直接使用 request,response,session参数。
  1. @RequestMapping(value={ "/other.do","/test/second.do"})
  2. public ModelAndView doOther(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, HttpSession httpSession){
  3. System.out.println("执行了 doOther 方法");
  4. String name = httpServletRequest.getParameter("name");
  5. System.out.println(name);
  6. }
  • 400 : http status , 表示客户端异常。 主要是发生在用户提交参数过程中,提交的数据不对
  • 接收请求中的参数: 逐个接收, 对象接收。

2.2.1 逐个接收

逐个接收: 请求中的参数名和控制器方法的形参名一样。按照名称对象接收参数:

  1. <p>逐个接收请求参数</p>
  2. <form action="receive-property.do" method="post">
  3. 姓名:<input type="text" name="name"> <br/>
  4. 年龄:<input type="text" name="age"> <br/>
  5. <input type="submit" value="提交参数">
  6. </form>

Controller接收参数:

  1. @RequestMapping(value ="/receive-property.do")
  2. public ModelAndView doPropertyParam(String name, Integer age) {
  3. }

接收参数的问题:

  1. 参数最好使用包装类型。 例如Integer ,能接收空值情况, 接收的是null。例如浏览器输入空,后端接收为null。如果使用int的话,浏览器输入空,后端报转换异常。
  2. 框架可以使用String到int ,long, float, double等类型转换
  3. post请求中有乱码的问题, 使用字符集过滤器

逐个接收的原理:

当方法定义必须使用Post请求,而我们使用了get方式请求,则会报错:Method not Allowed:405 

2.2.2 CharacterEncodingFilter使用:

解决乱码问题:使用过滤器,框架提供了过滤器:CharacterEncodingFilter。

注意:get不会出现乱码问题,只处理post乱码问题即可。

  1. 在web.xml 声明过滤器
  2. <!DOCTYPE web-app PUBLIC
  3. "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  4. "http://java.sun.com/dtd/web-app_2_3.dtd" >
  5. <web-app>
  6. <!-- 声明过滤器,框架提供的,解决post请求中乱码问题-->
  7. <filter>
  8. <filter-name>characterEncodingFilter</filter-name>
  9. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  10. <!--给过滤器属性赋值-->
  11. <init-param>
  12. <!--项目使用的字符编码-->
  13. <param-name>encoding</param-name>
  14. <param-value>utf-8</param-value>
  15. </init-param>
  16. <init-param>
  17. <!--强制请求(request)对象使用encoding的编码方式-->
  18. <param-name>forceRequestEncoding</param-name>
  19. <param-value>true</param-value>
  20. </init-param>
  21. <init-param>
  22. <!--强制应答(response)对象使用encoding的编码方式-->
  23. <param-name>forceResponseEncoding</param-name>
  24. <param-value>true</param-value>
  25. </init-param>
  26. </filter>
  27. <filter-mapping>
  28. <filter-name>characterEncodingFilter</filter-name>
  29. <url-pattern>/*</url-pattern>
  30. </filter-mapping>
  31. <!-- 声明springmvc核心对象
  32. 当访问 mymvc后,报错:文件没有找到,文件是[/WEB-INF/springmvc-servlet.xml]
  33. 当修改servlet-name为 web时,显示文件没找到,文件是[/WEB-INF/web-servlet.xml]
  34. 错误原因:
  35. DispatcherServlet的一个作用就是:
  36. 在servlet的init方法中,会创建springmvc使用的容器对象WebApplicationContext,
  37. WebApplicationContext context = new WebApplicationContext(配置文件);
  38. 且该配置文件的默认路径:/WEB-INF/</servlet-name>-servlet.xml
  39. 解决方法:一般不使用默认路径,都是 自定义配置文件的位置,见如下:
  40. -->
  41. <servlet>
  42. <servlet-name>myweb</servlet-name>
  43. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  44. <!--自定义配置文件的位置
  45. 原理:DispatcherServlet会读取变量 contextConfigLocation,取出变量的值:
  46. classpath:springmvc.xml 当作容器的入参WebApplicationContext(classpath:springmvc.xml);
  47. -->
  48. <init-param>
  49. <param-name>contextConfigLocation</param-name>
  50. <param-value>classpath*:springmvc.xml</param-value>
  51. </init-param>
  52. <!--
  53. 表示服务器tomcat创建对象的顺序, 是个整数值, 大于等于0.
  54. 数值越小,创建对象的时间越早。
  55. -->
  56. <load-on-startup>1</load-on-startup>
  57. </servlet>
  58. <!--
  59. url-pattern 作用: 把一些请求交给指定的servlet处理
  60. 使用中央调度器(前段控制器):DispatcherServlet:
  61. 1. 使用扩展名方式, 格式 *.xxx , xxx是自定义的扩展名。
  62. 例如 *.do , *.action, *.mvc 等等. 不能使用*.jsp
  63. http://localhost:8080/myweb/some.do
  64. http://localhost:8080/myweb/user/list/queryUser.do
  65. http://localhost:8080/myweb/user/list/list.do
  66. 2. 使用斜杠 "/"
  67. -->
  68. <servlet-mapping>
  69. <servlet-name>myweb</servlet-name>
  70. <!--强制所有请求,先经过过滤器处理-->
  71. <url-pattern>*.do</url-pattern>
  72. </servlet-mapping>
  73. </web-app>

2.2.3 请求中参数名和形参名不一样,使用@RequestParam

form表单中的参数是rname 和 rage,提交给controller的参数方法doReceiveParam形参名称是name 和 age。使用@RequestParam解决。

  1. <form action="receive-param.do" method="post">
  2. 姓名:<input type="text" name="rname"><br/>
  3. 年龄:<input type="text" name="rage"><br/>
  4. <input type="submit" value="提交">
  5. </form>
  1. /**
  2. * 逐个接收请求参数:请求中参数名和形参名不一样
  3. * @RequestParam:解决名称不一样的问题
  4. * 属性:value 请求中的参数名称
  5. * required:boolean类型,默认是true
  6. * ture是指请求中必须有此参数,没有则报错
  7. * 位置:在形参定义的前面
  8. */
  9. @RequestMapping(value="/receive-param.do")
  10. public ModelAndView doReceiveParam(@RequestParam(value="rname") String name,@RequestParam(value="rage") String age){
  11. System.out.println("执行了 doOther 方法");
  12. System.out.println(name + ":" + age);
  13. //调用service对象,处理请求,返回数据
  14. ModelAndView modelAndView = new ModelAndView();
  15. //添加数据
  16. modelAndView.addObject("msg",name);
  17. modelAndView.addObject("fun",age);
  18. modelAndView.setViewName("show");
  19. //返回结果
  20. return modelAndView;
  21. }

2.2.4 对象接收

对象接收: 在控制器方法的形参是java对象, 使用java对象的属性接收请求中参数值

要求: java对象的属性名和请求中参数名一样。

  1. <p>对象接收请求参数</p>
  2. <form action="receive-object.do" method="post">
  3. 姓名:<input type="text" name="name"><br/>
  4. 年龄:<input type="text" name="age"><br/>
  5. <input type="submit" value="对象提交">
  6. </form>
  1. public class Student {
  2. // 属性名和请求中参数名一样
  3. private String name;
  4. private Integer age;
  5. // set| get方法
  6. /**
  7. * 对象接收: 在控制器方法的形参是java对象, 使用java对象的属性接收请求中参数值。
  8. * 要求: java对象的属性名和请求中参数名一样。
  9. * java类中需要有一个无参构造函数,属性有set方法
  10. * 框架处理:
  11. * 1、调用Student的无参构造函数,创建对象
  12. * 2、调用对象的set方法,同名的参数调用对应的set方法
  13. * 参数是name,调用setName(参数值)
  14. */
  15. @RequestMapping(value="/receive-object.do")
  16. public ModelAndView doReceiveObject(Student student){
  17. System.out.println("执行了 doOther 方法");
  18. System.out.println(student.getName() + ":" + student.getAge());
  19. //调用service对象,处理请求,返回数据
  20. ModelAndView modelAndView = new ModelAndView();
  21. //添加数据
  22. modelAndView.addObject("msg",student.getName() );
  23. modelAndView.addObject("fun",student.getAge());
  24. modelAndView.setViewName("show");
  25. //返回结果
  26. return modelAndView;
  27. }
  28. }

2.3 控制器方法的返回值

控制器方法的返回值表示本次请求的处理结果,返回值有ModelAndView, String, void , Object

  • 请求的处理结果包含: 数据和视图

2.3.1 ModelAndView 数据和视图

如果要求请求的结果有数据和视图,使用ModelAndView最方便。

  • 数据:存放request作用域。
  • 视图:执行forward转发操作。

2.3.2 String 视图

框架对返回值是String,执行的是forward转发操作。

  • 视图可以表示为完整视图路径, 或者视图的逻辑名称。
  1. //使用requst是为了让请求的参数name和age在show.jsp中展示。
  2. @RequestMapping(value ="/return-string-view.do")
  3. public String doReturnStringView1(HttpServletRequest request,String name, Integer age) {
  4. System.out.println("执行了MyController的doReturnStringView1方法name=");
  5. request.setAttribute("myname",name);
  6. request.setAttribute("myage",age);
  7. //返回结果,forward,转发到show.jsp
  8. //逻辑名称, 需要配置视图解析器
  9. return "show";
  10. }
  11. @RequestMapping(value ="/return-string-view2.do")
  12. public String doReturnStringView2(String name, Integer age) {
  13. System.out.println("执行了MyController的doReturnStringView2方法name=");
  14. //完整视图路径,不能使用视图解析器
  15. return "/WEB-INF/view/show.jsp";
  16. }

2.3.3 void 没有数据和视图

void: 没有数据和视图, 可以使用HttpServletResponse对象输出数据,响应ajax请求。使用较少,一般使用Object。

导包:向浏览器返回json格式,使用工具类将字符串转为json格式

  1. <dependency>
  2. <groupId>com.fasterxml.jackson.core</groupId>
  3. <artifactId>jackson-core</artifactId>
  4. <version>2.13.1</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.fasterxml.jackson.core</groupId>
  8. <artifactId>jackson-databind</artifactId>
  9. <version>2.13.0</version>
  10. </dependency>

对象转json、输出json

  1. /**
  2. * 控制器返回void,相应ajax请求,使用HttpServletResponse输出数据
  3. */
  4. @RequestMapping("/return-void-ajax.do")
  5. public void returnVoidAjax(HttpServletResponse response,String name,String age) throws IOException {
  6. //调用service得到对象结果
  7. Student student = new Student();
  8. student.setName(name);
  9. student.setName(age);
  10. //把对象转为json
  11. ObjectMapper mapper = new ObjectMapper();
  12. String json = mapper.writeValueAsString(student);
  13. System.out.println("服务器端对象转为json==" + json);
  14. //输出json,相应ajax
  15. response.setContentType("application/json;charset=utf-8");
  16. PrintWriter pw = response.getWriter();
  17. pw.println(json);
  18. pw.flush();
  19. pw.close();
  20. }
  21. }

2.3.4 Object

  • 返回Student 表示数据, 所以控制器方法返回对象Object,用来响应ajax请求。返回对象Object ,可以是List, Student , Map ,String ,Integer… 这些都是数据, 而ajax请求需要的就是数据
  • 在ajax请求中,一般需要从服务器返回的是json格式的数据, 经常要处理java对象到json的转换。而且还需要输出数据响应ajax请求。
  • 框架提供了处理 java对象到json转换和数据输出工作
  • 故使用HttpMessageConverter。

2.3.4.1 HttpMessageConverter 消息转换器

HttpMessageConverter 接口作用:

  • 实现请求的数据转为java对象。
    • 例如:name=lisi,age=20转为student对象
  • 把控制器方法返回的对象转为json,xml,text,二进制等不同格式的数据

  1. public interface HttpMessageConverter<T> {
  2. /**
  3. * 作用: 检查clazz这个类型的对象,能否转为 mediaType表示的数据格式
  4. * 如果能转为mediaType表示的类型, 返回true, 返回true调用read()
  5. */
  6. boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
  7. /**
  8. * 作用: 接收请求中的数据,把数据转为 clazz表示的对象
  9. */
  10. T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException;
  11. /**
  12. * 作用:检查clazz这种数据类型,能否转为mediaType表示的数据格式
  13. */
  14. boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
  15. /**
  16. * 作用: 把t对象,按照contentType说明的格式,把对象转为json或者xml
  17. */
  18. void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException;
  19. }

MediaType:媒体类型,表示互联网中数据的格式。例如application/json, text/html, image/gif

  • HttpMessageConverter 接口的实现类:
    • MappingJackson2HttpMessageConverter : 用jackson工具库的ObjectMapper把java对象转为json数据格式。
    • StringHttpMessageConverter : 把字符串类型的数据,进行格式转换和编码。

怎么使用实现类:

  • 框架根据控制器方法的返回类型, 自动查找使用的实现类。
  1. public class doReceiveObject {
  2. @RequestMapping("/receive-object.do")
  3. public Student doReceiveObject(String name, Integer age) {
  4. System.out.println("MyController的方法doReceiveObject=");
  5. Student student = new Student();
  6. student.setName("lisi");
  7. student.setAge(20);
  8. return student;
  9. }
  10. }

说明

  • 默认情况下: SpringMVC使用了HttpMessageConveter接口的4个实现类。包括了StringHttpMessageConverter。
  • 当需要把java对象转为json格式时,需要在springmvc的配置文件加入注解驱动的标签

mvc:annotation-driven

  • 加入这个标签后, springmvc项目启动后,会创建HttpMessageConveter接口的7个实现类对象,包括StringHttpMessageConverter 和 MappingJackson2HttpMessageConverter。
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:mvc="http://www.springframework.org/schema/cache"
  6. 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 http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
  7. <!-- springmvc配置文件 -->
  8. <!-- 注解扫描 -->
  9. <context:component-scan base-package="com.crane.springmvc"></context:component-scan>
  10. <!-- 声明视图解析器: 帮助处理视图
  11. 作用:简化controller中的写法:
  12. 之前: modelAndView.setViewName("WEB-INF/view/show.jsp");
  13. 现在: modelAndView.setViewName("show");
  14. -->
  15. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  16. <!-- 前缀:指定视图文件的路径-->
  17. <property name="prefix" value="/WEB-INF/view/"></property>
  18. <!-- 后缀:指定视图文件的扩展名-->
  19. <property name="suffix" value=".jsp"></property>
  20. </bean>
  21. <!-- 声明注解驱动,创建HttpMessageConverter接口的7个实现类对象-->
  22. <mvc:annotation-driven></mvc:annotation-driven>
  23. </beans>

2.3.4.2 @ResponseBody

  • @ResponseBody注解的作用,就是把student转换后的json通过HttpServletResponse对象输出给浏览器。@ResponseBody注解作用就下面的代码的实现:
  1. //输出json,相应ajax
  2. response.setContentType("application/json;charset=utf-8");
  3. PrintWriter pw = response.getWriter();
  4. pw.println(json);
  5. pw.flush();
  6. pw.close();

以下两个是等价的:

  1. /**
  2. * 控制器返回void,相应ajax请求,使用HttpServletResponse输出数据
  3. */
  4. @RequestMapping("/return-void-ajax.do")
  5. public void returnVoidAjax(HttpServletResponse response,String name,String age) throws IOException {
  6. //调用service得到对象结果
  7. Student student = new Student();
  8. student.setName(name);
  9. student.setName(age);
  10. //把对象转为json
  11. ObjectMapper mapper = new ObjectMapper();
  12. String json = mapper.writeValueAsString(student);
  13. System.out.println("服务器端对象转为json==" + json);
  14. //输出json,相应ajax
  15. response.setContentType("application/json;charset=utf-8");
  16. PrintWriter pw = response.getWriter();
  17. pw.println(json);
  18. pw.flush();
  19. pw.close();
  20. }
  1. /**
  2. * 控制器方法返回Student-Json
  3. * application/json;charset=utf-8
  4. * 框架的处理模式:
  5. * 1、框架根据控制器方法的返回值类型,找到HttpMessageConvert接口的实现类,
  6. * 最后找到的是Mappingjackson2HttpMessageConvert.
  7. *. 2、使用Mappingjackson2HttpMessageConvert执行write方法,把对象student转为json格
  8. *。 式数据。
  9. *。 3、框架使用 @ResponseBody将json数据输出给浏览器
  10. */
  11. @RequestMapping("/doStudentJson.do")
  12. @ResponseBody
  13. public Student doAjaxJson(HttpServletResponse response,String name,String age) throws IOException {
  14. //调用service得到对象结果
  15. Student student = new Student();
  16. student.setName(name);
  17. student.setName(age);
  18. return student;
  19. }

2.3.4.3 控制器方法返回返回list---array

2.3.4.3 控制器方法返回返回String

        doStringData方法返回的字符串默认的格式为文本,是ISO-8859-1格式,输出到浏览器会出现乱码。

        解决办法是:在@ReqeustMapping中加属性produces=“text/plain;charset=utf-8

2.3.4. 控制器方法返回对象转为json的步骤

  • pom.xml加入jackson依赖,springmvc框架默认处理json就是使用jackson。
  • 在springmvc的配置文件中,加入注解驱动的标签mvc:annotation-dirven。
  • 在控制器方法的上面加入@ResponseBody注解,表示返回值数据,输出到浏览器。

2.4 静态资源处理

访问地址:

当web.xml中DispatcherServlet的url-pattern是 *.do

  • http://localhost:8080/ch05_url_pattern/index.jsp               tomcat处理
  • 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框架

2.4.1 tomcat的default servlet

tomcat安装目录/conf/web.xml

  • default叫做默认servlet,作用:

    • 他提供静态资源的处理

    • 他处理所有未映射到其他资源的请求处理:即下图中的c

2.4.2 中央调度器设置 “/”

http://localhost:8080/ch05_url_pattern/index.jsp tomcat    成功访问

http://localhost:8080/ch05_url_pattern/js/jquery-3.4.1.js   404 没有对应的控制器对象

http://localhost:8080/ch05_url_pattern/images/p1.jpg      404 没有对应的控制器对象

http://localhost:8080/ch05_url_pattern/html/test.html        404 没有对应的控制器对象

http://localhost:8080/ch05_url_pattern/some.do 200        MyController   

  • 使用斜杠 "/"  导致中央调度器成为了默认的default servlet,需要处理静态资源和其他的未映射的请求。  
  • 默认中央调度器没有处理静态资源的控制器对象, 所以静态资源都是 404。
  • some.do这个请求 有MyController对象,所以能访问。    
  • 如果项目中 , 中央调度器设置了“/” , 动态资源能访问,静态资源不能访问,所以需要处理静态资源的访问工作。

2.4.3 第一种方式处理静态资源

        在springmvc的配置文件加入 mvc:default-servlet-handler 标签, springmvc框架会在项目运行时,加入DefaultServletHttpRequestHandler对象,让这个对象处理静态资源的访问

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:mvc="http://www.springframework.org/schema/cache"
  6. 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 http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
  7. <!--声明静态资源的第一种处理方式 -->
  8. <mvc:default-servlet-handler/>
  9. </beans>

注意:default-servlet-handler和@RequestMapping使用存在冲突,导致动态资源不能访问。

解决办法:加上<mvc:annotation-driven />

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:mvc="http://www.springframework.org/schema/cache"
  6. 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 http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
  7. <!-- springmvc配置文件 -->
  8. <!-- 注解扫描 -->
  9. <context:component-scan base-package="com.crane.springmvc"></context:component-scan>
  10. <!-- 声明视图解析器: 帮助处理视图
  11. 作用:简化controller中的写法:
  12. 之前: modelAndView.setViewName("WEB-INF/view/show.jsp");
  13. 现在: modelAndView.setViewName("show");
  14. -->
  15. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  16. <!-- 前缀:指定视图文件的路径-->
  17. <property name="prefix" value="/WEB-INF/view/"></property>
  18. <!-- 后缀:指定视图文件的扩展名-->
  19. <property name="suffix" value=".jsp"></property>
  20. </bean>
  21. <!-- 声明注解驱动,创建HttpMessageConverter接口的7个实现类对象-->
  22. <mvc:annotation-driven />
  23. <!--声明静态资源的第一种处理方式 -->
  24. <mvc:default-servlet-handler />
  25. </beans>
  • 声明静态资源的第一种处理方式 : 创建DefaultServletHttpRequestHandler处理静态资源。    DefaultServletHttpRequestHandler把接收的静态资源的地址,转发给了tomcat的default。    
  • 优点: 解决方式简单。  
  • 缺点:依赖tomcat服务器提供的能力。<mvc:default-servlet-handler />。

2.4.4 第二种静态资源的处理方式

     在springmvc配置文件中加入 mvc:resources 标签, 框架会创建ResourceHttpRequestHandler控制器对象, 使用这个对象处理静态资源的访问。不依赖tomcat服务器。 推荐使用的。

  1. <mvc:annotation-driven />
  2. <!--声明静态资源的第二种处理方式
  3. mapping: 访问静态资源的uri地址, 可以使用通配符(**)
  4. ** : 表示任意的目录和目录和资源名称
  5. location: 静态资源在项目中的位置, 不要使用/WEB-INF目录
  6. -->
  7. <mvc:resources mapping="/images/**" location="/images/" />
  8. <mvc:resources mapping="/html/**" location="/html/" />
  9. <mvc:resources mapping="/js/**" location="/js/" />
  10. <!-- 一句话设置静态资源 -->
  11. <!-- <mvc:resources mapping="/static/**" location="/static/" /> -->

注意:mvc:resources和@RequestMapping使用存在冲突,导致动态资源不能访问。

解决办法:加上<mvc:annotation-driven />

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/67734
推荐阅读
相关标签
  

闽ICP备14008679号