SpringMVC快速使用——基于XML配置和Servlet3.0


SpringMVC快速使用——基于XML配置和Servlet3.0

目录
  • SpringMVC快速使用——基于XML配置和Servlet3.0
    • 1、官方文档
    • 2、目标
    • 3、编写pom文件引入jar包
    • 4、编写 web.xml 文件
    • 5、编写 spring-context.xml
    • 6、编写日志配置
    • 7、编写 Controller
    • 8、编写 welcome.jsp
    • 9、打包
    • 10、部署
    • 11、测试
    • 12、一些说明
      • 12.1 web.xml context-param说明
      • 12.2 一些特殊的Bean类型
    • 13、上传文件
      • 13.1 Apache Commons FileUpload
      • 13.2 Servlet 3.0 multipart parsing

1、官方文档

https://docs.spring.io/spring-framework/docs/5.2.8.RELEASE/spring-framework-reference/web.html#spring-web

2、目标

基于SpringMVC框架,使用XML配置编写一个Web应用,根据客户端发送的请求参数,动态展示欢迎页内容。

3、编写pom文件引入jar包

这里使用5.3.8版本Spring框架。基于Servlet API,必须引入servlet-api依赖。


  4.0.0
  com.black
  spring-springmvc-xml
   war
  0.0.1-SNAPSHOT
  spring-springmvc-xml Maven Webapp
  http://maven.apache.org
  
  
      5.3.8
  
  
    
    
        org.springframework
        spring-core
        ${spring.verson}
    
    
        org.springframework
        spring-beans
        ${spring.verson}
    
    
        org.springframework
        spring-context
        ${spring.verson}
    
    
        org.springframework
        spring-aop
        ${spring.verson}
    
    
        org.springframework
        spring-expression
        ${spring.verson}
    
    
        org.springframework
        spring-context-support
        ${spring.verson}
    
    
    
        org.springframework
        spring-web
        ${spring.verson}
    
    
        org.springframework
        spring-webmvc
        ${spring.verson}
    

    
    
        javax.servlet
        javax.servlet-api
        3.0.1
        provided
    
    
    
        org.springframework
        spring-jcl
        ${spring.verson}
    
    
    
    
        org.slf4j
        slf4j-api
        1.7.31
    
    
        ch.qos.logback
        logback-core
        1.2.3
    
    
        ch.qos.logback
        logback-classic
        1.2.3
        compile
    
  
  
    spring-springmvc-xml
  


4、编写 web.xml 文件

<?xml version="1.0" encoding="UTF-8"?>


  
  
  
  
  
  
      contextConfigLocation
      
  

  
  
      org.springframework.web.context.ContextLoaderListener
  
  
  
  
    dispatcherServlet
    org.springframework.web.servlet.DispatcherServlet
	
    
      contextConfigLocation
      classpath:spring-context.xml
    
    
    1
  
  
  
  
    dispatcherServlet
    
    
    /
  

  spring-web-application
  
      index.jsp
  


5、编写 spring-context.xml

位置:/src/main/resource/spring-context.xml



  
  
  
  
  
    
        
  
  
  


6、编写日志配置

位置:/src/main/resource/logback.xml

<?xml version="1.0" encoding="UTF-8"?>

    
     
    
    
    
    
        
        ${file_name_date}/log-info-${file_name_date}.log
        
            ${CONSOLE_LOG_PATTERN}
            
            UTF-8
        
    
  
    
        
            ${CONSOLE_LOG_PATTERN}
            
            UTF-8
        
    
    
        
        
    

7、编写 Controller

package com.black.app.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class WelcomeController implements Controller {
	private static Logger logger = LoggerFactory.getLogger(WelcomeController.class);
	
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		logger.info("WelcomeController#handleRequest 开始处理...");
		//获取请求参数-姓名
		//request.getParameter 既支持GET 也支持POST
		String name = request.getParameter("name");
		//如果在windows乱码则进行转码
		name = new String(name.getBytes("ISO8859-1"),"UTF-8");
		logger.info("WelcomeController#handleRequest 请求参数:." + name);
		ModelAndView view = new ModelAndView();
		view.addObject("name", name);
		//返回 welcome.jsp
		view.setViewName("welcome");
		logger.info("WelcomeController#handleRequest 处理结束。");
		return view;
	}

}

8、编写 welcome.jsp

位置:/src/main/webapp/WEB-INF/welcome.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>


欢迎【<%= request.getAttribute("name")%>】同学,来到我的 spring-springmvc-xml web应用

9、打包

maven compile package

war包路径:spring-springmvc-xml\target\spring-springmvc-xml.war

10、部署

将spring-springmvc-xml.war部署 apache-tomcat 下。
(1)将 spring-springmvc-xml.war 拷贝到 apache-tomcat-7.0.91\webapps\

(2)编写 apache-tomcat-7.0.91\conf\server.xml



...




...

(3)启动 apache-tomcat
apache-tomcat-7.0.91\bin\startup.bat

如果闪退,记得将安装目录添加到配置环境变量CATALINA_HOME=E:\work\software\apache-tomcat-7.0.91 :

(4)启动后控制台打印:

(5)启动后,war包被解压,应用放在webapps/spring-springmvc-xml 下:

11、测试

(1)访问首页:http://localhost:8180/spring-springmvc-xml/

(2)访问欢迎页:http://localhost:8180/spring-springmvc-xml/welcome?name=小明

http://localhost:8180/spring-springmvc-xml/welcome?name=小红


(3)post 请求访问欢迎页:http://localhost:8180/spring-springmvc-xml/welcome

12、一些说明

12.1 web.xml context-param说明

context-param 里的 contextConfigLocation 和 init-param 的contextConfigLocation有什么区别?
(1)context-param 里的配置参数是所有的 servlet 实例共享的。
(2)context-param 里的contextConfigLocation 是 Root WebApplicationContext,是可以被很多 DispatcherServlet 实例继承的; init-param 的contextConfigLocation 是 WebApplicationContext ,只能当前 DispatcherServlet 实例拥有的配置,与其他 servlet(不仅仅是DispatcherServlet实例) 不共享。
(3)如果不需要 WebApplicationContext 的继承关系,则 context-param 里的contextConfigLocation 配置是:

  
      contextConfigLocation
      
  

如果需要 WebApplicationContext 的继承,则 context-param 里的contextConfigLocation 配置是:

  
      contextConfigLocation
      classpath:applicationContext.xml
  

如果需要继承 Root WebApplicationContext 的,则 init-param 里的contextConfigLocation 配置是:

   
      contextConfigLocation
      classpath:spring-context.xml
    

Spring 官方文档中的继承关系:

对应 web.xml 示例:


  
  org.springframework.web.context.ContextLoaderListener
  
  
  contextConfigLocation
  /WEB-INF/root-context.xml
  
  
  app1
  org.springframework.web.servlet.DispatcherServlet
  
  contextConfigLocation
  /WEB-INF/app1-context.xml
  
  1
  
  
  app1
  /app1/*
  

(4) 如果context-param 不配置 contextConfigLocation 参数, 那么默认会加载 /WEB-INF/applicationContext.xml 文件;
如果文件不存在,则会报错:

2021-07-19 00:42:41.802 [INFO ] [ost-startStop-1] o.s.web.context.ContextLoader.initWebApplicationContext[line:271]: Root WebApplicationContext: initialization started
2021-07-19 00:42:42.081 [DEBUG] [ost-startStop-1] w.c.s.XmlWebApplicationContext.prepareRefresh[line:629]: Refreshing Root WebApplicationContext
2021-07-19 00:42:42.225 [ERROR] [ost-startStop-1] o.s.web.context.ContextLoader.initWebApplicationContext[line:313]: Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from ServletContext resource [/WEB-INF/applicationContext.xml]; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/applicationContext.xml]
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:342)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:310)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:224)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:195)
	at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
	at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94)
	at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130)
	at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:671)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553)
	at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:401)
	at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:292)
	at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103)
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5157)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5680)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:1018)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:994)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
	at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1127)
	at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:2021)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/applicationContext.xml]
	at org.springframework.web.context.support.ServletContextResource.getInputStream(ServletContextResource.java:159)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:333)
	... 25 common frames omitted

(5) 如果 dispatcherServlet init-param 不配置 contextConfigLocation 参数,会自动去加载 “/WEB-INF/${servletname}-servlet.xml” 即/WEB-INF/dispatcherServlet-servlet.xml ;如果文件不存在 那么会报错:

2021-07-19 00:39:47.019 [DEBUG] [ost-startStop-1] w.c.s.XmlWebApplicationContext.prepareRefresh[line:629]: Refreshing WebApplicationContext for namespace 'dispatcherServlet-servlet'
2021-07-19 00:39:47.031 [ERROR] [ost-startStop-1] o.s.w.s.DispatcherServlet.initServletBean[line:534]: Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from ServletContext resource [/WEB-INF/dispatcherServlet-servlet.xml]; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/dispatcherServlet-servlet.xml]
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:342)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:310)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:224)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:195)
	at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
	at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94)
	at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130)
	at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:671)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553)
	at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:702)
	at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:668)
	at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:716)
	at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:591)
	at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:530)
	at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:170)
	at javax.servlet.GenericServlet.init(GenericServlet.java:158)
	at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1230)
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1174)
	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1066)
	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5409)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5707)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:1018)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:994)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
	at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1127)
	at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:2021)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/dispatcherServlet-servlet.xml]
	at org.springframework.web.context.support.ServletContextResource.getInputStream(ServletContextResource.java:159)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:333)
	... 32 common frames omitted

12.2 一些特殊的Bean类型

Spring MVC 的9大组件

Bean type 解释
HandlerMapping 映射一个请求到一个Handler(有一堆拦截器);
主要有两个实现:RequestMappingHandlerMapping(支持@RequestMapping注解)和 SimpleUrlHandlerMapping(URL 映射到 一个 Handler)
HandlerAdapter 帮助DispatcherServlet调用handler
HandlerExceptionResolver 解决异常的策略
ViewResolver 根据逻辑视图名解析出真实的视图
LocaleResolver,LocaleContextResolver 解析器 Locale,为了提供国际化视图
ThemeResolver 解析应用能够使用的主题
MultipartResolver 解析multi-part请求
FlashMapManager 重定向时可以将一个请求的属性传给另一个请求


13、上传文件

有两种上传文件方式:

  • 使用Apache Commons FileUpload
  • 使用 Servlet 3.0 multipart parsing

13.1 Apache Commons FileUpload

主页:https://commons.apache.org/proper/commons-fileupload/
(1) 引入commons-fileupload jar包

 
	
	    commons-fileupload
	    commons-fileupload
	    1.4
	

(2)配置 multipartResolver

 
  
  

(3)配置上传Controller
跳转上传jsp页面controller:


public class UploadPageController implements Controller {
	
	private static Logger logger = LoggerFactory.getLogger(UploadPageController.class);

	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		logger.info("跳转上传文件页面...");
		ModelAndView view = new ModelAndView();
		//返回 upload.jsp
		view.setViewName("upload");
		return view;
	}
}

跳转上传动作controller:


      
  

保存上传文件到"d:/upload/"下,上传完成后返回“上传成功”

public class UploadFileController implements Controller {
	
	private static Logger logger = LoggerFactory.getLogger(UploadFileController.class);

	//保存路径
	private String saveDir;
	
	public String getSaveDir() {
		return saveDir;
	}

	public void setSaveDir(String saveDir) {
		this.saveDir = saveDir;
	}


	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		logger.info("上传文件...");
		ModelAndView view = new ModelAndView();
		view.setViewName("upload-result");
		boolean isMultipart = ServletFileUpload.isMultipartContent(request);
		
		if(isMultipart) {
			//创建上传路径
//			URL u = UploadFileController.class.getClassLoader().getResource("");
//			String filePathString = u.getPath()+"/upload";
			logger.info("上传路径:" + saveDir );
			File file = new File(saveDir);
			if(!file.exists()) {
				file.mkdirs();
			}
			
			MultipartHttpServletRequest mp = (MultipartHttpServletRequest)request;
			Iterator iterator =  mp.getFileNames();
			while (iterator.hasNext()) {
				String fileName = iterator.next();
				MultipartFile f = mp.getFile(fileName);
				String realName =  f.getOriginalFilename();
				f.transferTo(new File(saveDir + File.separator + realName));
			}
			view.addObject("result", "成功!");
		}
		return view;
	}
}

(4)编写上传页面和上传结果页面
upload.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<% String contextPath = application.getContextPath();
%>


上传文件

选择文件:
备注:

上传

upload-result.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>


上传文件<%= request.getAttribute("result")%>

(5)验证
浏览器访问 http://localhost:8180/spring-springmvc-xml/uploadpage


选择上传redis-6.2.0.tar.gz文件:


点击【Press】上传,结果:


查看d:/upload/文件:


至此,使用 commons-fileupload 上传文件成功!

13.2 Servlet 3.0 multipart parsing

(1) web.xml 增加配置


...
    
    
       d:/upload
      
      
      -1
      
      -1
      
      0
    
    ...

(2) 配置 StandardServletMultipartResolver

   
  
  

(3)使用 13.1 的Controller 和jsp页面
(4)验证

浏览器访问 http://localhost:8180/spring-springmvc-xml/uploadpage



查看d:/upload/文件: