![](https://i-blog.csdnimg.cn/blog_migrate/19bdb4cf9579b5e3dc1f7af6f5412108.png)
![](https://i-blog.csdnimg.cn/blog_migrate/37950b75a7b018c9dd0a84b185c7fa84.png)
![](https://i-blog.csdnimg.cn/blog_migrate/84584112d146e4587bac8da256fbc910.png)
![](https://i-blog.csdnimg.cn/blog_migrate/76c4c65ba1551c7d23874e6a3ff2a308.png)
![](https://i-blog.csdnimg.cn/blog_migrate/5650c527fcb8027e31b7a649fe67a0f9.png)
![](https://i-blog.csdnimg.cn/blog_migrate/450cc147b5997ad4e43841c6d4d62391.png)
![](https://i-blog.csdnimg.cn/blog_migrate/dec4440cbb2e7d6f9a0d74daaa02352c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/daab8ffd425b0823efd24734b341053e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2c65ec0d81b2e222a0180f2f5355bdfd.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9698a0d7ea379b23c85c5d43cf8c6192.png)
![](https://i-blog.csdnimg.cn/blog_migrate/076c4423cb69a72632889434c047b310.png)
Servlet 是在服务器上运行的小程序。这个词是在 Java applet的环境中创造的,Java applet 是一种当作单独文件跟网页一起发送的小程序,它通常用于在客户端运行,结果得到为用户进行运算或者根据用户互作用定位图形等服务。
服务器上需要一些程序,常常是根据用户输入访问数据库的程序。这些通常是使用公共网关接口(Common Gateway Interface,CGI)应用程序完成的。然而,在服务器上运行 Java,这种程序可使用 Java 编程语言实现。在通信量大的服务器上,JavaServlet 的优点在于它们的执行速度更快于 CGI 程序。各个用户请求被激活成单个程序中的一个线程,而无需创建单独的进程,这意味着服务器端处理请求的系统开销将明显降低。
实现过程
最早支持 Servlet 技术的是 JavaSoft 的 Java Web Server。此后,一些其它的基于 Java 的 Web Server 开始支持标准的 Servlet API。Servlet 的主要功能在于交互式地浏览和修改数据,生成动态 Web 内容。这个过程为:
客户端发送请求至服务器端;
服务器将请求信息发送至 Servlet;
Servlet 生成响应内容并将其传给服务器。响应内容动态生成,通常取决于客户端的请求;
服务器将响应返回给客户端。
Servlet 看起来像是通常的 Java 程序。Servlet 导入特定的属于 Java Servlet API 的包。因为是对象字节码,可动态地从网络加载,可以说 Servlet 对 Server 就如同 Applet对 Client 一样,但是,由于 Servlet 运行于 Server 中,它们并不需要一个图形用户界面。从这个角度讲,Servlet 也被称为 FacelessObject。
一个 Servlet 就是 Java 编程语言中的一个类,它被用来扩展服务器的性能,服务器上驻留着可以通过“请求-响应”编程模型来访问的应用程序。虽然 Servlet 可以对任何类型的请求产生响应,但通常只用来扩展 Web 服务器的应用程序。Servlet根据请求,动态的去生成要返回的html,并不是早就准备好的html文档。
![](https://i-blog.csdnimg.cn/blog_migrate/3edc5c80563746c08eae77f8d6f39d83.png)
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
诀窍是,当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器
![](https://i-blog.csdnimg.cn/blog_migrate/44698667f3495797b37e5256422375aa.png)
这里注意两个问题:
tomcat启动乱码问题
![](https://i-blog.csdnimg.cn/blog_migrate/ee88c6ba59577f24bc04b6963f017c22.png)
tomcat的启动成功的判断方法
![](https://i-blog.csdnimg.cn/blog_migrate/33b4190f266c48e03a57c660b0b03380.png)
修改端口和调整乱码问题
定位到服务配置文件中
![](https://i-blog.csdnimg.cn/blog_migrate/e63569c60778264b816842cf1656aff3.png)
定位到日志文件中
![](https://i-blog.csdnimg.cn/blog_migrate/3de9ec748b1aa494fff50f6cc2b9a05c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/62c0e4d5a63e3d8ac3883894b9e5269c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/30e833369caeb27d932f8d0adce07660.png)
过程简述:
1.首先从浏览器输入网址发出请求,请求发送到tomcat
2.tomcat根据映射假名匹配,匹配到后找到真名
3.根据真名再匹配servlet的具体路径
4.找到后Servlet处理请求,并且返回响应到浏览器
5.浏览器加载响应。
![](https://i-blog.csdnimg.cn/blog_migrate/d1ba58212876f5b21dfc2dad0bcb2abb.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2f79eb16f38cb2a66942ba37516af235.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9bc7c62de8a7e20e08bac341cb7d7eee.png)
放在webapp目录中的WEB-INF中的sub文件不能随便被外部访问,里面放html,是访问不到的。
![](https://i-blog.csdnimg.cn/blog_migrate/a5eceb6642dda80da79427cd2164b72f.png)
这样就可以访问了,一般推荐采用绝对路径,不采用相对路径。
![](https://i-blog.csdnimg.cn/blog_migrate/69492105124dd7c8bba60b5116b76058.png)
![](https://i-blog.csdnimg.cn/blog_migrate/4cc1d9675c1feb7ace69851c0ee8cf50.png)
![](https://i-blog.csdnimg.cn/blog_migrate/39a3e1066c4a1aafa0d58ef571b36f1c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b0cc60b358c8ab97b05e2d090883dd90.png)
注意上下文问题:就是servlet的映射的根路径的控制www.localhost:8080/xxxxx/url-pattern
一般都设置为忽略不常用。
![](https://i-blog.csdnimg.cn/blog_migrate/88d5e91ffb96fb13a84052c422a628fd.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8382defa740e0e5d02371cc3f7004fbb.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c9fcf19a58aa91899711ca037f87ceb5.png)
String[] specs = request.getParameterValues("spec");
PrintWriter out=response.getWriter();
for(String spec:specs){
out.println("<h2>spec:"+spec+"</h2>");
}
![](https://i-blog.csdnimg.cn/blog_migrate/e66c802e260beeea9cfff3086cca4a10.png)
![](https://i-blog.csdnimg.cn/blog_migrate/4f573f082a67c1a0a9cae2a3ced303cb.png)
![](https://i-blog.csdnimg.cn/blog_migrate/81520fa714899d1606f7bd37f878c72e.png)
以下是两种请求的处理方式。
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String mobile = req.getParameter("mobile");
PrintWriter out = resp.getWriter();
out.println("GET");
out.println("<h1>"+name+"</h1>");
out.println("<h1>"+mobile+"</h1>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String mobile = req.getParameter("mobile");
PrintWriter out = resp.getWriter();
out.println("POST");
out.println("<h1>"+name+"</h1>");
out.println("<h1>"+mobile+"</h1>");
}
![](https://i-blog.csdnimg.cn/blog_migrate/5de61d8cdd1ec6f08e52534a30f3a025.png)
public class FirstServlet extends HttpServlet {
//第一阶段装载,读取xml文件,加载配置信息,并未创建
//第一次访问(地址栏输入)的时候才会创建servlet实体对象
public FirstServlet() {
System.out.println("正在创建...");
}
//创建之后初始化
@Override
public void init() throws ServletException {
System.out.println("正在初始化");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("正在处理。。");
}
//在tomcat关闭前会自动的关闭销毁
@Override
public void destroy() {
System.out.println("正在销毁");
}
// 注意全局有且仅有一个servlet对象实例,有多个请求时,单例多线程。
}
![](https://i-blog.csdnimg.cn/blog_migrate/2a0d4145bb0a65de4545f736782b6a51.png)
在类上注解写上不用配置web.xml了
@WebServlet("/anno")
public class AnnotationServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("im annotation servlet!");
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/f1c38ac671388e7705afd79184f81322.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b60f4eb227c9a7656d49e9b7565558d7.png)
Uniform Resource Locator
Uniform Resource Identifier
![](https://i-blog.csdnimg.cn/blog_migrate/59557a000d5d5341cacb2e2fe348542a.png)
HTTP 协议的 Header 是一块数据区域,分为请求头和响应头两种类型,客户端向服务区发送请求时带的是请求头,而服务器响应客户端数据时带的是响应头。
请求头里主要是客户端的一些基础信息,UA(user-agent)就是其中的一部分,而响应头里是响应数据的一些信息,以及服务器要求客户端如何处理这些响应数据的指令。请求头里面的关键信息如下:
1) accept
表示当前浏览器可以接受的文件类型,假设这里有 image/webp,表示当前浏览器可以支持 webp 格式的图片,那么当服务器给当前浏览器下发 webp 的图片时,可以更省流量。
2) accept-encoding
表示当前浏览器可以接受的数据编码,如果服务器吐出的数据不是浏览器可接受的编码,就会产生乱码。
3) accept-language
表示当前使用的浏览语言。
4) Cookie
很多和用户相关的信息都存在 Cookie 里,用户在向服务器发送请求数据时会带上。例如,用户在一个网站上登录了一次之后,下次访问时就不用再登录了,就是因为登录成功的 token 放在了 Cookie 中,而且随着每次请求发送给服务器,服务器就知道当前用户已登录。
5) user-agent
表示浏览器的版本信息。当服务器收到浏览器的这个请求后,会经过一系列处理,返回一个数据包给浏览器,而响应头里就会描述这个数据包的基本信息。
响应头里的关键信息有:
1) content-encoding
表示返回内容的压缩编码类型,如“Content-Encoding :gzip”表示这次回包是以 gzip 格式压缩编码的,这种压缩格式可以减少流量的消耗。
2) content-length
表示这次回包的数据大小,如果数据大小不匹配,要当作异常处理。
3) content-type
表示数据的格式,它是一个 HTML 页面,同时页面的编码格式是 UTF-8,按照这些信息,可以正常地解析出内容。content-type 为不同的值时,浏览器会做不同的操作,如果 content-type 是 application/octet-stream,表示数据是一个二进制流,此时浏览器会走下载文件的逻辑,而不是打开一个页面。
4) set-cookie
服务器通知浏览器设置一个 Cookie;通过 HTTP 的 Header,可以识别出用户的一些详细信息,方便做更定制化的需求,如果大家想探索自己发出的请求中头里面有些什么,可以这样做:打开 Chrome 浏览器并按“F12”键,唤起 Chrome 开发者工具,选择 network 这个 Tab,浏览器发出的每个请求的详情都会在这里显示。
![](https://i-blog.csdnimg.cn/blog_migrate/9a10c3ad4581cb9806c2187f35bd9764.png)
根据请求头进行判断是哪一种设备,就返回哪种设备的页面。
![](https://i-blog.csdnimg.cn/blog_migrate/d932d3354a0bbb881bfa7cfcdc587b8a.png)
通过请求头判断处理方式,这里有一句话要注意,设置编码方式,否则中文字符串会乱码?号。
@WebServlet("/ua")
public class UserAgentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String ua = req.getHeader("User-Agent");
String output = "";
if(ua.toLowerCase().indexOf("window nt")!=-1){
output = "<h1>这是PC页面</h1>";
}else {
output = "<h1>这是移动端页面";
}
resp.setContentType("text/html;charset=utf-8");
PrintWriter out=resp.getWriter();
out.println(output);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/d30194d18cbb4cb5ef15c95af2b424fb.png)
![](https://i-blog.csdnimg.cn/blog_migrate/39ce3a6f92c1f946ec79f204f2b77a9c.png)
401代表没有登陆,403代表没有权限
![](https://i-blog.csdnimg.cn/blog_migrate/dd865cecc359d22af9b7d481818a7314.png)
@WebServlet("/ua")
public class UserAgentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String ua = req.getHeader("User-Agents");
String output = "";
if(ua==null){
resp.getWriter().println("请求头不存在");
return;
}
if(ua.toLowerCase().indexOf("window nt")!=-1){
output = "<h1>这是PC页面</h1>";
}else {
output = "<h1>这是移动端页面";
}
resp.setContentType("text/html;charset=utf-8");
PrintWriter out=resp.getWriter();
out.println(output);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/b398af052fe50cbaef6b5dc53b77d0ca.png)
@WebServlet("/ct")
public class ContentTypeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String output = "<h1><a href='http://www.baidu.com'><span>百度</span>";
response.setContentType("aplication/x-msdownload;charset=utf-8");
response.getWriter().println(output);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/28704b0a25a32067dfd412ae7ba942ad.png)
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("我是主页");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
@WebServlet("/login")
public class CheckLoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
if(username.equals("admin")&&password.equals("123456")){
System.out.println("登录成功");
//请求转发
//request.getRequestDispatcher("/index").forward(request,response);
//响应重定向
response.sendRedirect("/index");
}else {
System.out.println("用户登录失败");
}
}
}
<body>
<form action="/login" method="post">
<input name="username">
<input name="password" type="password">
<input type="submit">
</form>
</body>
方式一请求转发的形式
![](https://i-blog.csdnimg.cn/blog_migrate/e18db05e97e773f078333e5a7fe1b43e.png)
方式二响应重定向的方式
![](https://i-blog.csdnimg.cn/blog_migrate/40eacaa83a6c296b46beac2dee7c0290.png)
![](https://i-blog.csdnimg.cn/blog_migrate/5932b997e028db9e1c3c72aef47644da.png)
![](https://i-blog.csdnimg.cn/blog_migrate/479d2118e648de66aefa761e9f5ce75d.png)
两者的区别:
请求转发:一个是一次即可请求完成,紧密相关,因为由一个tomcat管理,只能在应用的内部进行转发
响应重定向:不是紧密相连的对象,默认get方式,因为两次响应,可以跳到其他服务器管理站点如百度
![](https://i-blog.csdnimg.cn/blog_migrate/11545aced4e969b62699c2e25c6f1dc6.png)
登录后主页面显示账号名称实例:
@WebServlet("/login")
public class CheckLoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
if(username.equals("admin")&&password.equals("123456")){
System.out.println("登录成功");
request.setAttribute("username",username);
request.setAttribute("password",password);
// 请求转发,总体一个请求,可以设置和获取属性
request.getRequestDispatcher("/index").forward(request,response);
// //响应重定向,一共两个请求,会出现Null的情况
// response.sendRedirect("/index");
}else {
System.out.println("用户登录失败");
}
}
}
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String username = (String)request.getAttribute("username");
response.getWriter().println("我是主页"+username);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
Cookie
![](https://i-blog.csdnimg.cn/blog_migrate/bb31dc36b431adad4932f6015bc1ed52.png)
![](https://i-blog.csdnimg.cn/blog_migrate/515b603aca284d50b3f9a40d0d74216c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/aae523c65543d1c274b50bf2d23ed5b6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e22efe4ae1295c54e9db120faa59399f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/43b9287f8671b14157d54cd5f722d9a9.png)
@WebServlet("/cookie/random")
public class RandomServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Integer random = new Random().nextInt(10000);
Cookie cookie = new Cookie("random" , String.valueOf(random));
cookie.setMaxAge(60*60*24);
response.addCookie(cookie);
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("<h2>随机数" + random+ "已生成</h2>");
}
}
@WebServlet("/cookie/show")
public class CookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
Integer random=-1;
if(cookies==null){
response.getWriter().println("无cookie");
return;
}
for(Cookie c:cookies){
if (c.getName().equals("random")) {
random=Integer.parseInt(c.getValue());
}
}
response.setContentType("text/html;charset=utf-8");
response.getWriter().println(random);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6fd98858b9b77e43a064ce0c19b8d84f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9bc401fbc839d8a3e50e5a24f2294d1a.png)
为什么说session是和浏览器窗口绑定的?
因为当我把窗口关闭,cookie默认消除,此时向tomcat发送请求的时候,因为cookie没了,所以此时会创建一个新的session,原来的30min会自动销掉。
public class CheckLoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
if(username.equals("admin")&&password.equals("123456")){
System.out.println("登录成功");
//为请求开辟一片内存空间,并设置属性及值,设置同时设置cookie的sessionid
HttpSession session = request.getSession();
session.setAttribute("username",username);
//响应设置好cookie的sessionid,响应重定向到index
response.sendRedirect("/index");
}else {
System.out.println("用户登录失败");
}
}
}
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
//根据cookie来查找session空间,并获取属性
HttpSession session = request.getSession();
String username=(String) session.getAttribute("username");
response.getWriter().println("我是主页"+username);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/2ddd601484e18696f27517c05c3c44fe.png)
@WebServlet("/servletcontext/init")
public class ServletContextInitServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
servletContext.setAttribute("copyright","xxxx");
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().println("ServletContext已初始化");
}
}
@WebServlet("/servletcontext/indx")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
ServletContext context = req.getServletContext();
String copyright = (String)context.getAttribute("copyright");
resp.getWriter().println(copyright);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/cb847f5f8cc8bec0da50639ada31b954.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3a7e1cf81c7340d879404dc50194af6b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/4e40bb2526e93001b7091c48d2da685e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/389a9e8ca3a02af8c84a157cc2a870f5.png)