1.简单servlet程序示例
1)创建一个servlet,重写service()方法,会自动调用doGet()方法或者doPost()方法
package
com.huawei.servlet
import javax
.servlet.ServletException
import javax
.servlet.ServletRequest
import javax
.servlet.ServletResponse
import javax
.servlet.annotation.WebServlet
import javax
.servlet.http.HttpServlet
import javax
.servlet.http.HttpServletRequest
import javax
.servlet.http.HttpServletResponse
import java
.io.IOException
import java
.io.PrintWriter
public class HelloServlet extends HttpServlet {
@Override
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
res
.setContentType(
"text/html;charset=utf-8")
req
.setCharacterEncoding(
"utf-8")
String name = req
.getParameter(
"name")
PrintWriter
out = res
.getWriter()
out.println(
"<span style='color:red;font-size:30px;'>你好 "+name+
"</span>")
}
}
2)配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>helloServlet
</servlet-name>
<servlet-class>com.huawei.servlet.HelloServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet
</servlet-name>
<url-pattern>/test
</url-pattern>
</servlet-mapping>
</web-app>
3)注解方式实现上面的内容——免于web.xml中servlet配置
package com.huawei.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(name =
"helloServlet", urlPatterns =
"/test2")
public class HelloServlet extends HttpServlet {
@Override
public void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType(
"text/html;charset=utf-8");
req.setCharacterEncoding(
"utf-8");
String name = req.getParameter(
"name");
PrintWriter out = res.getWriter();
out.println(
"<span style='color:red;font-size:30px;'>你好 "+name+
"</span>");
}
}
4)IntelliJ IDEA 2017部署普通web项目(非maven)
3)启动Tomcat
5)@WebServlet注解
@WebServlet(name =
"helloServlet",
urlPatterns =
"/test2",
loadOnStartup =
1)
public class HelloServlet extends HttpServlet {
}
如果希望应用程序启动时,就先将Servlet类载入、实例化并做好初始化动作,则可以使用loadOnStartup设置。设置大于0的值(默认值为-1),表示启动应用程序后就要初始化Servlet(而不是实例化几个Servlet)。数字代表了Servlet的初始顺序,容器必须保证有较小数字的Servlet先初始化,在使用标注的情况下,如果有多个Servlet在设置loadOnStartup时使用了相同的数字,则容器实现厂商可以自行决定要如何载入哪个Servlet。
2.servlet执行流程
按上述方法启动服务器在浏览器输入http://localhost:8080/start/test?name=亚索根据ip:端口号与服务器建立连接根据应用名(idea可以自己随便写,如start,eclipse则只能是工程名)去服务器上查找对应的应用(HelloJavaEE),每一个应用都有一个web.xml文件根据/test去web.xml文件中查找对应的url-pattern, 找到之后,根据servlet-name查找到对应的HelloServlet调用HelloServlet的service方法处理数据
3.servlet映射路径
Servlet的映射路径由<servlet-mapping>中的<url-pattern>(注意<url-pattern>要么要以/开头,要么要以*开头)决定,那么<url-pattern>究竟怎么写,怎么去匹配呢?有两种匹配方案:
精确匹配 <url-pattern>/test/login</url-pattern> 精确匹配的要点是:<url-pattern>以/开始,并且必须将<url-pattern>中的内容精确的写上。在精确匹配时要注意坚决不能漏掉/,否则会报错,一定要带有/模糊匹配,下面三种方式,但是在一个url-pattern中不能组合下面的模糊匹配方式
<url-pattern>/*</url-pattern><url-pattern>/test/*</url-pattern><url-pattern>*.do</url-pattern>
注意模糊匹配不能组合起来用,只能单个使用如果在浏览器中输入的url有多个Servlet同时被匹配,也就是说模糊匹配和精确匹配都能找到对应的Servlet资源,精确匹配的优先级高(长得最像的优先被匹配),但是要尽量避免这种情况的发生。
当以后缀名结尾的模糊匹配,优先级最低。
4.servlet运行原理
1)建立连接 浏览器根据ip地址及端口号与服务器建立连接 2)打包 浏览器根据http协议将数据打包 数据包中包含请求资源路径(/start/test) 3)发送请求 浏览器向服务器发送请求 4)拆包 服务器根据http协议拆包,获取浏览器发送过来的请求数据 5)创建Request 可以通过请求对象获取请求数据 6)创建Response 可以通过响应对象获取输出流,向页面输出数据 7)创建HelloServlet 服务器通过反射实例化HelloServlet 8)调用service方法 在service方法中处理数据 9)服务器端的通讯模块将数据打包 10)服务器向浏览器发送响应 11)浏览器拆包,获取服务器响应回来的数据 12)浏览器生成新的页面,响应给用户
5.servlet映射练习
Servlet1 映射到/abc/*Servlet2 映射到/*Servlet3 映射到/abcServlet4 映射到*.do
Question: ①/abc/a.html:Servlet1 ②/abc:Servlet3 ③/abc/a.do:Servlet1 ④/a.do:Servlet2 ⑤/xxx/yyy/a.do:Servlet4
解析URL的顺序:当输入一个URL时,首先会到web.xml文件中查找是否与偶匹配的url-pattern,如果能匹配到url-pattern,则处理,如果不能匹配到,则交给tomcat的default-servlet处理,也就是会去加载静态资源文件。
结论:先找动态资源,后找静态资源。
6.get请求与post请求
get请求: ☆在浏览器地址栏直接传参 ☆超链接 ☆表单默认提交方式post请求: ☆将表单的默认提交方式改成post, <form method = “post”></form>
7.HTTP协议简述
什么是http协议 hypertext transport protocal 超文本传输协议 是一种应用协议,包含了浏览器与服务器的通讯过程及数据格式。通讯过程 step1.建立连接,浏览器根据ip及端口号与服务器建立连接 step2.打包,发送请求,浏览器将数据打包向服务器发送请求 step3.打包,发送响应,服务器将数据打包向浏览器发送响应 step4.服务器关闭连接 特点:一次请求,一次连接 优点:效率高,可以用有限的资源为更多的用户服务数据格式 ●请求数据包 请求行 请求方式(get/post) 请求资源路径(/应用名/….) 协议类型及版本 若干消息头 是一些键值对,由w3c制定,具有特定的含义。 规定了浏览器与服务器之间,可以通过发送消息头的方式来传递一些信息。 比如user-agent,它包含了浏览器的相关信息,比如类型及版本号。 实体内容 如果是post请求,浏览器会将参数名=参数值放在该处。 如果是get请求,参数名=参数值跟在请求资源路径后面。 ● 响应数据包 响应行 协议类型及版本号 响应的状态码 状态码描述信息 若干消息头 由w3c制定的一些键值对,比如 content-type:告诉浏览器,服务器返回的数据类型及编码格式 实体内容 服务器处理之后的数据get请求与post请求区别 1)如果是get请求,请求参数是放在请求资源路径后面,不能够提交大量的数据(不同的浏览器对数据量大小的限制不一样, 一般是2k-8k,为了保证浏览器的兼容性,最好不要超过2k), 而post请求的请求参数是放在实体内容里面,理论上没有限制。 2)post相对于get更安全。post也不是绝对的安全,因为服务器不会对数据加密,可以通过代理服务抓取数据包,所以对于敏感的数据建议加密。
8.servlet获取请求参数
参数名唯一 String request.getParameter(参数名); 注: a.如果参数名写错,返回的是null b.如果用户在输入框没有输入数据,返回的是 “”参数名有多个相同 String[] request.getParameterValues(参数名);
9.转发与重定向
重定向
服务器向浏览器发送一个302的状态码以及一个location消息头(值就是一个url地址),当浏览器检测到302状态码之后,会立即向location的地址发送请求如何重定向 response.sendRedirect(String url);重定向的特点
重定向之后,浏览器地址栏的地址会发生改变重定向的地址是任意的转发
一个web组件(servlet/jsp)将未完成的事情交给另外一个组件继续完成。通常情况是servlet将未做完的事情交给jsp继续处理。比如:servlet负责取数据,jsp负责展示数据如何转发
step1.绑定数据 //name:绑定名 obj:绑定值 request.setAttribute(String name,Object obj); //根据绑定名获取绑定值 Object request.getAttribute(String name)step2.获得转发器 //url:转发的目的地 RequestDispatcher dispatcher = request.getRequestDispatcher(String url);step3.转发 dispatcher.forward(req,res);转发的特点
转发之后,浏览器地址的地址不会发生改变转发的地址只能是同一应用内部的地址转发之间的组件共享同一个request和response
10.servlet 生命周期
1)为什么要学习Servlet生命周期
Servlet程序由tomcat服务器调用,所以有必要去知道究竟怎么去调用,Servlet生命周期就是要去搞明白Servlet对象什么时候去创建?调用什么方法?什么时候Servlet对象被销毁?销毁调用什么方法做了什么事情?Servlet程序的生命周期是由tomcat服务器去控制的。
2)servlet分为几个阶段
阶段一:实例化
情况一(默认):
当请求到达容器时,容器会先检查是否有该对象,如果没有,创建该servlet对象,servlet生命周期整个过程当中,只会被实例化一次。情况二:
当容器启动时创建servlet对象因为有一些servlet实例化之后需要做大量的初始化工作,比如读取配置文件信息,这些操作需要花费 一定的时间,如果当请求到达容器时才实例化,那么服务器响应的时间会较长,影响用户体验度。方式: 在web.xml文件中配置<load-on-startup>1</load-on-startup>配置的参数>=0的整数,数值越小,优先级越高
阶段二:初始化
容器为servlet分配资源,调用init(ServletConfig)方法,ServletConfig对象由容器在调用init方法之前创建好,可以通过getServetConfig()方法获取到config对象,config.getInitParameter(key)通过该方法可以获取初始化参数值 可以在web.xml中配置初始化参数,或者通过注解方式<init-param> <param-name>city</param-name> <param-value>南京</param-value></init-param>
String value = getServletConfig().getInitParameter(“key”);注:可以重写init方法,建议重写无参的init()
阶段三:就绪
在servlet对象实例化完,并且初始化工作已结束,容器会调用service方法,会根据请求方式决定调用doGet()还是doPost();可以重写service()方法 (建议),也可以重写doGet()或者doPost()方法注:service方法在请求到达容器时被调用,而且每发送一次请求,就会被调用一次
阶段四:销毁
容器会根据自身的算法,调用destroy方法
总结:在servlet生命周期的整个过程中,实例化/初始化/销毁只会被执行一次,而就绪会被调用多次。
3)servlet相关的接口与类
servlet接口 init(ServletConfig config); ServletConfig是一个接口 service(ServletRequest req,ServletResponse res); ServletRequest接口 ServletResponse接口 destroy();
GenericServlet抽象类实现了servlet接口 init(); destroy();
HttpServlet抽象类继承了GenericeServlet service()方法