Servlet
什么是Servlet?
-
Servlet是JavaWeb三大组件之一(Servlet、Filter、Listener)
-
Servlet是用来处理客户端请求的动态资源。服务器会把接收到的请求交给Servlet来处理
-
Servlet的任务有:
获取请求数据
处理请求
完成响应 -
Servlet接口方法:
void init(ServletConfig)
void service(ServletRequest,ServletResponse)
void destory()
ServletConfig getServletConfig()
String getServletInfo()
实现Servlet的方式
- 实现Servlet接口(不方便)
- 继承GenericServlet类(不方便)
- 继承HttpServlet类(方便,常用)
如何使用Servlet?
-
定义一个类并且extends HttpServlet
-
重写servive()方法
-
在web.xml中进行映射配置
-
通过浏览器访问映射的url
LoginServlet.java public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * 构造方法 */ public LoginServlet() { System.out.println("========构造方法======="); } /** * 服务方法 */ @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("=========service(req,resp)======="); String method = req.getMethod(); if("get".equalsIgnoreCase(method)) { this.doGet(req, resp); }else if("post".equalsIgnoreCase(method)) { this.doPost(req, resp); } } /** * 当前请求的method为get时 执行这里 */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("==========doGet()======"); } /** * 当前请求的method为post时 执行这里 */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("=========doPost()======"); } @Override public void init() throws ServletException { System.out.println("=========init()初始化======"); } @Override public void init(ServletConfig config) throws ServletException { System.out.println("========init(config)======"); } @Override public void destroy() { System.out.println("=======destroy()销毁方法====="); } } web.xml配置Servlet,把访问路径/login与一个com.wdzl.servlet.LoginServlet绑定到一起 <servlet> <servlet-name>login</servlet-name> <servlet-class>com.wdzl.servlet.LoginServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/login</url-pattern> </servlet-mapping>
浏览器不能直接访问Servlet文件,只能通过映射的方式来间接访问Servlet,映射配置方式:
-
基于xml文件配置
- 的子标签:
- 的子标签:
<servlet> <servlet-name>hello</servlet-name> <servlet-class>org.my.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/demo2</url-pattern> </servlet-mapping>
- 注解配置
@WebServlet("/demo2") public class HelloServlet implements Servlet { }
-
Servlet生命周期 (重点):实例化,初始化,服务,销毁
1.由谁来控制的 ? == 容器
由容器(Tomcat,Jboss,Weblogic,glassfish等) 不需要我们去实例化和调用
2.四个阶段:实例化,初始化,服务,销毁
-
**加载和实例化:**容器通过构造方法完成实例化,一次,单例的 。
注意:serlvet的请求和响应使用的是多线程
服务器创建Servlet:
- 当Servlet第一次被请求时,或服务器启动时,服务器会创建Servlet实例。
- 服务器默认是在servlet第一次被请求时创建Servlet实例,如果希望服务器启动时就创建Servlet实现需要在web.xml中配置
- 服务器只为一个Servlet创建一个实例对象,所以Servlet是单例的
-
**初始化:**init()方法
注意:init有两个重载的方法,有参和无参,执行一次。
想要获取初始化参数时,使用init(ServletConfig config)
服务器初始化Servlet:
- 当服务器创建Servlet实例后会马上调用Servlet的init(ServletConfig)方法,完成对Servlet的初始化
- init(ServletConfig)只会被调用一次
- 服务器会在调用init()方法时传递ServletConfig参数
-
**服务:**service()方法, 执行多次,每次请求都会执行
服务器使用Servlet处理请求:
- 当Servlet被请求时,服务器会调用Servlet的service(ServletRequest,ServletResponse)方法
- service(ServletRequest,ServletResponse)方法每处理一次请求,就会被调用一次,所以它可能会被调用N次
- 因为Servlet是单例的,所以可能在同一时刻一个Servlet对象会被多个请求同时访问,所以这可能出现线程案例问题
- Servlet不是线程案例的,这有助与提高效率,但不能让Servlet具有状态,以免多个线程争抢数据
-
**销毁:**destroy()方法,执行一次。 服务器容器停止或servlet实例需要重新加载时
服务器销毁Servlet:
- 服务器通常不会销毁Servlet,通常只有在服务器关闭时才会销毁Servlet
- 服务器会在销毁Servlet之前调用Servlet的destory()方法
- 可以在destory()方法中给出释放Servlet占有的资源,但通常Servlet是没什么可要释放的,所以该方法一般都是空的
2.1 顺序?
web.xml中配置,load-on-startup设置
2.2 Servlet实例化、初始化时间?(面试)
-
默认情况下,Servlet是在第一次被访问时由服务器创建的。
-
如果服务器启动时就创建Servlet,那么还需要在web.xml文件中配置。
在服务器启动时,进行实例化和初始化,启动配置为-1,表示不随服务器启动(第一次被访问时加载)
如果大于等于0时,按数字由小到大依次启动
<servlet> <servlet-name>hello1</servlet-name> <servlet-class>my.servlet.Hello1Servlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>hello1</servlet-name> <url-pattern>/hello1</url-pattern> </servlet-mapping> <servlet> <servlet-name>hello2</servlet-name> <servlet-class>my.servlet.Hello2Servlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>hello2</servlet-name> <url-pattern>/hello2</url-pattern> </servlet-mapping> <servlet> <servlet-name>hello3</servlet-name> <servlet-class>my.servlet.Hello3Servlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>hello3</servlet-name> <url-pattern>/hello3</url-pattern> </servlet-mapping>
service和doGet doPost 关系?
在HttpServlet的**service(HttpServletRequest,HttpServletResponse)**方法会去判断当前请求是GET还是
POST**(在service方法中,获取请求的method,来调用doGet和doPost)**,如果是GET请求,那么会去调用本类
的doGet()方法,如果是POST请求会去调用doPost()方法,这说明我们在子类中去覆盖doGet()或doPost()方法即
可。
/**
* 服务方法
*/
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("=========service(req,resp)=======");
String method = req.getMethod();
if("get".equalsIgnoreCase(method)) {
this.doGet(req, resp);
}else if("post".equalsIgnoreCase(method)) {
this.doPost(req, resp);
}
}
如何正确的获取request,response,out,application,session,config对象
-
request、response:service(HttpServletRequest req, HttpServletResponse resp),
是容器帮我们实例化,传过来的
-
session:HttpSession session = req.getSession()
-
out:PrintWriter out = resp.getWriter();
-
**application:ServletContext application = getServletContext(); **
正常使用的前提,没有定义有参的init方法
对象 | 描述 |
---|---|
request | HttpServletRequest 接口的实例 |
response | HttpServletResponse 接口的实例 |
out | JspWriter类的实例,用于把结果输出至网页上 |
session | HttpSession类的实例 |
application | ServletContext类的实例,与应用上下文有关 |
config | ServletConfig类的实例 |
pageContext | PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问 |
page | 类似于Java类中的this关键字 |
Exception | Exception类的对象,代表发生错误的JSP页面中对应的异常对象 |
public class CountServlet extends HttpServlet {
private int count;//计数
/**
* 9大内置对象:
* request response out session config
* page,exception,application,pageContext
*
* request,session,application
* response out config
*
*/
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//注意:设置的位置一定是在getWriter()之前
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
HttpSession session = req.getSession();
ServletContext application = getServletContext(); //正常使用的前提,没有定义有参的init方法
System.out.println(">>>=="+application.getInitParameter("config"));
System.out.println(">>>=="+application.getInitParameter("charset"));
count++;
out.println("<h1>第"+count+"次访问!</h1>");
}
@Override
public void destroy() {
}
@Override
public void init() throws ServletException {
System.out.println("=======init()=========");
}
private ServletContext application;
// @Override
// public void init(ServletConfig config) throws ServletException {
// String ct = config.getInitParameter("initCount");
//
// application = config.getServletContext(); //获取application serlvet的上下文
// System.out.println(">>>==="+obj);
// try {
// count = Integer.parseInt(ct);
// } catch (Exception e) {
// count = 0;
// }
// }
}
注意:乱码问题
区分是请求乱码还是响应乱码:
获取提交参数乱码了,request请求的问题 req.setCharacterEncoding("UTF-8");
如果是out输出乱码了,response响应问题 resp.setContentType("text/html;charset=utf-8");
ServletContext是JavaWeb四大域对象之一:
-
PageContext;
-
ServletRequest;
-
HttpSession;
-
ServletContext;
Session获取问题:
HttpSession session = Request.getSession(true/false);
//false:获取session对象=====如果获取到session对象,则返回对象;如果获取不到,返回null
//true:默认的,无参时,默认为true=====获取session对象,如果获取到session对象,返回对象; 如果获取不到,创建一个新的session对象并返回
问题:Object o = request.getSession(); o可能为null ?
不可能
//登录成功
request.getSession();
//注销操作(原来session存在,注销,否则不用重复注销)
HttpSession session = request.getSession(false);
if(session != null){
session.invalidate();
}
初始化参数配置和获取?
- init方法参数如何使用
- init方法有两个同名重载方法,如果有参构造方法声明了,则不再调用无参方法。
- config用来获取初始化配置,web.xml中的配置(注解中)
配置url-pattern映射多种方式?
是的子元素,用来指定Servlet的访问路径,即URL(以“/”开头)
-
可以在中给出多个,例如:
<servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/AServlet</url-pattern> <url-pattern>/BServlet</url-pattern> </servlet-mapping> 一个Servlet绑定了两个URL,无论访问/AServlet还是/BServlet,访问的都是HelloServlet
-
还可以在中使用通配符“*”,可以匹配任何URL前缀或后缀,使用通配符可以命名一个Servlet绑定一组URL,例如:
路径匹配:(具体url配置映射,前面注意前面斜杠 /) <url-pattern>/servlet/*<url-patter> :/servlet/a、/servlet/b,都匹配/servlet/*; 后缀匹配:(根据请求后缀拦截一类请求 *.jsp 注意:不能有斜杠) <url-pattern>*.do</url-pattern> :/abc/def/ghi.do、/a.do,都匹配*.do; 缺省匹配:(匹配所有请求 /*) <url-pattern>/*<url-pattern> :匹配所有URL;
注意:需要组合配合时,可以对同一个servlet做多次映射
ServletConfig:
ServletConfig是Servlet中的init()方法的参数类型
-
String getServletName():获取Servlet配置名,即的值;
-
ServletContext getServletContext():获取ServletContext对象,这个对象稍后介绍
-
String getInitParameter(String name):获取初始化参数
-
Enumeration getInitParameterNames():获取所有初始化参数的名称
在web.xml文件中,配置<servlet>时可以为<servlet>配置0~N个初始化参数,例如: <servlet> <servlet-name>xxx</servlet-name> <servlet-class>my.servlet.MyServlet</servlet-class> <init-param> <param-name>p1</param-name> <param-value>v1</param-value> </init-param> <init-param> <param-name>p2</param-name> <param-value>v2</param-value> </init-param> </servlet>
ServletContext初始化参数配置:
一个JavaWeb应用只创建一个ServletContext对象!
我们可以在N多个Servlet中来获取这个唯一的对象,使用它可以给多个Servlet传递数据!
ServletContext对象在Tomcat启动时就创建,在Tomcat关闭时才会死去!
获取ServletContext对象:(HttpServlet)
- 在**void init(ServletConfig config)**中:ServletContext context = config.getServletContext();
- ServletConfig类的getServletContext()方法可以用来获取ServletContext对象:ServletContext sc = this.getServletConfig().getServletContext();
初始化参数配置:
<context-param>
<param-name>config</param-name>
<param-value>springmvc-servlet.xml</param-value>
</context-param>
<context-param>
<param-name>p1</param-name>
<param-value>v1</param-value>
</context-param>
<context-param>
<param-name>p2</param-name>
<param-value>v2</param-value>
</context-param>
* servletContext.getInitParameter("p1"),返回v1
* servletContext.getInitParameter("p2"),返回v2
* servletContext.getInitParameterNames(),返回Enumeration<String>,包含p1和p2
服务器启动时,解析提取,放入ServletContext。 可以在其他Servlet或jsp中获取
注解 :
从Servlet3.0开始,支持注解
Servlet常用的几种注解:
● WebServlet:标识Servlet类
● WebFilter:标识Filter类
● WebListener:标识Listener类
● WebInitParam:标识初始化参数
● MulitpartConfig:标识上传附件的配置
@WebServlet属性列表:
属性名 | 类型 | 描述 |
---|---|---|
name | String | 指定Servlet 的 name 属性,等价于 。如果没有显式指定,则该 Servlet 的取值即为类的全限定名。 |
value | String[] | 该属性等价于 urlPatterns 属性。两个属性不能同时使用。 |
urlPatterns | String[] | 指定一组 Servlet 的 URL 匹配模式。等价于标签。 |
loadOnStartup | int | 指定 Servlet 的加载顺序,等价于 标签。 |
initParams | WebInitParam[] | 指定一组 Servlet 初始化参数,等价于标签。 |
asyncSupported | boolean | 声明 Servlet 是否支持异步操作模式,等价于 标签。 |
description | String | 该 Servlet 的描述信息,等价于 标签。 |
displayName | String | 该 Servlet 的显示名,通常配合工具使用,等价于 标签。 |
@WebServlet(name = "servlet1",
urlPatterns = {"/url1", "/url2","url3/*"},
loadOnStartup = 1,
initParams = {
@WebInitParam(name = "name", value="hotusm")
})
public class MyServlet extends HttpServlet {
private String name;
public MyServlet() {
System.out.println("load on startup");
}
@Override
public void init() throws ServletException {
super.init();
name= this.getInitParameter("name");
}
@Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
System.out.println(session);
System.out.println("name:"+name);
}
}
https://www.cnblogs.com/zr520/p/6095977.html