servlet是Server Applet的简称,翻译过来就是服务程序.好吧,这么说你可能仍是不太懂,简单的讲,这个servlet是运行在服务器上的一个小程序,用来处理服务器请求的.进一步讲,咱们知道,通常的网页程序,是由咱们经过浏览器访问来实现的,在这个过程当中,咱们的浏览器发送访问请求,服务器接收请求,并对浏览器的请求做出相应的处理.这就是咱们熟悉的B/S模型(浏览器-服务器模型).而servlet就是对请求做出处理的组件,运行于支持Java的应用服务器中.php
在servlet刚刚出现的那个年代,servlet的做用十分复杂,既承担着处理数据的做用,又承担着展现页面的做用,美工人员想要参与开发,基本上是不太现实的,毕竟美工不可能再去花时间将页面作好.
随着时间的推移,出现了MVC思想,也就是模型-界面-控制器思想,极大的简便了开发,也明确了servlet的做用.
根据上面这张图,咱们就能知道,servlet在其中承担的做用是controller,控制器,起到对数据进行操做的做用.
顺便补充说明一下,最经典的MVC模型就是JSP+JavaBean+Servlet开发的模式.html
我一直再讲,servlet是对数据进行处理的一个控制器,那么,你必定很好奇,servlet究竟处理的是什么数据?
这里你要知道,我以前在其余文章也讲过,咱们的web应用彻底是基于http协议的.http协议有请求报文(request)和响应报文(request),请求报文就是浏览器向服务器发送的数据造成的数据对象,同理,相应报文就是服务器向浏览器发送的数据造成的信息,而http协议有两个重要的方法,一个是POST,一个是GET,这两个方法就是向浏览器发送请求的方法.
你应该知道这两个方法在什么地方使用,没错,就是在前端的表单中使用,好比你登陆CSDN的时候,提交的用户名和密码,就是被http协议封装成请求报文的形式发送到服务器的,这样,servlet就可以读取请求报文的内容,并对报文进行处理了.前端
狭义上讲,servlet是servlet是java语言实现的一个类,因此咱们就要根据这个类进行相应的扩展开发.
开发流程以下:java
开发流程就是这个样子,咱们先来看一下最后一个步骤.web
你必定在想,若是我写了好几个servlet,可是前端发送请求的时候,究竟会把请求发送给哪一个servlet呢?我在输入某个地址的时候,到底是由哪一个servlet进行响应的呢?
这时候servlet的配置就显得尤其重要.对servlet的配置指定了对前端请求处理到底是经过哪一个servlet.
配置servlet一共有两种方式,一种是使用web.xml文件配置,另一种就是使用注解配置,下面咱们来详解介绍这两种配置方式小程序
<webapp>
<!-- 配置一个servlet -->
<!-- servlet的配置 -->
<servlet>
<!-- servlet的内部名称,自定义。尽可能有意义 -->
<servlet-name>MyServlet</servlet-name>
<!-- servlet的类全名: 包名+简单类名 -->
<servlet-class>cn.roobtyan.servlet.FirstServlet</servlet-class>
</servlet>
<!-- servlet的映射配置 -->
<servlet-mapping>
<!-- servlet的内部名称,必定要和上面的内部名称保持一致!! -->
<servlet-name>MyServlet</servlet-name>
<!-- servlet的映射路径(访问servlet的名称) -->
<url-pattern>/first</url-pattern>
</servlet-mapping>
</webapp>
当你访问/first的时候,服务器天然就会把请求交给MyServlet进行处理了.浏览器
新版本的servlet支持使用注解进行配置,这样极大的简便了开发.
注解配置以下:安全
@WebServlet(name = "LoginServlet",urlPatterns = {"/login"})
public class LoginServlet extends HttpServlet {
}
而后,你在访问/login的时候,服务器一样就会将处理交由LoginServlet进行处理了.
这样是否是很是爽?(^-^)
实际上,注解的做用和web.xml的做用是相同的,通常都是推荐使用注解的方式进行开发,这样十分简便,可读性也变的更增强大.
你必定会好奇,以下:ruby
<url-pattern>/first<url-pattern>
和服务器
@WebServlet(name = "LoginServlet",urlPatterns = {"/login"})
这里面的url可不能够不这么精确的配置,用一种模糊匹配的方式,就是我访问某种规则的路径的时候,统一调用一个servlet,这固然是能够的了.
这就涉及到映射路径的问题了
/* 任意路径都映射到这个servlet
/roobtyan/* /roobtyan下的任意路径映射到该servlet
*.(*.do *.action *.html) 是这样的:/任意路径.do/action/html
这里面有两点是须要注意的,一是url要么以/开头,要么以*开头,其余的都是非法的
通常来说,servlet只会初始化一次,也就是整个过程当中只存在一个servlet对象,即使是有屡次访问,依然只有一个对象,这个对象是能够复用的.我想你必定会好奇这个servlet到底是在何时建立的,因此就来说一下servlet的生命周期,所谓的生命周期咱们在java基础知识中必定也了解过,就是servlet类究竟在何时建立,调用了何种方法,最后在何时被销毁.咱们以前学过的对象都是本身手动建立,最后由JVM来销毁的,而servlet的整个生命周期,都是由tomacat,也就是服务器控制的
咱们以一张图来了解一下:
能够看到,servlet共有三个关键的方法,分别是init(),service(),destroy().
好了,讲了这么多,你必定是跃跃欲试了,咱们就用一个登陆控制的例子来简单的看一下servlet开发的步骤.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>roobtyan登陆控制系统</title>
</head>
<body>
<h1 align="center" style="color: red;">欢迎您登陆系统后台</h1><hr/>
<%--the form start--%>
<div align="center">
<form method="post" action="/login">
Username:<input type="text" name="username"/><br/><br/>
Password:<input type="password" name="password"/><br/><br/>
<input type="submit" value="登陆"/>
</form>
</div>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>欢迎页面</title>
</head>
<body>
<h1 align="center" style="color: red">Welcome:</h1>
<% out.println(session.getAttribute("user")); %>
<hr/>
<span style="align:center; color:yellow">
Time:<% out.println(new Date()); %>
</span>
</body>
</html>
public class LoginServlet extends HttpServlet {
public void service(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
//设置字符编码
request.setCharacterEncoding("utf8");
//从request对象中获取username,password
String username = request.getParameter("username");
String password = request.getParameter("password");
//判断是否为管理员
if("administrator".equals(username)&&"123456".equals(password)){
//登陆成功,设置session
HttpSession session = request.getSession(true);
session.setAttribute("user", "管理员,欢迎你!");
}else {
session.setAttribute("user","登陆信息错误,请检查用户名或密码");
}
//将页面转发到欢迎页面
requestDispatcher = request.getRequestDispatcher("/welcome.jsp");
requestDispatcher.forward(request,response);
}
}
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.roobtyan.cn.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
这样,咱们的第一个servlet程序就作完了.我想若是你存在疑问的话,应该是在jsp技术上,若是是这样,那么请参照个人博客:Jsp技术介绍
还有一个地方你可能存在疑惑,为何使用request.getParameter方法能够获取到提交的表单中的内容呢?这个很好解释,由于前端使用post或者get方法将表单信息提交到servlet的时候,将表单信息封装成了request对象,这样就能够获取到了.值得注意的是,表单中的name字段,就是咱们获取值的根据.
最后一个可能存在疑问位置就是这里
//将页面转发到欢迎页面
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/welcome.jsp");
requestDispatcher.forward(request,response);
这段代码我在最后会解释,其实也挺简单的
上面的你都注意到了,那你很是厉害了.不过,有一个地方你可能注意不到,那就是这段代码:
request.setCharacterEncoding("utf8");
设置字符编码的这部分,若是不设置,会形成乱码,这仍是须要注意的.关于POST和GET乱码的解决,请看个人文章:POST和GET乱码的解决
前面咱们说了,servlet只有在第一次被访问的时候才会加载,这确定会形成第一个访问的人访问时间较长,由于他须要等待servlet完成加载.那么,有没有什么方法可以使得servlet自动加载呢,就是在启动服务器的时候就将servlet加载起来呢?
答案是有的,一样能够在web.xml中进行配置
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>cn.roobtyan.LoginServlet</servlet-class>
<!-- 让servlet对象自动加载 -->
<load-on-startup>1</load-on-startup>
</servlet>
就是使用的<login-on-startup></login-on-startup>
配置的,注意: 其中的整数值越大,建立优先级越低!
前面咱们讲了,一个servlet在服务器中只会存在一个实例,不管是有多少访问,都掉用的同一个实例,也就是单实例多线程的.这就存在着必定的线程安全问题,好比说,我在servlet中定义了一个局部变量,那么这个变量的值颇有可能不是我期待的值,因此,在servlet中要尽可能避免使用局部变量.
在servlet中共有四个重要的对象:
HttpServletRequest 请求对象:获取请求信息 HttpServletResponse 响应对象: 设置响应对象 ServletConfig对象 servlet配置对象 ServletContext对象 servlet的上下文对象
前两个咱们介绍的很多,这两个的具体内容我回单独拿出来一章介绍,和HTTP协议一块介绍,我以为这样看起来更能接受一些.
那么咱们如今就介绍后面两个
ServletConfig config = this.getServletConfig();
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>cn.roobtyan.LoginServlet</servlet-class>
<!-- 初始参数: 这些参数会在加载web应用的时候,封装到ServletConfig对象中 -->
<init-param>
<param-name>location</param-name>
<param-value>doom</param-value>
</init-param>
</servlet>
配置文件中的init-param
就是配置信息
这个ServletConfig对象共有以下的方法
java.lang.String getInitParameter(java.lang.String name) 根据参数名获取参数值
java.util.Enumeration getInitParameterNames() 获取全部参数
ServletContext getServletContext() 获得servlet上下文对象
java.lang.String getServletName() 获得servlet的名称
这个对象比较简单,就不过多介绍,注意,这个对象只能在本身的servlet中使用,超出了范围就不行了.
java.lang.String getContextPath() --获得当前web应用的路径
java.lang.String getInitParameter(java.lang.String name) --获得web应用的初始化参数
java.util.Enumeration getInitParameterNames()
void setAttribute(java.lang.String name, java.lang.Object object) --域对象有关的方法
java.lang.Object getAttribute(java.lang.String name)
void removeAttribute(java.lang.String name)
RequestDispatcher getRequestDispatcher(java.lang.String path) --转发(相似于重定向)
java.lang.String getRealPath(java.lang.String path) --获得web应用的资源文件
java.io.InputStream getResourceAsStream(java.lang.String path)
具体的方法使用就是这样,按照API去用就能够了,我就再也不过多介绍
刚才咱们用到的
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/welcome.jsp");
requestDispatcher.forward(request,response);
这个就是转发,按照这样用就能够了
与转发功能类似的是重定向,重定向的使用是这样的:
response.sendRedirect("/welcome.jsp");
这样也会访问到welcome.jsp这个页面.
这就是以前的Respose对象,我们先这样用着,后面我回单独写一章博客来说解的.
虽然两者最终实现的功能是相同的.可是仍是有很大不一样的.不一样之处以下
因此,若是想要在多个页面使用相同的request对象,那么只能使用转发,而不能使用重定向.
好了,以上就是所有要介绍的内容.servlet的生命周期是十分重要的,其余的只能靠动手实践才能很好的掌握,本身动动手敲出一个个好玩的例子吧!
感谢您的阅读,欢迎指正博客中存在的问题,也能够跟我联系,一块儿进步,一块儿交流!
微信公众号:进击的程序狗
邮箱:roobtyan@outlook.com
我的博客:http://roobtyan.cn
扫描下面的二维码关注我吧,你将收获到意想不到的东西哟……
给你们准备了一份很是棒的JAVA的视频教程,从JAVA基础一直到JAVAWEB,还有很是强大的项目实战。
就在个人微信公众号里,回复java就可查看,免费的呦!