买网站平台名字吗,厦门网站建设的公司哪家好,wordpress 备案,辽宁省建设工程招标网目录
1. HttpServlet
1.1 init方法
1.2 destroy方法
1.3 service方法
1.4 Servlet的生命周期
1.5 代码示例
1.5.1 使用postman构造请求
1.5.2 使用ajax构造请求
2. HttpServletRequest
2.1 核心方法
2.2 代码示例1#xff1a;打印请求信息
3. 前端给后端传参
3.1…目录
1. HttpServlet
1.1 init方法
1.2 destroy方法
1.3 service方法
1.4 Servlet的生命周期
1.5 代码示例
1.5.1 使用postman构造请求
1.5.2 使用ajax构造请求
2. HttpServletRequest
2.1 核心方法
2.2 代码示例1打印请求信息
3. 前端给后端传参
3.1 通过GET的query string
3.2 通过POST借助form表单
3.3 通过POST使用json格式构造body
4. HttpServletResponse [便捷起见非必要时Servlet程序均以smart tomcat方式部署程序]
Servlet有3个重要类分别为HttpServletHttpServletRequestHttpServletResponse
1. HttpServlet
编写Servlet程序第一步就是创建一个类继承自HttpServlet类并重写其doGet方法
其核心方法有
方法名称调用时机init在HttpServlet实例化之后被调用一次destroy在HttpServlet实例不再使用的时候调用一次service收到HTTP请求的时候调用doGet收到GET请求时调用由service方法调用doPost收到POST请求时调用由service方法调用doPut/doDelete/do Options/...收到其他请求时调用由service方法调用
1.1 init方法
1. 不由程序员手动调用由tomcat自动调用
2. 当tomcat首次收到了和该类相关联的请求时才会进行实例化 以上一篇用Servlet的hello world程序为例 WebServlet注解就是将/hello类和HelloServlet类绑定在一起表示
如果Tomcat收到了/hello这样路径的请求就会调用HelloServlet于是就对HelloServlet进行实例化
实例化只进行一次后续再收到/hello就不必再重复实例化了直接复用之前的HelloServlet实例即可
3. 可以重写init方法插入一些我们自己的初始化的逻辑
运行以下代码
WebServlet(/hello)
public class HelloServlet extends HttpServlet {Overridepublic void init() throws ServletException {// 重写init方法System.out.println(init);}Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 把数据显示在服务器控制台System.out.println(Hello world);
// 把数据写回浏览器resp.getWriter().write(Hello world);}
}
1运行程序仅启动服务器时在控制台并未打印init
原因只有当请求关联到hello路径时才会打印
2在浏览器中打开页面即触发了请求此时服务器的日志上就会调用init进行实例化 3多次刷新页面即多次发送请求 doGet方法多次被调用而init方法仅被调用一次
4. 也可以通过修改web.xml配置让tomcat启动时立即实例化该servlet
5. servlet是服务器上运行的代码只要服务器不重新启动init就不会再执行
1.2 destroy方法
1. 可以使用destroy方法进行一些清理工作
2. 只要服务器在运行都有可能再使用服务器终止时就不可再使用了
3. 重写destroy方法
WebServlet(/hello)
public class HelloServlet extends HttpServlet {Overridepublic void init() throws ServletException {// 重写init方法System.out.println(init);}Overridepublic void destroy() {
// 重写destroy方法System.out.println(destroy);}Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 把数据显示在服务器控制台System.out.println(Hello world);
// 把数据写回浏览器resp.getWriter().write(Hello world);}
}启动服务器并刷新页面后点击停止后可见服务器日志调用了destroy方法 注但此处的destroy方法是否能被执行到并不确定
第一种情况如果是使用smart tomcat的停止按钮终止程序这个操作本质上是通过tomcat的8005端口来主动停止可以触发destroy方法
第二种情况如果是直接杀进程此时可能就来不及执行destroy方法
故而并不推荐使用destroy方法
1.3 service方法
当收到路径匹配的HTTP请求就会触发service方法
比如doGet方法就是在service方法中调用的
父类HttpServlet有一个service方法其内部就会调用doGet方法
1.4 Servlet的生命周期
开始时执行 init
每次收到请求执行 service
销毁前执行 destroy 注一个servlet程序包含很多个servlet某个servlet的生死不影响整个sevlet程序
1.5 代码示例
在java目录下再创建一个类MethodServlet
其内容如下
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;WebServlet(/method)
public class MethodServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(doGet);resp.getWriter().write(doGet);}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(doPost);resp.getWriter().write(doPost);}Overrideprotected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(doPut);resp.getWriter().write(doPut);}Overrideprotected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println(doDelete);resp.getWriter().write(doDelete);}
}
直接在浏览器输入地址访问只能发送GET请求其他请求类型可以通过ajax或postman进行构造。
1.5.1 使用postman构造请求 基于一次浏览器地址访问后即已构造一个GET请求使用postman依次构造GETPOSTPUTDELETE请求并发送再查看服务器日志 1.5.2 使用ajax构造请求
1. 在IDEA中创建.html文件 tomcat要求.html文件设置在webapp目录下与WEB-INF同级
可以使用vscode进行编写 用vscode打开即可
2. 编写代码
!doctype html
html langen
headmeta charsetUTF-8meta nameviewportcontentwidthdevice-width, user-scalableno, initial-scale1.0, maximum-scale1.0, minimum-scale1.0meta http-equivX-UA-Compatible contentieedgetitleDocument/title
/head
bodyscript srchttps://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js/scriptscript$.ajax({type:get,url:method,// 此处url为相对路径此时基准路径为当前html所在的路径127.0.0.1:8080/hello_servletsuccess:function(body, status){console.log(body);}})/script
/body
/html
在浏览器输入地址 按f12进入chrome的console标签页 同样在服务器日志也可见 3. 依次修改请求类型为postputdelete再运行即可得到不同的结果 注使用ajax构造HTTP请求的注意点
1html文件的位置webapp下与WEB-INF同级
2在html文件中使用ajax构造HTTP请求时的url可以写为相对路径该相对路径的基准路径就是当前html文件的路径在此例中为127.0.0.1:8080/hello_servlet
也可以写为绝对路径浏览器要求以 / 开头的为绝对路径 $.ajax({type:get,url:/hello_servlet/method,success:function(body, status){console.log(body);}})
3注意WebServlet注解的路径必须 / 开头此处的含义不是绝对路径而是servlet的要求
2. HttpServletRequest
HttpServletRequest表示一个HTTP请求这个对象是tomcat自动构造的
tomcat其实会自动监听端口接受连接读取请求解析请求构造请求对象等一系列工作
2.1 核心方法
方法描述String getProtocal()返回请求协议的名称和版本 String getMethod() 返回请求的HTTP方法的名称如GET、POST或PUTString getQequestURI()从协议名称直到HTTP请求的第一行的查询字符串中返回该请求的URL的一部分String getContexPath()返回指示请求上下文的请求URI部分String getQueryString()返回包含在路径后的请求URL中的查询字符串?后的参数Enumeration getParameterNames()返回一个String对象的枚举包含在该请求中包含的参数的名称String getParameter(String name)以字符串形式返回请求参数的值或者如果参数不存在则返回nullString[] getParameterValues(String name)返回一个字符串对象的数组包含所有给定的请求参数的值如果参数不存在则返回nullEnumeration getHeaderNames()返回一个枚举包含在该请求中包含的所有头名String getHeader(String name)以字符串形式返回指定的请求头的值String getCharacter Encoding()返回请求主题中使用的字符编码的名称String getContentType()返回请求主题的MIME类型如果不知道类型则返回nullint getContentLength()以字节为单位返回请求主体的长度并提供输入流或者如果长度未知则返回-1InputStream getInputStream()用于读取请求的body内容返回一个InputStream对象 注1query string是键值对结构此处可以通过getParameter方法来根据key获取到value
2InputStream就是输入流对象进行read操作即可把body数据读取出来
2.2 代码示例1打印请求信息
基于hello_servlet项目创建一个ShowRequestServlet.java文件其内容如下
import javax.servlet.ServletException;
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.util.Enumeration;WebServlet(/showRequest)
public class ShowRequestServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 设置响应的content-type即表明body里的数据格式是何种类型resp.setContentType(text/html);// 创建一个StringBuilder把这些api的结果拼起来统一写回响应中StringBuilder stringBuilder new StringBuilder();stringBuilder.append(req.getProtocol());stringBuilder.append(br);stringBuilder.append(req.getMethod());stringBuilder.append(br);stringBuilder.append(req.getRequestURI());stringBuilder.append(br);stringBuilder.append(req.getContextPath());stringBuilder.append(br);stringBuilder.append(req.getQueryString());stringBuilder.append(br);stringBuilder.append(br);stringBuilder.append(br);// 获取到header中的所有键值对EnumerationString headerNames req.getHeaderNames();while(headerNames.hasMoreElements()){String headerName headerNames.nextElement();stringBuilder.append(headerName : req.getHeader(headerName));stringBuilder.append(br);}resp.getWriter().write(stringBuilder.toString());}
}
运行后根据url打开页面 注1此处实现html页面的换行操作不能使用\n而使用br标签同时设置响应的content-type为text/html告诉浏览器响应的body里的数据格式是何种类型
2按照没有添加query string时默认响应为null比如增加query string 为a10b20响应的query string便为a10b20
3. 前端给后端传参
3.1 通过GET的query string 1前端test.html
!doctype html
html langen
headmeta charsetUTF-8meta nameviewportcontentwidthdevice-width, user-scalableno, initial-scale1.0, maximum-scale1.0, minimum-scale1.0meta http-equivX-UA-Compatible contentieedgetitleDocument/title
/head
bodyform actionpostParameter methodpostinput typetext namestudentIdinput typetext nameclassIdinput typesubmit value提交/formscript srchttps://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js/scriptscript/script
/body
/html
2后端GetParameterServlet.java
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;WebServlet(/getParameter)
public class GetParameterServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 预期浏览器会发一个形如 /getParameter?studentId001classId2001;// 借助req的getParameter方法就能拿到query string 中的键值对内容了// getParameter得到的是一个String类型的值String studentId req.getParameter(studentId);String classId req.getParameter(classId);resp.setContentType(text/html);resp.getWriter().write(studentId studentId classId classId);}
}运行程序后根据url打开浏览器页面如下 注1输入在url后的查询字符串键值对会被Tomcat处理成形如Map这样的结构后续就可以随时通过key来获取到value了
2如果key在query string中不存在则返回值为空
3.2 通过POST借助form表单
form表单也是键值对形式组织数据的只是这部分内容在body中
对于前端是form表单这样格式的数据后端还是使用paraMeter来获取
1前端test.html
!doctype html
html langen
headmeta charsetUTF-8meta nameviewportcontentwidthdevice-width, user-scalableno, initial-scale1.0, maximum-scale1.0, minimum-scale1.0meta http-equivX-UA-Compatible contentieedgetitleDocument/title
/head
bodyform actionpostParameter methodpostinput typetext namestudentIdinput typetext nameclassIdinput typesubmit value提交/formscript srchttps://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js/scriptscript/script
/body
/html 2后端PostParameterSrvlet.java
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;WebServlet(/postParameter)
public class PostParameterServlet extends HttpServlet {Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String studentId req.getParameter(studentId);String classId req.getParameter(classId);resp.setContentType(text/html);resp.getWriter().write(studentId studentId classId classId);}
}
运行程序后根据url打开浏览器页面 提交后页面如下 注1使用query string和使用form表单的后端代码格式基本相同都是通过getParameter根据key获取value只是使用form表单构造的键值对不在query string中而是在body中
2getParameter方法不仅能获取到请求中query string中的键值对还可以获取到form表单构造的body中的键值对
3以form表单形式构造并发送的请求一定会触发页面跳转
4.html及请求、浏览器页面的对应关系图 5前端后端交互的过程
图1 图2 3.3 通过POST使用json格式构造body
json也是键值对结构的数据格式可以把body按照该形式组织
在前端可以通过ajax方式构造该内容也可以使用postman
1postman构造请求 2后端PostParameter2Sevlet.java
import javax.servlet.ServletException;
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.InputStream;WebServlet(/postParameter2)
public class PostParameter2Servlet extends HttpServlet {Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 通过这个方法处理 body 为 json 格式的数据// 直接把 req 对象中的 body 完整地读取出来// 获取请求的body长度并构造数组int length req.getContentLength();byte[] buffer new byte[length];InputStream inputStream req.getInputStream();inputStream.read(buffer);//把这个字节数组构造成 String, 打印出来String body new String(buffer, 0, length,utf8);System.out.println(body body);resp.setContentType(text/html);resp.getWriter().write(body);}
}
使用fiddler可以查看到构造的json请求 当请求到达tomcat后tomcat就会将其解析为req对象
在servlet代码中req.getInputStrea,读取body内容又把body的内容构造成一个响应结果返回给浏览器此例中为postman在post页面中就有响应结果 注1使用form表单构造请求传参与json格式请求传参的代码执行流程是类似的只是传输数据的格式不同
form表单的格式形如 json格式形如: 但是当前通过json传递数据服务器只是将整个body都读出来没有按照键值对的方式处理还不能根据key获取到value可以使用第三方库来解析json的body如jacksongsonfastjson由于spring mvc内置了jackson这个库故而天然就支持处理jackson的数据。
故而以引入jackson库为例
通过maven引入第三方库 基于jackson库修改代码使得获取到请求body内部的键值对 class Student{public int studentId;public int classId;
}
WebServlet(/postParameter2)
public class PostParameter2Servlet extends HttpServlet {Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 使用jackson的核心对象ObjectMapper objectMapper new ObjectMapper();// readValue就是把一个json格式的字符串转为java对象Student student objectMapper.readValue(req.getInputStream(), Student.class);}
}
注意1objectMapper对象的readValue方法的作用
① 将json格式的字符串读取出来
② 根据第二个参数类对象创建Student实例第二个参数是一个类对象
③ 解析json格式的字符串处理成map键值对结构
④ 遍历所有键值对看键的名字和Student实例的哪个属性名匹配就把对应的value设置到该属性中
⑤ 返回该Student实例
2readValue方法用于将json字符串转成java对象writeValue方法用于把一个java对象转成json格式字符串
3在上文代码中将Student类内的属性设置为public修饰这在Java中并不常见。但是如果要把一个类作为jackson返回的对象就需要让jackson能够看到类中的属性可以采取的方法有
① 把属性设置为public② 给该属性提供public修饰的getter与setter方法
4. HttpServletResponse
servlet代码种的doXXX方法就是根据请求计算响应后将响应的数据设置到HttpServletResponse对象中。tomcat就会将这个HttpServletResponse对象按照HTTP协议的格式转成一个字符串并通过socket写回给浏览器
其核心方法有
方法描述void setStatus(int sc)为该响应设置状态码void setHeader(String name, String value)设置一个带有给定的名称和值的header如果name已经存在则覆盖旧值void addHeader(String name, String value)添加一个带有给定的名称和值的header如果name已经存在不覆盖旧值并列添加新的键值对void setContentType(String type)设置被发送到客户端的响应的内容类型void setCharacterEncoding(String charset)设置被发送到客户端的响应的字符编码MIME字符集例如UTF-8void sendRedirect(String Location)使用指定的重定向URL发送临时重定向响应到客户端PrintWriter getWriter()用于往body中写入文本格式数据OutputStream getOutputStream()用于往body中写入二进制格式数据
1一个HTTP响应中报头的key是可以存在多个重复的
2可以通过setCharacterEncoding指定响应的编码格式
浏览器默认不知道程序员的页面编码方式会采取猜测的方式使用字符集进行解析比如在getParameterServlet.java中将写回浏览器的响应格式写为
resp.setContentType(text/html);
resp.getWriter().write(学生id: studentId 班级id: classId); 此时根据路径打开浏览器页面就会出现乱码 为了避免这种情况我们需要在写回响应前显式指定响应的编码格式字符集 resp.setContentType(text/html);resp.setCharacterEncoding(utf-8);resp.getWriter().write(学生id: studentId 班级id: classId);
刷新浏览器页面有 3也可以把字符集和ContentType一起设置 resp.setContentType(text/html; charsetutf8);resp.getWriter().write(学生id: studentId 班级id: classId);
4void sendRedirect用于构造重定向响应3xxx的状态码就会跳转到另外一个页面
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;WebServlet(/redirect)
public class RedirectServlet extends HttpServlet {Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.sendRedirect(https://www.sogou.com);}
}
运行代码后根据路径打开浏览器页面即可跳转至搜狗主页 前后端交互逻辑如下 实现重定向尤其是返回错误页面有多种方式