如果每一个自定义的Servlet类都 implements Servlet接口,那么多个Servelt中就会出现重复代码。
解决方案:重构代码,消除重复
1、GenericServlet 抽象类 implements Servlet, ServletConfig, java.io.Serializable
GenericServlet类可以处理普通的请求和响应
1)Servlet的 init(config)方法,并在该方法中编写自己的初始化代码
GenericServlet类专门提供了一个无参数的初始化方法 init(),暴露给子类去实现。
执行步骤:
当执行 GenericServlet的 init(config)方法时,会调用this.init()方法(多态的作用),会执行子类实现的方法,
2)定义一个全局的 ServletConfig对象
把当前的servletConfig对象暴漏给子类访问使用,并覆写了ServletConfig的操作方法
遵循守恒原则,子类就少写了代码 那么父类要给补回来 。
3)service方法定义成抽象的,让子类必须实现,所以GenericServlet类也是抽象的
自定义Servlet类继承GenericServlet
public class LifeServlet extends GenericServlet {
private static final long serialVersionUID = 1L;
private ServletContext servletContext;
@Override
public void init() throws ServletException {
System.out.println("init");
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("service");
ServletConfig config = getServletConfig();
servletContext = getServletContext();
System.out.println(config);
System.out.println(servletContext);
Enumeration enumeration = getInitParameterNames();
while (enumeration.hasMoreElements()) {
String name = (String) enumeration.nextElement();
String value = getInitParameter(name);
System.out.println(name + ";" + value);
}
}
}
如何处理HTTP类型的请求和响应
2、HttpServlet抽象类 extends GenericServlet
HttpServlet类可以处理 HTTP协议的请求和响应。
http请求有GET、POST请求,针对不同的请求,分而治之。解决方案:提供doGet方法与doPost方法
1)service方法获取http信息,分而治之
2)分而治之的doXxx方法需子类去实现
自定义Servlet类继承HttpServlet
public class LifeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private ServletContext servletContext;
@Override
public void init() throws ServletException {
System.out.println("init");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPut(req, resp);
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("service");
ServletConfig config = getServletConfig();
servletContext = getServletContext();
System.out.println(config);
System.out.println(servletContext);
Enumeration enumeration = getInitParameterNames();
while (enumeration.hasMoreElements()) {
String name = (String) enumeration.nextElement();
String value = getInitParameter(name);
System.out.println(name + ";" + value);
}
}
}
开发中一般的Servlet继承体系:
API文档:https://docs.oracle.com/javaee/7/api/
二、HttpServletRequset接口在Servlet API中,ServletRequest接口被定义为用于封装请求的信息,ServletRequest对象由Servlet容器在用户请求Servlet时创建并传入Servlet的service()方法中。
HttpServletRequest接口继承了ServletRequest接口,是专用于HTTP协议的子接口,用于封装HTTP请求信息。在HttpServlet类的service()方法中,传入的ServletRequest对象被强制转换为HttpServletRequest对象来进行HTTP请求信息的处理。
1、HttpServletRequset中常用方法:具体查看API
1)获取请求行信息
getMethod():获取请求使用的HTTP方法,如POST,GET
getRequestURI():获取请求行中的资源名部分
getProtocol():获取使用的协议及版本号,如HTTP/1.1
getQueryString():获取请求URL后面的查询字符串,只对GET有效
getServletPath():获取Servlet所映射的路径
getContextPath():获取请求资源所属于的web应用的路径
2)获取请求头信息
getIntHeader(String name):获取整数类型参数名为name的http头部
getDateHeader(String name):获取long类型参数名为name的http头部
getContextLength():获取请求内容的长度,以字节为单位
getContextType():获取请求的文档类型和编码
getLocale():获得用户浏览器设置的Locale信息
getCookies():获取一个Cookie[]数组,该数组包含这个请求中当前的所有cookie
常见请求头:
3)获取请求正文
请求正文内容为POST请求参数名称和值组成的一个字符串。POST请求主要通过form表单进行数据提交,而表单元素的enctype属性可以指定两种编码方式,默认使用的是application/x-www-form-urlencoded。在这种情况下,浏览器提交表单的时候会将元素名和元素值以“=”分隔形成一个参数,每个参数之间以&分隔组成正文内容。
在Servlet中可以使用:getParameter(String name),getParameterNames(),getParameterValues(String name),getParametrerMap()等方法获取参数名和参数值。
当表单想服务器上传文件时enctype使用的是multipart/form-data。其编码方式的请求正文由描述头、空行和主体内容三部分组成,非文件类型元素的主体内容就是表单设置的值,文件类型的主体内容文文件的二进制数据形式。
在Servlet中可以使用:getInputStream(),getReader等方法进行获取。同时@MultiPartConfig注解方式也有方法提供。
4)获取网络连接信息
getRemoteAddr():获取请求用户的ip地址
getRemoteHost():获取请求用户的主机名
getRemotePort():获取请求用户使用的端口号
getLocalAddr():获取web服务器的ip地址
getLocalName():获取web服务器的主机名
getLocarPort():获取web服务器使用的端口号
getServerName():获取网站的域名
getServerPort():获取url请求的端口号
getScheme():获取请求使用的协议
getRequestURL:获取请求的url地址
5)存取请求域属性
void setAttribute(String name, Object value):设定name的属性值为value,保存在request范围内
Object getAttribute(String name):从request范围了获取name属性的值
void removeAttribute(String name):从request范围移除name属性的值
Enumeration getAttributeNames():获取所有request范围的属性
三、HttpServletResponse接口
ServletResponse接口:该对象封装了服务器要返回客户端的所有响应信息。如果使用HTTP,则包含了HTTP的响应行、响应头部和响应体。
HttpServletResponse接口:是ServletResponse的子接口,处理HTTP协议响应信息。
1、HttpServletResponse中常用方法:具体查看API
1)设置返回内容类型
response.setContentType("text/html");
response.setContentType(MIME)的作用是使客户端浏览器,区分不同种类的数据,并根据不同的MIME调用浏览器内不同的程序嵌入模块来处理相应的数据。
2)设置字符编码
response.setCharacterEncoding("UTF-8");
3)设置响应状态码
response.setStatus(200);
4)设置响应头
response.setHeader("username", "admin");//也可以添加一些私人的头部信息
5)发送返回内容
response.getWriter().writer(); 发送字符实体内容
response.getOutputStream().writer() 发送字节实体内容,比如文件下载等
注意:这两个方法不能共存,会报错。
6)设置输出的内容的MIME类型
void
setContentType(String type)
Sets the content type of the response being sent to the client, if the response has not been committed yet.
三、四的一个简单demo
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username") ;
String password = req.getParameter("password") ;
/*
resp.setContentType("text/html"); // 设置输出的MIME类型(内容的类型)
resp.setCharacterEncoding("UTF-8"); // 设置输出数据的编码方式
*/
//推荐使用此方法。等同于上面两行代码
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.write("this is tilte");
out.write("LifeServlet:" + username + "--" + password);
out.write("");
}
浏览器方法:http://127.0.0.1:8080/DemoServlet/life?username=admin&password=123456
三、请求的中文乱码问题
在Tomcat中,对于POST和GET请求,都默认采用 ISO-8859-1的编码方式,而 ISO-8859-1不支持中文,所以乱码
1、解决方案(不推荐)
按照 ISO-8859-1 把乱码恢复成二进制形式的数据,然后再把二进制形式的数据使用UTF-8重新编码。
byte[] usernamedata = username.getBytes("ISO-8859-1");
username = new String(usernamedata, "UTF-8");
System.out.println(username);
2、解决方案(推荐)
1)针对POST请求方法
req.setCharacterEncoding("UTF-8");
注意:必须放在获取任意参数之前,对GET无效
2)针对GET请求方法
修改Tomcat中的server.xml配置文件,如下:
参考文章:
HttpServletRequset接口相关内容全解
HttpServletResponse接口详解
站在前辈的肩膀上,每天进步一点点
ends~