猿蜕变4——一文获取web框架正确学习套路
看过之前的springMVC初体验,相信你对springMVC有了一定的认识。今天我们继续来学习springMVC相关的核心知识,掌握web框架的正确学习办法,帮助你快速起飞,完成蜕变。
在这章节之前,我们已经编写了第一个SpringMVC的程序—HelloSpringWebMVC,也对它做了简单的流程分析,实际上SpringMVC还有其他的执行流程,下面这幅图,就是springMVC的执行流程图:
0.在应用启动时,我们配置的前端控制器DispatcherServlet加载spring MVC相关的配置文件,完成应用的初始化工作,这个事情只会在应用启动时做一次,。
1.用户发起请求http://127.0.0.1/helloWebMvc.do,所有满足DispatcherServlet 的URL规则的请求,都会被匹配转发到DispatcherServlet。
2.DispatcherServlet将Url交由处理器映射器(HandlerMapping)处理。
3. 处理器映射器(HandlerMapping)会返回一个执行链(这个请求需要执行哪些步骤,包括公共部分和我们自己编写的Controller)给DispatcherServlet。
4. DispatcherServlet根据之前返回的执行链,再次请求处理适配器(HandlerAdper)。
5. 处理适配器(HandlerAdper)将执行链交由相匹配的处理器(Handler)执行。
6. 处理器(Handler)执行具体的处理流程并且返回ModelAndView对象
7. 处理适配器(HandlerAdper)将处理器(Handler)返回的ModelAndView对象返回给前端控制器DispatcherServlet。
8. 前端控制器DispatcherServlet请求视图解析器(ViewResolver)查找对应的视图。
9. 视图解析器(ViewResolver)将对应的视图对象(View)返回给前端控制器DispatcherServlet
10.前端控制器将视图对象(View)转发给对应的视图组件。视图组件(比如jsp、velocity等等具体的视图组件)完成渲染工作,将渲染结果(很多时候是HTML文档)返回给前端控制器DispatcherServlet。
11. 前端控制器DispatcherServlet将最后的结果返回给用户(浏览器)。
配置url-pattern为*.do,这个是最常用的方式,其实你要是配置为*.xxx都是可以的,只要url能匹配,没什么问题,程序可以执行,但是,很多时候可能习惯成自然,大家都这么干,你也就必须这么干,因为在中国大家是最厉害的群体,不敢轻易得罪,得罪了容易没饭吃啦。
如果将url-pattern配置为/*,那么所有的请求都会到达DispatcherServlet,如果你直接请求一个jsp页面,也会被当作是一个Controller去处理,而DispatcherServlet找不到你请求的jsp页面(因为它会认为你请求的是一个Controller),就会造成404错误。所以在实际的开发过程中,最好不要去做/*的配置
如果将url-pattern配置为/,那么应用中涉及的静态资源:比如html页面、css文件、js文件、图片等等,都会交由DispatcherServlet处理。这种配置方式不会拦截.jsp文件和.jspx文件,因为这个在tomcat中的conf目录里面的web.xml文件中已经做了相关配置处理,这些请求会交给org.apache.jasper.servlet.JspServlet去处理,能够正常的访问到jsp页面。
解决静态资源不能访问的问题,解决方式有三种:
使用defaultServlet:
在tomcat中的conf/web.xml中配置,增加一个DefaultServlet的配置,当某个请求系统找不到由谁去处理时,就会让DefaultServlet去处理。我们可以DefaultServlet去处理静态资源,如果你要配置在应用中配置也是可以的,只是由一个要求:必须配置在DispatcherServlet之前:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
使用mvc:default-servlet-handler:
在Spring MVC的配置文件中(spring-servlet.xml)增加配置即可,这种方式会将所有的请求交由对应的servlet进行处理,当然,最终也是由DefaultServlet来处理:
<mvc:default-servlet-handler/>
使用mvc:resources:
SpringMVC提供了mvc:resources标签来专门解决解决静态资源无法访问的问题,只需要在Spring MVC的配置文件中(spring-servlet.xml)增加以下配置即可,这样这些静态资源会交给Spring MVC提供的ResourceHttpRequestHandler进行处理:
<mvc:resourcesmapping="/static/**" location="/ static /" />
mapping表示对静态资源url请求的要求。需要特别注意的是,/后是两个星号**。
location表示静态资源存放的目录,这个路径是一个相对路径,相对于应用的webapp目录的一个路径,要求资源位于webapp目录下,我们配置成了/ static /,所以我们可以在应用的webapp目录下创建一个static文件夹,然以后将所有的静态资源放进去,一般来说我们对静态文件需要做下分类,所以会在static目录下再建立子目录:css,js,images,分别存放css文件,js文件,和图片。推荐使用该配置。
我们之前编写Spring MVC 程序,需要在spring-servlet.xml中配置我们的Controller,比如:
<bean id="/helloWebMvc.do"class="com.pz.web.study.springmvc.controller.HelloSpringWebMVC"/>
随着我们需要开发的功能增加,我们会编写更多的Controller,这样一来,每增加一个Controller,我们就需要增加一行类似的配置,spring-servlet.xml就会越来越大,慢慢的变得难以维护。,而实际上,Spring MVC提供了基于注解的方式来解决这个问题,让配置文件变得更加简洁明了。接下来,我们就使用注解的方式来编写我们的Controller。
使用注解编写spring MVC 的Controller程序,和使用配置文件的方式基本一致,也需要在web.xml配置DispatherServlet(咱们之前已经加过了,暂时不用动了)。我们需要在对SpringMVC的配置文件做一些修改就好:
配置组件扫描器
我们在配置文件中增加组件扫描器就好了。修改spring-servlet.xml配置文件,增加配置:
<!-- 自动扫描com.pz.web.study.springmvc.controller路径下的所有文件,并根据注解完成注入的工作 -->
<context:component-scan base-package="com.pz.web.study.springmvc.controller.*"></context:component-scan>
以上配置增加以后,在应用启动时,SpringMVC 会扫描com.pz.web.study.springmvc.controller包下所有类,并对所有增加了Spring MVC 能够识别的Controller的Annotation的类做实例化操作(大家想想咱的小框架,是不是很类似?)。
配置注解驱动(如果你使用了mvc:resources标签就需要增加这个配置,要不会有404错误)
修改spring-servlet.xml配置文件,增加配置:
<mvc:annotation-driven/>
编写Controller代码在com.pz.web.study.springmvc.controller包下创建AnnotationControllerDemo类:
package com.pz.web.study.springmvc.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class AnnotationControllerDemo {
@RequestMapping("/helloByAnnotation.do")
public ModelAndViewhelloAnnotation(HttpServletRequest req, HttpServletResponse res) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("hello", "hello spring web mvc by helloAnnotation");
mv.setViewName("helloByAnnotation");
return mv;
}
}
编写页面代码helloByAnnotation.jsp,测试页面嘛可以简单点,启动tomcat,我们访问下:
http://127.0.0.1/helloByAnnotation.do页面输出
hello spring web mvc by helloAnnotation
我们打开之前编写的AnnotationControllerDemo类,这类没有实现任何接口,只是在类名和方法上添加了两个注解:
@Controller(需要引入org.springframework.stereotype.Controller):使用在类名上,表示是一个Controller。
@RequestMapping(需要引入org.springframework.web.bind.annotation.RequestMapping):使用在方法上,表示该方法为Controller提供的方法,属性值value,为一个URI,表示这个方法响应对应的URL,这个URL是一个相对路径,相对于webapp,方法名可以随意命名。一个方法也可以处理多个请求,只用定义多个url就好。 @RequestMapping也可以被使用在类名上,表示这个Controller类下的所有方法,都属于一个目录。当@RequestMapping被使用在类名上时,方法上的@RequestMapping就相对于类名上定义的路径。为了加深大家的理解我们看下面的例子。
package com.pz.web.study.springmvc.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/demo/")
publicclass AnnotationControllerDemo2 {
@RequestMapping("/hello.do")
public ModelAndView hello(HttpServletRequest req,HttpServletResponse res) throws Exception{
ModelAndView mv = new ModelAndView();
mv.addObject("hello", "hello spring web mvc by helloAnnotation");
mv.setViewName("helloByAnnotation");
return mv;
}
@RequestMapping({"/hello2.do","/hello3.do"})
public ModelAndView hello2(HttpServletRequest req,HttpServletResponse res) throws Exception{
ModelAndView mv = new ModelAndView();
mv.addObject("hello", "one method for multiple urls");
mv.setViewName("helloByAnnotation");
return mv;
}
}
启动tomcat分别访问:
http://127.0.0.1/demo/hello.do
http://127.0.0.1/demo/hello2.do
http://127.0.0.1/demo/hello3.do
- 浅谈MySQL中的事务隔离级别(r11笔记第86天)
- 巧用echo命令解决Samba批量添加用户难题
- 分分钟搭建MySQL Group Replication测试环境(r11笔记第82天)
- MySQL 5.7 Group Replication错误总结(r11笔记第84天)
- 空结构体struct{}解析
- 动态创建MySQL Group Replication的节点(r11笔记第84天)
- sysbench压测小记(r11笔记第99天)
- WordPress启用memcached动态缓存以及报错解决
- 升级CentOS6.5内核,开启Nginx的fastopen和reuseport特性
- Nginx网站使用CDN之后禁止用户真实IP访问的方法
- 相差数十倍的SQL性能分析(r11笔记第98天)
- shell脚本实现整站缓存和预缓存,进一步提升网站整体加载速度
- Oracle中的PGA监控报警分析(r11笔记第96天)
- MySQL错误修复记录:Table xx is marked as crashed and should be repaired
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- js删除数组对象中符合条件的数据
- .net core webapi jwt 更为清爽的认证 ,续期很简单(2)
- 手把手教你写一个windows服务 【基于.net】 附实用小工具{注册服务/开启服务/停止服务/删除服务}
- 一网打尽枚举操作 .net core
- Jenkins 发布.net core 程序,服务端无法下载nuget包的解决方法 error NU1102: 找不到版本为 (>= 3.1.6) 的包
- NET Core Kestrel部署HTTPS 一个服务器绑一个证书 一个服务器绑多个证书
- .net core webapi jwt 更为清爽的认证 ,续期很简单(1)
- 用flask来在线管理你的iptables
- Linux Shell命令速查表
- Windows10实现滑动锁屏
- Vue&uni-app在微信浏览器隐藏titleNView的一个方法
- 使用OData服务将SAP C4C自定义BO的TextCollection暴露给外部消费者
- 如何在SAP C4C AdvancedListPane上批量执行若干BO实例的action
- SAP ABAP Webdynpro ALV的link to action的实现方法
- SAP CRM和C4C表格列宽度调整的工作原理