博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringMVC 之搭建第一个JavaWeb应用
阅读量:2454 次
发布时间:2019-05-10

本文共 11106 字,大约阅读时间需要 37 分钟。

文章目录

SpirngMVC架构图

在这里插入图片描述

总结:
1、用户发起请求,到前端控制器(DispatchServlet),会执行到(doDispatch)方法;
2、循环 HandlerMapping 查找 Handler,返回一个处理器执行链(HandlerExecutionChain);
HandlerExecutionChain 包含:
a)Handler对象
b) HandlerInterceptor[] 拦截器数组
4、通过HandlerAdapter进行包装Handler,返回一个HandlerAdapter对象;
5、循环执行处理器执行链中拦截器的前置方法;
6、通过适配器执行Handler,返回一个ModelAndView;
a)Model Data(模型数据)
b)View(ViewName) 视图名称
7、DispatcherServlet将ModelAndView传给ViewReslover视图解析器;
8、ViewReslover解析后返回具体View;
9、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中);
10、DispatcherServlet响应用户。

简单总结:

1、请求进入中央处理器(DispatcherServlet)
2、通过HandlerMapping查询业务逻辑类
3、通过HandlerAdapter执行业务逻辑
4、通过ViewReslover渲染视图
5、DispatcherServlet响应用户

为什么要设计适配器?

适配器是专门用来执行业务方法的,业务方法的Controller有很多种类型,如果没有适配器的话,在DispatcherServlet中调用Controller中业务方法的时,需要判断Controller类型后再调用;如果这是我们想扩展一个自己的Controller,是需要改源码做判断调用。违反扩展开放,修改关闭的原则。如果有个适配器,这时要扩展Contrller,只需要编写自己的Controller和实现适配器接口就可以了。

开发第一个SpringMVC应用

创建SpringMVC工程

在这里插入图片描述

工程目录结构

在这里插入图片描述

导入依赖

4.0.0
com.springmvc
SpringMVCTest
1.0.0-SNAPSHOT
war
4.10
1.6.4
4.1.3.RELEASE
1.2
2.5
2.0
org.springframework
spring-webmvc
${spring.version}
org.slf4j
slf4j-log4j12
${slf4j.version}
jstl
jstl
${jstl.version}
javax.servlet
servlet-api
${servlet-api.version}
provided
javax.servlet
jsp-api
${jsp-api.version}
provided
org.apache.tomcat.maven
tomcat7-maven-plugin
80
/

配置web.xml

在src/main/webapp下创建WEB-INF目录以及web.xml

配置DispatcherServlet

spingmvc
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc-servlet.xml
1
springmvc
*.do

web.xml 常用配置

CharacterEncodingFilter过滤器

CharacterEncodingFilter类是一个过滤器,当前台JSP页面和JAVA代码中使用了不同的字符集进行编码的时候就会出现表单提交的数据或者上传/下载中文名称文件出现乱码的问题,那这个类就可以出场了。

CharacterEncodingFilter类具有encoding和forceEncoding两个属性,其中encoding是表示设置request的编码,forceEncoding表示是否同时设置response的编码。

encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceEncoding
true
encodingFilter
/*
Spring加载配置文件

在web.xml中定义contextConfigLocation参数,Spring会使用这个参数去加载所有逗号分隔的xml文件,如果没有这个参数,Spring默认加载WEB-INF/applicationContext.xml文件。

配置Spring加载的配置文件:

contextConfigLocation
classpath*:spring-basic.xml, classpath*:conf/spring/applicationContext_core*.xml, /WEB-工NF/daoContext.xml
org.springframework.web.context.ContextLoaderListener

配置SpringMVC:

spring-mvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath*:spring-mvc.xml
1
spring-mvc
*.do
错误页面配置

在web.xml中有两种配置error-page的方法,一是通过错误码来配置,而是通过异常的类型来配置。

通过错误码来配置error-page:

404
/index.jsp

通过异常的类型配置error-page:

java.lang.Exception
/index.jsp

注意:<error-code><exception-type>不能在同一个<error-page>标签上同时出现。

首页配置

默认从webapp目录下寻找首页,也可以配置WEB-INF目录下的文件。

index.jsp
/WEB-INF/views/index.jsp

配置日志文件

在src/main/resources下创建log4j.properties

log4j.rootLogger=DEBUG,A1log4j.logger.org.mybatis = DEBUGlog4j.appender.A1=org.apache.log4j.ConsoleAppenderlog4j.appender.A1.layout=org.apache.log4j.PatternLayoutlog4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n

SpringMVC配置文件

在src/main/resources下创建springmvc-servlet.xml

SpringMVC默认从WEB-INF下读取servlet配置文件,文件的命名规则是:servletName-servlet.xml

如果要自定义servlet文件,需要在servlet定义时指定contextConfigLocation。

配置文件解析:

1、配置处理器映射器HandlerMapping
2、配置处理器适配器HandlerAdapter
3、配置模型Handler
4、配置视图解析器ViewResolver

HandlerMapping:

在这里插入图片描述
HandlerAdapter:
在这里插入图片描述
ViewResolver:
在这里插入图片描述

为什么要设计适配器?

Controller是多种类型的,如果没有适配器,在DispatcherServlet中调用Hadnler,需要判断Controller类型做调用,我们想去扩展自己的Controller,需要去改源码做判断调用。违反开闭(对扩展开放,对修改关闭)原则。

如果有了适配器,如果要扩展Controller,只需要写自己的Controller和实现适配器接口即可。

编写模型对象处理器

package com.springmvc.handler;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.mvc.Controller;public class HelloHandler implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 处理业务逻辑 ModelAndView mv = new ModelAndView(); mv.setViewName("hello");// 设置视图名称 mv.addObject("msg", "我的第一个SpringMVC应用!");// 设置模型数据 // request.setAttribute("msg", "xxxxx"); return mv; }}

启动Tomcat查看效果

在这里插入图片描述

在这里插入图片描述
测试:
在这里插入图片描述

DispatcherServlet源码解析

DispatcherServlet源码初始化过程

protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context); //文件上传组件 initLocaleResolver(context); //国际化 initThemeResolver(context);// 主题 initHandlerMappings(context);// HandlerMapping 处理器映射 initHandlerAdapters(context);// HandlerAdapter 适配器 initHandlerExceptionResolvers(context); //异常相关组件 initRequestToViewNameTranslator(context); // 转化 initViewResolvers(context); // ViewResolvers 视图解析器 initFlashMapManager(context); // 闪存 }

初始化映射器

在这里插入图片描述
初始化适配器
在这里插入图片描述
SpringMVC的默认配置文件
org.springframework.web.servlet.DispatcherServlet.properties在这里插入图片描述

发现默认的配置文件中已经配置了默认的映射器和适配器,所以可以简化配置,无需配置映射器和适配器。

在这里插入图片描述

在DispatcherServlet中的doDispatch方法是SpringMVC的执行流程的控制方法,源码如下:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request; // 定义执行链 HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try {
ModelAndView mv = null; Exception dispatchException = null; try {
processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. // 获取执行链 mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. // 获取Handler的适配器 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return; } } // 执行链中拦截器的前置方法,如果返回false则终止执行。 if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return; } try {
// Actually invoke the handler. // 通过Handler适配器执行Handler mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); } finally {
if (asyncManager.isConcurrentHandlingStarted()) {
return; } } applyDefaultViewName(request, mv); // 执行拦截器的后置方法 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) {
dispatchException = ex; } // 处理返回的结果,视图解析器的处理 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err); } finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); return; } // Clean up any resources used by a multipart request. if (multipartRequestParsed) {
cleanupMultipart(processedRequest); } } }// 1、定义执行处理器执行链(HandlerExecutionChain mappedHandler = null;)// 2、获取处理器执行链(mappedHandler = getHandler(processedRequest);)// 3、获取处理器适配器(HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());)// 4、执行链中拦截器的前置方法,如果返回false则终止执行(if (!mappedHandler.applyPreHandle(processedRequest, response)))// 5、通过适配器执行真正的业务处理器逻辑,并返回模型和视图对象(mv = ha.handle(processedRequest, response, mappedHandler.getHandler());)// 6、执行链中拦截器的后置方法(mappedHandler.applyPostHandle(processedRequest, response, mv);)// 7、处理返回的结果,视图解析器的处理(processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);)// 8、查找到视图后进行渲染,然后响应给请求端

使用注解方式开发SpringMVC应用

在第一个SpringMVC应用的基础上修改SpringMVC配置文件和编写模型对象处理器。

下面两个配置不是SpringMVC默认配置,所以不能省略。

SpringMVC配置文件

编写模型对象处理器

使用@RequestMapping映射请求URL

使用@Controller注解使HelloHandler 成为处理请求的控制器

package com.springmvc.handler;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;@Controller@RequestMapping("/hello")public class HelloHandler {
@RequestMapping("/show") public ModelAndView show() {
// 处理业务逻辑 ModelAndView mv = new ModelAndView(); mv.setViewName("hello");// 设置视图名称 mv.addObject("msg", "我的第一个注解SpringMVC应用!");// 设置模型数据 return mv; }}

使用tomcat7启动后并测试

在这里插入图片描述

升级版注解驱动

作用:SpringMVC默认配置的升级版;

对应的java类是:

org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser

使用<mvc:annotation-driven />后默认加入的HandlerMapping和Adapter有:

在这里插入图片描述

HandlerMapping有2个:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMappingorg.springframework.web.servlet.handler.BeanNameUrlHandlerMappingAdapter有3个:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapterorg.springframework.web.servlet.mvc.HttpRequestHandlerAdapterorg.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter

改进后的注解SpringMVC配置

在这里插入图片描述

代码

转载地址:http://pdchb.baihongyu.com/

你可能感兴趣的文章
如何使用TensorFlow对象检测API播放Quidditch
查看>>
交付方式 saas_我在全职工作时如何交付我的第一个SaaS副项目
查看>>
instagram技术_Instagram9位科技女孩进行技术采访的主要技巧
查看>>
angular面试题及答案_关于最流行的Angular问题的StackOverflow上的48个答案
查看>>
zeppelin连接数据源_使用开放源代码合同(open-zeppelin)创建以太坊令牌
查看>>
ai人工智能程序_简单解释:一个AI程序如何掌握Go的古老游戏
查看>>
以下是ECMAScript 2016、2017和2018中所有新增功能的示例
查看>>
初创团队最重要的是什么_我从一家出色的初创公司工作中学到的最重要的教训...
查看>>
kafka应用于区块链_Apache Kafka的区块链实验
查看>>
印地语freeCodeCamp YouTube频道+不和谐聊天现已上线
查看>>
css content属性_CSS之前和之后CSS –如何使用content属性
查看>>
如何将ApexCharts与Vue.js集成-详细指南
查看>>
ntp时间同步会同步时区吗_如何处理时区并使软件与国际客户同步
查看>>
nsfw_如何使用机器学习设置NSFW内容检测
查看>>
react中使用构建缓存_如何使用React构建客户支持实时聊天小部件
查看>>
reactjs生命周期_如何在ReactJS中了解组件的生命周期方法
查看>>
graphql和rest_如何使用GraphQL使您的网站整洁和可维护
查看>>
flutter dart_Dart和Flutter的简化介绍
查看>>
hbuilder自述文件_为什么创建自述文件已成为我最喜欢的开发部分
查看>>
从ES5到ESNext-这是自2015年以来添加到JavaScript的所有功能
查看>>