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/文件: