1 如何开发一个Servlet
1.1 流程:
- 写一个普通类继承于HTTPServlet
- 在对应的doxxx方法中编写业务逻辑代码
- 在web.xml文件中配置servlet相关信息
-
servlet
a) servlet-name:将servlet指定一个别名,该别名是给tomcat使用,在一个项目中servletname不能重名
b) servlet-class:指定servlet的全限定类名
-
servlet-mapping:
a) servlet-name:与上面的servlet-name相匹配
b) url-pattern:将servlet指定一个url,供外部访问
-
1.2 访问的过程:
http://localhost:8080/day05/test
http:协议
localhost:主机域名,也可以是ip地址
8080:tomcat的端口
Day05:项目名称
Test:资源名称
当我们在浏览器中输入一个网址,敲回车访问都做了什么事情?
1. 根据域名查找对应的ip地址
a) 本机查找:在操作系统目录下找到hosts文件,根据里面的设置查找,如果找到进行访问找不到,进行 远程查找
b) 远程查找:网络提供商会提供一个域名服务器,只要是正规的域名里面都会进行解析,获取真实的ip地址,返回给浏览器真实的ip地址
2. 找到主机和ip地址,向对应的主机发送请求
3. 根据ip找到主机,根据端口找到tomcat
4. tomcat根据请求的url解析,找到对应的项目
5. /test:tomcat在项目的web.xml文件中查找url-pattern
6. 找到后,获得对应的servlet-name
7. 根据name找到对应的servlet-class
8. 根据全限定类名字符串使用反射创建servlet对象
9. 将请求的内容封装为HttpServletRequest对象,将相应封装为HttpServletResponse对象,调用servlet对象的service方法
10. service方法中解析请求方式,根据请求方式调用对应的doxxx方法
2 Servlet的映射路径
映射路径:我们在web.xml中使用url-pattern配置
配置规则:
1. 精确匹配
/first 匹配url是first的servlet
/first.do 匹配url是first.do的servlet
/first.action 匹配url是first.action的servlet
/user/login 匹配url是/user/login的servlet
/login.html 匹配url是/ login.html的servlet
这种写法很多时候会使用,将动态资源伪装为静态资源的url,伪静态为了提高搜索引擎的权重
2. 模糊匹配 多个url能匹配一个servlet
/* 无论输入任意的url都能匹配
/user/* 只有名字是/user/下的url能匹配
/*.do 是错误写法
*.do 只要url是以.do结尾都能匹配
注意:
1. 如果使用*开头,前面不要在使用/
2. 精确匹配的优先级高于模糊匹配
3 servlet缺省路径
当我们输入url为/的时候,默认打开index.jsp页面
原因:tomcat给我们提供了一个DefaultServlet的类,这个类默认的url就是/,
这个类默认跳转欢迎页面,欢迎页面配有多个,从上向下查找,找到后不再继续查找,显示页面
如果没找到,接着查找下个页面,如果所有的页面都找不到,显示404
打开tomcat的conf/web.xml文件
<servlet> <servlet-name>default</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>listings</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list>
注意:
- tomcat的web.xml配置的信息是针对于这个服务器下面所有的项目生效的,我们项目的web.xml配置的信息是针对于我们这个项目的
- 如果一段配置信息在tomcat的web.xml和我们项目的web.xml中同时配置,也就是说一段配置信息出现了突以我们的配置为准
- 如果我们也配置一个url为/,tomcat的默认没有生效
如果我们的欢迎页面不是index命名的,可以在我们的web.xml文件中配置如下信息:
<welcome-file-list> <welcome-file>hello.html</welcome-file> <welcome-file>hello.htm</welcome-file> <welcome-file>hello.jsp</welcome-file> </welcome-file-list>
当一个请求过来的时候,tomcat查找url的规则是什么?
- Tomcat先查找动态资源
- 先查找精确匹配
- 再查找模糊匹配的
- 找不到返回404
如果请求过来的是/index.jsp,如何查找?
- /和/欢迎页面同样效果,在这个例子中/和/hello.jsp是等效的
- 先查找web.xml文件,看看有没有合适的动态资源的配置
- 没有找到,使用默认的DefaultServlet进行处理
- 显示欢迎页面
- 如果项目的web根目录下没有对应的欢迎页面,返回404
4 Sevlet的生命周期(重点)
4.1 引入
我们之前学习的对象的生命周期:
- 使用new或者反射创建对象
- 使用构造方法或者动态代码块初始化对象的属性
- 对象创建后,可以调用对象的属性和方法
- 当对象失去引用被回收后,对象销毁
4.2 Servlet重要的四个生命周期方法
- 构造方法 容器启动后,用户第一次访问servlet的时候,只创建一次
- init方法 构造方法执行后,执行,只执行一次
- doxxx方法 用户访问一次就执行一次
- destroy方法 容器关闭的时候,销毁servlet的时候执行一次
结论:servlet是一个单例多线程的程序,对象的创建延迟到用户第一次访问的时候
5 Servlet的自动加载
Servlet对象创建的时机:用户第一次访问的时候,容器启动的时候不会执行
注意:
- 在某些情况下,我们希望servlet对象的创建提前到容器启动的时候此处我们可以使用<load-on-startup>1</load-on-startup>在配置servlet的时候,使用这个标签进行配置,会让servlet随着容器的启动创建对象
- 这个标签中需要制定一个int类型的值,这个值代表自启动的servlet的启动优先级,数值越小,优先级越高,数值越大,优先级越小
6 Servlet的多线程并发问题
Servlet在设计的时候是线程安全的,也就是说正常情况下使用没有线程安全的问题
线程安全一般出现在多线程使用同一个方法访问同一个共享数据的时候
如果我们在servlet中定义了属性,在doxxx方法中编辑这个值,可能会出现线程安全问题
解决办法:
- 在doxxx方法中使用同步
- 避免在servlet中定义属性
7 ServletConfig对象
7.1 作用
servletConfig对象不是我们自己创建的,是tomcat创建给我们使用的
我们使用这个对象可以获取servlet的配置信息
7.2 对象创建和得到
创建:tomcat帮我们创建
得到:在servlet类的init方法中,通过形参获取
Api:
String getInitParameter(String key):获取指定的初始化参数
Enumeration<String> getInitParameterNames(String key):获取所有的初始化参数
ServletContext getServletContext():获取servlet上下文对象
String getServletName(): 获取servlet-name
8.3 servlet的初始化参数配置
- Servlet的初始化参数:
- 我们在配置servlet信息的时候,在servlet标签中使用init-param标签配置的参数
- Servlet的初始化参数可以配置多个
- Servlet的初始化参数只能在这个servlet中内部使用,别的servlet不能获取
作用:为了保证servlet的正确执行设置的一些初始化信息
8 ServletContext对象
8.1 引入
ServletContext对象我们称为servlet上下文对象,通俗的理解当前项目的运行环境
还可以理解为项目对象
8.2 对象创建和得到
创建:tomcat创建,容器启动的时候,一个运行的web项目只有一个
获取:
- 使用请求获取:req.getServletContext()
- 使用servletConfig获取:config.getServletContext()
8.3 ServletContext对象的核心API(作用)
初始化参数相关:
String getInitParameter(String key):获取指定的初始化参数
Enumeration<String> getInitParameterNames(String key):获取所有的初始化参数
域空间操作相关:
Void setAttribute(String key,Object value):向上下文域空间中添加一个键值对
Object getAttribute(String key):从上下文域空间中根据指定的键获取对应的值
Void removeAttribute(String key):从上下文域空间中根据指定的键删除对应的键值对
其他:
String getRealPath(String path): 给出一个web项目中的相对路径,获取对应的绝对路径
InputStream getResourcesAsStream(String path):给出一个文件的相对路径,返回该文件对应的输入流
String getContextPath:获取项目对应的url,我们进行页面跳转的时候使用
Void getRequestDispatcher(String path).forward(req,resp):转发跳转页面
8.4 得到web应用路径
String getContextPath:获取web项目路径
我们进行重定向跳转页面的时候,用来配合页面的路径使用
8.5 得到web应用的初始化参数(全局)
项目应用的初始化参数的配置:
在项目的web.xml文件中使用context-param进行配置,指定参数名和参数值
初始化参数可以配置多个
参数的获取:
String getInitParameter(String key):获取指定的初始化参数
Enumeration<String> getInitParameterNames(String key):获取所有的初始化参数
8.6 获取真实路径
在web项目中读写文件的时候,不能直接使用项目中的相对路径,需要使用真实路径(绝对路径)
- String getRealPath(String path):使用该方法给出一个web项目的相对路径,返回一个绝对路径
- InputStream getResourcesAsStream(String path):给出一个web项目文件的相对路径,返回对应的文件的输入流
8.7 域对象有关的方法
域对象作用:在不同的servlet之间共享数据
Servlet中的域对象一共有4个:
pageContext HttpServletRequest HttpSession ServletContext
上面书写的顺序是作用域从小到大
上面的四个域对象操作里面数据的方法都是一样的:
Void setAttribute(String key,Object value):向域空间中添加一个键值对
Object getAttribute(String key):从域空间中根据指定的键获取对应的值
Void removeAttribute(String key):从域空间中根据指定的键删除对应的键值对
Request域空间的作用域:只能在同一次请求中,操作数据一次请求,可以跨域多个资源
8.8 转发
服务端跳转资源:
- 重定向:response.sendRedirect()
- 转发:servletContext/request.getRequestDispatcher(String path).forward(req,resp)
转发和重定向的区别:
- 转发只能转发站内资源,重定向可以跳转站内资源和站外资源
- 转发后地址栏不变,重定向地址栏发生改变
- 转发后的资源,和前面是同一个请求,重定向后的资源,和前面不是同一个请求重定向就是发起新的请求