一、Servlet是什么
(1)Servlet:Server Applet,全称java servlet。java编写的服务端程序,交互式的浏览和修改数据,生成动态web内容。狭义的Servlet是java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类。一般人们理解为后者。
(2)Servlet运行在支持java的应用服务器中。Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的web服务器。
(3)Servlet的工作模式:
- 客户端发送请求至服务器
- 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器
- 服务器将响应返给客户端
二、Servlet API
三、第一个Servlet
3.1、创建一个类实现接口Servlet
package com.jsonliu.test;
import javax.servlet.*;
import java.io.IOException;
/**
* @Author: JSONLiu
* @Description:
* @Date Created in 2021-08-14 17:42
* @Modified By:
*/
public class LoginServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//初始化方法
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse)
throws ServletException, IOException {
//处理post、get的方法
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
//销毁方法
}
}
3.2、在web.xml中配置映射关系
<servlet>
<servlet-name>自定义名称</servlet-name>
<servlet-class>处理请求的类的完整路径</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>自定义名称</servlet-name>
<url-pattern>请求名</url-pattern>
</servlet-mapping>
标签执行顺序:
请求-> web.xml -> servlet-mapping标签中的url-pattern标签内容和请求进行匹配 -> 匹配成功后找到servlet-mapping中servlet-name -> 去servlet中找和上一个servlet-name相同的name值 -> 去找servlet中servlet-class中处理类的完整路径
四、Servlet工作原理
(1)Servlet接口定义了Servlet和servlet容器之间的契约。这个契约是:Servlet容器将Servlet类载入内存,并产生Servlet实例和调用它具体的方法。在一个应用程序中,每种Servlet类型都只有一个实例。
(2)用户请求致使Servlet调用Service()方法,并传入一个ServletResquest对象和一个ServletResponse对象,这两个对象都是有Servlet容器(例:Tomcat)封装好的,不需要程序员去实现,可以直接使用。
(3)ServletResquest中封装了当前http请求,开发人员不需要解析和操作原始的http数据。ServletResponse表示当前用户的http响应,程序员只需要操作ServletResponse就可以把响应发回给用户。
(4)对于每一个应用程序,Servlet容器还会创建一个ServletContext对象。这个对象封装了应用程序上下文的环境详情。每个应用程序只有一个ServletContext。每个Servlet对象也有一个封装Servlet配置的ServletConfig对象。
五、Servlet的生命周期
当客户端发送首次请求时,由容器(web服务器tomcat)去解析请求,根据请求找到对应的Servlet,判断该类的对象是否存在,不存在则创建对象实例,调取init()方法初始化操作。初始化完成后调取service()方法,由service()判断客户端请求方式,如果是get执行doGet(),如果是post执行doPost()。处理方法完成后,作出相应的回应给客户端,单次请求结束。
当用户第二次发送请求时候,会判断对象是否存在,但不会执行init()方法。而直接执行service()方法调取doGet()或者doPost()。
四个过程:
- 实例化 – 创建servlet实例
- 初始化 – init()
- 处理请求 – service()
- 服务终止 – destory()
六、请求
HttpServletResquest是Http环境中的Servlet请求。它扩展与java.servlet.ServletResquest接口。
常用方法:
String getParameter(String name)根据表单组件名称获取提交数据,返回值是String。(注意:服务器在接收数据时使用字符串统一接收)
String getParameterValues(String name)获取表单组件对应多个值时的请求数据
void setCharacterEncoding(String charset)指定每个请求的编码(针对post请求才起作用)
ResquestDispatcher getResquestDispatcher(String path) 跳转页面(返回一个ResquestDispatcher对象,该对象的foward()方法用于转发请求)
request.getResquestDispatcher("…/success.jsp").foward(request,response);
// 存值
request.setAttribute("key",value);
// 取值
request.getAttribute("key");
// 取值后向下转型
String uname=(String)request.getAttribute("key");
6.1、客户端发送数据给服务器
方式1:Get/Post提交表单
方式2:通过a标签发送数据(get提交)
<a href="请求名?key=value&key=value&key=value">
这里的key等于表单元素的控件名,value等于表单中控件的value属性。
数据获取方式:
String name=request.getParameter("name");
方式3:地址栏直接拼接get请求
方式4:JS提交Get请求
location.href="目标请求?key=value&key=value"
6.2、处理请求乱码
方式1:
//post提交管用
setCharacterEncoding("UTF-8");
方式2:
//get提交时中文乱码
String s=new String(变量名.getBytes("ISO-8859-1"),"UTF-8");
方式3:
修改tomcat服务器server.xml中字符集
6.3、get和post的区别
- get请求,所有请求数据会附加在URL之后,以?分割URL和传输数据,多个参数用&连接。URL编码采用ASCII码,所有的非ASCII码需要编码后再传输。
- post请求,会把所有的数据放到Http请求包的包体中。get请求的数据会暴露在地址栏中,post则不会。
- 传输数据的大小:get请求时,特定浏览器和服务器会对URL有长度限制,get请求时传输数据会收到URL长度限制。post理论上不受限制,但是实际开发中Apache、IIS等服务器对post提交数据大小进行设置。
- Post安全性比get高
七、响应
// HttpServletResponse接口继承ServletResponse接口,专门用来封装Http响应消息。在HttpServletResponse接口中定义了向客户端发送响应状态码,响应消息头,响应消息体的方法。
// 常用方法:
void addCookie(Cookie var1); //给这个响应添加一个cookie
void sendRedirect(String var1);//发送一条响应码,将浏览器跳转至指定位置
PrintWriter getWriter();//获得字符流,通过字符流的write(String s)方法可以将字符串
// 设置到response的缓冲区,随后tomcat将response缓冲区中的内容组装成Http响应返回给浏览器端。
setContentType();//设置响应内容的类型
7.1、重定向和转发对比
重定向:
request.setRedirect();
转发:
request.getDispatcher("../success.jsp").foward(request,response);
都是用来跳转页面。
不同点:
-
重定向时会改变地址栏地址信息,request中存储的数据会丢失;转发时,地址栏中显示的是请求页面地址,request中存储的数据能保留。
-
转发属于一次请求一次响应,重定向属于两次请求两次响应。
-
使用out对象向浏览器中输出js或者html、css
out.print("<script type='text/javascript'>
alert('登录失败');location.href='../login.jsp'</script>");
注:使用js跳转页面,也会丢失request中的数据。
八、会话
request中存的值只能在单次请求中保存,保存的数据不能跨页面,当重定向时,request保存的值会丢失。session中的数据可以在多个页面间共享,即使重定向,数据也不会丢失。
会话的概念:从打开浏览器到关闭浏览器,期间访问浏览器,就称为一次会话。
常用方法:
void setAttribute(String key,Object val);//以key/value形式保存对象值,将数据存储在服务器端
Object getAttribute(String key); //通过key获取对象值
void invalidate();//设置session对象失效
String getId();//获取sessionid,当第一次登陆成功后,session会产生一个唯一ID,
// 浏览器之后访问如果发现ID还是之前那个ID,那么说明当前访问属于同一个会话。
void setMaxInactiveinterval(int interval);//设置session的非活动时间
示例:
方式1:session.setMaxInactiveinterval(10*60); //设置有效时间为10分钟
方式2:修改web.xml
<session-config>
<session-timeout>10</session-timeout> //单位:分钟
</session-config>
int getMaxInactiveinterval();//获取session的有效非活动时间,默认30分钟
void removeAttribute(String key);//从session中删除指定key对象
session失效的三种办法:
1、invalidate
2、removeAttribute(“key”);
3、直接关闭浏览器
九、获得初始化参数
request.setCharacterEncoding(“UTF-8”);//代码耦合度太高,不便于后期维护,可以通过初始化参数修改。
实现方式:
1、web.xml中先定义初始化参数
<servlet>
<servlet-name></servlet-name>
<servlet-class></servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</servlet>
2、servlet中获取初始化参数,重写init()方法
public void init(ServletConfig config) throws ServletException{
encoding=config.getInitParamter("encoding");
}
注意:这种初始化参数仅限于当前servlet使用。
9.2、全局初始化参数
1、定义context-param,与servlet同级别:
<context-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</context-param>
2、获得数据
@Override
public void init(ServletConfig config)throws ServletException{
String encoding=config.getServletContext().getInitParameter("encoding");
}
十、Servlet3.0
@WebServlet注解配置Servlet
从Servlet3.0开始,配置Servlet支持注解方式,同时也保留了web.xml方式。所以使用Servlet有两种方式:
Servlet类使用@WebServlet进行配置
web.xml中进行配置
<servlet>
<servlet-name>a</servlet-name>
<servlet-class>
<!--处理类的完整路径-->
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
10.1、代码示例
UserServlet,注解中配置,web.xml中不需要配置
package com.jsonliu.test;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
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;
import java.util.Enumeration;
/**
* @Author: JSONLiu
* @Description:
* @Date Created in 2021-08-15 13:55
* @Modified By:
*/
@WebServlet(
name = "myUserServlet",
urlPatterns = "/user/test",
loadOnStartup = 1,
initParams = {
@WebInitParam(name="name",value="小明"),
@WebInitParam(name="pwd",value="123456")
}
)
public class UserServlet extends HttpServlet {
private static final long serialVersionUID=7109220574468622594L;
@Override
public void init(ServletConfig config)throws ServletException{
super.init(config);
System.out.println("servlet初始化...");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
PrintWriter writer=resp.getWriter();
writer.append("hello servlet!<br/>");
writer.append("servletName:"+getServletName()+"<br/>");
ServletConfig config=this.getServletConfig();
Enumeration<String> parameterNames = config.getInitParameterNames();
while (parameterNames.hasMoreElements()){
String paramName = parameterNames.nextElement();
writer.append(paramName+":"+config.getInitParameter(paramName)+"<br/>");
}
writer.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
效果
说明:
- loadOnStartup:标记容器是否在启动时就加载Servlet,默认为不配置或为负数时,表示客户端第一次请求Servlet时才加载,0或者正数表示启动应用就加载。数值越小,加载该Servlet优先级越高。
- name:可以指定,也可以不指定。通过getServletName()获取,若不指定,为完整类名。
- urlPatterns/value:String[],可以配置多个映射,如:urlPatterns={"/user/test","/user/example"}
- urlPatterns常用拦截规则:
/*或者/:拦截所有
.do:拦截指定后缀
/user/test:拦截路径
/user/.do、/.do、test.do:都是非法的,启动时会报错