1、什么是Servlet
servlet其实就是java里面一种java类,只不过这种java类有一些特殊的作用,所以我们就叫它servlet.
浏览器地址栏输入地址或者是点击超链接或者是点击表单的提交按钮等操作,
向服务器发送一个请求,这个请求的目的是要调用服务器中web项目里面的一个指定类
的对象(servlet对象)中的指定方法(service方法)(同时还可以把页面上的相关参数
传过来)
如果说随便一个类的对象中的方法都可以这么来调用的话,那么后台的代码程序就会
很混乱,因为随便一个访问地址url就能访问到一个方法
所有在j2ee平台中,规定了只有一种类的对象可以被这么来访问,就是servlet
2、servlet的作用
可以让浏览器直接通过一个地址(URL)去访问。(一般的java类是做不到这一点的)
3、怎么写一个类,能成为一个servlet
1. 三种方式
a.实现一个接口:javax.servlet.Servlet
找一个抽象类 继承Servlet重写里面的部分方法
b.继承一个抽象类:javax.servlet.GenericServlet
发现功能 还是不好用--->又找一个抽象类-->HttpServlet
c.继承一个抽象类:javax.servlet.http.HttpServlet
这种是之后一直要用的方法(常用)
2. 解释
Servlet接口中,有五个抽象方法,其实最重要的一个方法是:
service(ServletRequestreq,ServletResponse res)
destroy()方法将在该Servlet停止服务时被servlet的容器调用
getServletConfig()返回一个包含了该Servlet的初始化和启动了的参数的ServletConfig 对象
getServletInfo()方法返回这个Servlet对象的信息例如作者,版本和版权
init(ServletConfig config)被Servlet容器调用,用来指示该Servlet正在提供服务
service(ServletRequest req, ServletResponse res)被Servlet容器调用,让该Servlet可以接收请求和响应请求
抽象类GenericServlet实现了接口Servlet,
但是留了一个抽象方法没有实现,就是上面所提到的service方法,除此之外,GenericServlet里面还增加了一些新的方法.
抽象类HttpServlet,继承了GenericServlet,但是HttpServlet中没有任何抽象方法,
除了从父类继承过来的方法之外,里面还有很多新的方法:doXxx方法,另外需要注意的是,HttpServlet里面有俩个service方法,但是俩个方法的参数类型不同.
i.Servlet接口中的service方法.
因为无论我们使用哪一种方式去写出来的一个servlet类的中,一定会有一个方法叫做service,这个方法是Servlet接口中的定义的,tomcat服务器接收到客户端请求后,帮我们调用servlet中的方法的时候,它只会调用这一个service方法.注意这个service方法中参数的类型:service(ServletRequestreq,ServletResponse res)。
ii.GenericServlet中的俩个init方法
带参数的init(ServletConfig config)方法是从Servlet接口中实现的,还有一个是这个类直接定义的,无参的init()方法.tomcat服务器创建servlet对象的时候,会帮我们去调用init(ServletConfig config)进行servlet类中的初始化工作,所以如果我们想在servlet类中初始化自己的一些相关数据的话,需要去重写这个init方法。有参数的init方法中调用了无参的init方法,所以将来我们只需要重写这个无参的init方法就可以了。这样我们就不需要再专门对这个init(ServletConfig config)方法中的参数进行处理了。
iii.HttpServlet中的俩个service方法
这个是从Servlet接口中实现的方法.
“`
service(ServletRequest req, ServletResponse res){
//强转参数类型
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
//调用新定义的service方法
service(request,response);
}
HttpServlet中新定义的方法
service(HttpServletRequest req, HttpServletResponse resp){
//拿到当前请求的类型 get/post
String method = req.getMethod();
//判断请求的方法 然后去调用doXxx方法
if(method.equals("GET")){
doGet(req,resp);
}
if(method.equals("POST")){
doPost(req,resp);
}
...
..
}
iiii.Servlet的细节
(1)一个<servlet>可以对应多个<serlvet-mapping>,从而一个Servlet可以有多个路径来访问.
(2)url-partten中的路径可以使用*匹配符号进行配置,但是要注意,只能是/开头/ * 结尾或*.后缀这两种方式 ~由于*的引入,有可能一个路径被多个urlpartten匹配, 这是优先级判断条件如下:
哪个最像找哪个 *.后缀永远匹配级最低
(3)缺省Servlet:如果有一个Servlet的url-partten被配置为了一根正斜杠,这个Servlet就变成了缺省Serlvet.其他Servlet 都不处理的请求的时候, 就由缺省Servlet来处理.其实对于静态资源的访问就是由缺省Servlet来执行 设置404页面500页面等提示页面也是由缺省Servlet来执行
通常我们不会自己去配置缺省Servlet
http://ip:port/项目名字/资源路径
例如:
http://127.0.0.1:8002/web_test/servlet1
4.servlet的生命周期 servlet的对象是单例:在web项目整个运行期间
每一个servlet类只会有一个对象存在.默认情况下,这一个对象是在servlet第一次
被访问的时候才会创建的,而且之后不管再访问多少次这个servlet, 也不会再去创建它的的对象的.(我们可以设置某一个servlet的对象在服务器启动的时候就被创建出来)
这些操作(方法的调用)都是由服务器来做的:
1.默认情况下,第一次被访问的时候tomcat创建servlet对象(调用无参构造器)
2.在调用完构造器创建对象后,tomcat还会调用init(ServletConfig config)方法,对servlet对象进行初始化,所以我们可以重写init方法来进行对象的初始化。
3.客户端第一次访问的时候,在tomcat创建servlet对象之后,tomcat接着会调用 service(ServletRequest req,ServletResponse res)方法,在方法中可以接收客户端传过来 的参数以及给客户端写回去相应的数据或者页面.
4.从这之后,客户端再这个servlet,那么tomcat就会直接调用servlet对象中的service方法
5.在销毁servlet对象的时候会tomcat调用destroy()方法.
通过web.xml文件中设置,可以让servlet的对象是在服务器启动的时候被创建出来. web.xml:
<servlet>
<servlet-name>LifeServletTest</servlet-name>
<servlet-class>cn.yulangde.servlet.LifeServletTest</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
加入<load-on-startup>标签,表示这个servlet需要在启动服务器的时候就被创建对象.其中,标签可以要放一个数字,这个数字的大 小就决定了多个servlet对象被创建的顺序,数字越小越先创建.(如果我们配置了多个servlet在启动服务器的时候被创建对象的话)
5.servlet的线程安全问题
问题产生的原因:
1.servlet是单例,一个servlet类只有一个对象在项目运行期间。
2.web项目项目本身就有多线程的特点,虽然我们在代码中没有写和线程相关的东西,但是这个多线程的特点是由服务器给我们提供出来的,一个客户端发送了一 个请求,服务器接收到请求后就会建一个线程去处理这个请求。所以就有可能出现这样的情况:俩个线程同时去访问同一个servlet对象.
如何解决/防止
1.加锁synchronized 如果一定要用成员变量则用锁来防止线程安全问题,但是要注意锁住内容应该是造成线程安全问题的核心代码,尽量的少锁主内容,减少等待时间提高servlet的响应速度
2.尽量少的定义成员变量 因为只有成员变量才会产生线程安全的问题(在多个线程访问同一个对象的时 候),方法中的局部变量是没有这样的问题的.
3.其他(实现一些安全性的接口)
6.客户端向服务器发请求并且传参(get/post) 客户端向服务器发送请求可以是get方式也可以是post方式.所以传参也分为get方式下传参和post方式下传参
1.哪些方式的请求属于get/post方式
get方式:
a.浏览器中输入地址(URL)然后回车
b.超链接 <a href="param?name=haha&age=20"></a>
c.页面中引入的css样式文件
d.页面中引入的js的文件(javascript)
e.<img src="image/a.jpg" />
f.form表单中method="get"
g.ajax中可以设置异步提交请求的方式为get
post方式:
a.form表单中method="post"
b.ajax中可以设置异步提交请求的方式为post
2.get和post的特点及其区别 它们各自的特点及其区别主要是体现在所传递的参数上面。
a.get方式参数 参数是直接放在要请求url后面的 例如: url?参数名=参数值&参数名=参数值 要请求的url为:http://ip:port/WebTest/firstServlet 传参: .../firstServlet?name=tom.../firstServlet?name=tom&age=20
这种方式传参的特点:
1.参数直接放在url后面
2.从浏览器的地址栏里面可以直接看到所传的参数
3.参数的长度有限制,不能把一个很长的数据通过get方式传参.(与浏览器种类有关)
b.post方式传参 参数是放在请求的体部的。 (浏览器发送的请求可以大致的分为请求头+请求体)
这种方式传参的特点:
1.参数放在请求的体部而不是url后面.
2.浏览器的地址栏中看不到所传的参数.
3.因为参数不用出现在地址栏里面,所有参数长度是没有限制的.
7.servlet中接收客户端传过来的参数。
客户端都是以这样的形式传参的: 参数名字=参数值
所有在servlet中我们需要用参数名字来拿到参数值:
1,String value = request.getParameter("key");
其中key就是参数名字,value是参数值,不管传的值本身是什么类型,servlet中接收到以后只能是字符串类型或者字符串类型数组.
2,如果客户端用的多选框,这个时候传过来的参数就要用一个字符串类型数组来接收:String[] like = req.getParameterValues("like");
3,在表单中
参数值就是用户所填写的内容或者是所选的选项的value属性值
参数名字就是每一个input或者其他输入元素中的name属性的值.
例如:
<input type="text" name="username" value="这个是参数的值">
参数名字就是name属性的值:username
参数的值就是将来用户所填内容.
4,在servlet中,不管是get方式提交的时候还是post方式提交的时候,来到servlet里面以后,都是用相同的方式来取得数据。
request.getParameter("key"); request.getParameterValues("key");