表单数据
- 读取get请求
如http://192.168.2.221:5338/web/getTextApi?Name=bifan
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//super.doGet(req, resp); 需要注释掉,否则会出错
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
String name = req.getParameter("Name");
out.println("<h3>你好"+name+",我的来自服务的数据 </h3>");
}
- 读取post请求
值得注意的是,监听post请求,getParame等方法返回的都是空数据,就是说不能直接post参数
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp); 需要注释掉,否则会出错
String postData = IOUtils.toString(req.getInputStream());
System.out.println("doPost:"+postData);
}
无论在postman中尝试那种的Content-Type,打印出来的结果是这样的:
doPost:
------WebKitFormBoundaryoHE1psoQ7B2oQlBt
Content-Disposition: form-data; name="Name"bifan
------WebKitFormBoundaryoHE1psoQ7B2oQlBt–
解决方法,在postman的发送post请求的body选择为x-www-form-urlencoded 就可以了,然后doPost改写为:
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp); 需要注释掉,否则会出错
doGet(req,resp);
原因是,使用了x-www-form-urlencoded,会将请求的表单数据转为字符串,并添加到url后面,相当于转换成get一样的参数,所以可以直接回调doGet就可以了。如果使用的是form-data,那么返回的就会带有------WebKitFormBoundaryoHE1psoQ7B2oQlBt,不能直接读取请求表单参数,一般是上传文件,type=file时会使用这个form-data类型,------WebKitFormBoundaryoHE1psoQ7B2oQlBt其实是消息的边界符,每个完整的消息都会包含这个。
过滤器
Servlet过滤器的作用:
A.查询请求并作出相应的行动。
B.阻塞请求-响应对,使其不能进一步传递。
C.修改请求的头部和数据。用户可以提供自定义的请求。
D.修改响应的头部和数据。用户可以通过提供定制的响应版本实现。
E.与外部资源进行交互。
Servlet使用场景:
A.认证过滤
B.登录和审核过滤
C.图像转换过滤
D.数据压缩过滤
E.加密过滤
F.令牌过滤
G.资源访问触发事件过滤
H.XSL/T过滤
I.Mime-type过滤
对全局添加日志过滤器的例子:
创建全局日志filter:
public class LogFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("======== Filter 初始化方法 ========");
// 获取的是web.xml中配置Filter时设置的值,参数为设置值得名称,若参数不存在,则返回空
String initParam = filterConfig.getInitParameter("param");
System.out.println("initParam :" + initParam);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("before the log filter!");
// 将请求转换成HttpServletRequest 请求
HttpServletRequest hreq = (HttpServletRequest) servletRequest;
// 记录日志
System.out.println("Log Filter已经截获到用户的请求的地址:" + hreq.getServletPath());
try {
// Filter 只是链式处理,请求依然转发到目的地址。
filterChain.doFilter(servletRequest, servletResponse);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("after the log filter!");
}
@Override
public void destroy() {
}
}
在web.xml配置filter:
<filter>
<filter-name>logFilter</filter-name>
<filter-class>LogFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>logFilter</filter-name>
<url-pattern> /* </url-pattern>//这里/*是指对所有servlet匹配过滤
</filter-mapping>
运行,发起一个请求结果:
======== Filter 初始化方法 ========
initParam :null
before the log filter!
Log Filter已经截获到用户的请求的地址:/getTextApi
doGet:
after the log filter!
异常捕捉
有时候出现异常,我们想要进行处理,比如客户端请求了一个接口是404的,或者是其他异常,我们想返回特定的信息,可以通过异常捕捉做到。
1.创建ErrorHandler
public class ErrorHandler extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// super.doGet(req, resp);
Throwable throwable = (Throwable)
request.getAttribute("javax.servlet.error.exception");
Integer statusCode = (Integer)
request.getAttribute("javax.servlet.error.status_code");
String servletName = (String)
request.getAttribute("javax.servlet.error.servlet_name");
if (servletName == null){
servletName = "Unknown";
}
String requestUri = (String)
request.getAttribute("javax.servlet.error.request_uri");
if (requestUri == null){
requestUri = "Unknown";
}
// 设置响应内容类型
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String title = "Error/Exception 信息";
String docType = "<!DOCTYPE html>\n";
out.println(docType +
"<html>\n" +
"<head><title>" + title + "</title></head>\n" +
"<body bgcolor=\"#f0f0f0\">\n");
out.println("<h1>异常信息实例演示</h1>");
if (throwable == null && statusCode == null){
out.println("<h2>错误信息丢失</h2>");
out.println("请返回 <a href=\"" +
response.encodeURL("http://localhost:8080/") +
"\">主页</a>。");
}else if (statusCode != null) {
out.println("错误代码 : " + statusCode);
}else{
out.println("<h2>错误信息</h2>");
out.println("Servlet Name : " + servletName +
"</br></br>");
out.println("异常类型 : " +
throwable.getClass( ).getName( ) +
"</br></br>");
out.println("请求 URI: " + requestUri +
"<br><br>");
out.println("异常信息: " +
throwable.getMessage( ));
}
out.println("</body>");
out.println("</html>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
doGet(req,resp);
}
2.配置web.xml
<servlet>
<servlet-name>ErrorHandler</servlet-name>
<servlet-class>ErrorHandler</servlet-class>
</servlet>
<!-- servlet 映射 -->
<servlet-mapping>
<servlet-name>ErrorHandler</servlet-name>
<url-pattern>/*</url-pattern>表示匹配所有地址
</servlet-mapping>
<error-page>配置异常处理页面
<exception-type>java.lang.Throwable</exception-type >
<location>/ErrorHandler</location>
</error-page>
运行服务器,浏览器请求一个404地址,效果如下:
异常信息实例演示
错误信息丢失
请返回 主页。
cookie设置
可以添加一个cookie,设置最大存活时长,浏览器获取到cookie后会保存该cookie:
PrintWriter out = response.getWriter();
Cookie testCookie = new Cookie("name", "bifan"); // 中文转码
//设置cookie的存活时间
testCookie.setMaxAge(60 * 1);
//添加进去cookies
response.addCookie(testCookie);
String title = "设置 Cookie 实例 完成";
out.println(title);
只要cookie还存活,浏览器下次发起请求时会将该cookie返回,可以读取到cookie,如果不为空,说明cookie还存活的:
Cookie cookie;
Cookie[] cookies;
// 获取与该域相关的 Cookie 的数组
cookies = request.getCookies();
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
cookie = cookies[i];
if ((cookie.getName()).equals("name")) {
out.print("cookie 还存在存活,name:" + cookie.getName() + ",value:" + cookie.getValue());
}
}
} else {
out.println(
"<h2 class=\"tutheader\">cookie 已经失效:</h2>");
}
Session设置
cookie是服务器存在客户端本地的,不是所有浏览器都支持cookie,session是存在服务器本地的,兼容性更好。
应用场景:
- 登录网站,今输入用户名密码登录了,第二天再打开很多情况下就直接打开了。这个时候用到的一个机制就是cookie。
- session一个场景是购物车,添加了商品之后客户端处可以知道添加了哪些商品,而服务器端如何判别呢,所以也需要存储一些信息就用到了session。
区别:
- 存储数据量方面:session 能够存储任意的 java 对象,cookie 只能存储 String 类型的对象
- 一个在客户端一个在服务端。因Cookie在客户端所以可以编辑伪造,不是十分安全。
- Session过多时会消耗服务器资源,大型网站会有专门Session服务器,Cookie存在客户端没问题。
*域的支持范围不一样,比方说a.com的Cookie在a.com下都能用,而www.a.com的Session在api.a.com下都不能用,解决这个问题的办法是JSONP或者跨域资源共享。
实现统计新访客数量:
// 如果不存在 session 会话,则创建一个 session 对象
HttpSession session = request.getSession(true);
int visitCount =1;
String visitCountKey = "visitCount";
if(session.getAttribute(visitCountKey) == null) {
session.setAttribute(visitCountKey, visitCount);
}
// 检查网页上是否有新的访问者,有新访客
if (session.isNew()){
visitCount = (Integer)session.getAttribute(visitCountKey);
visitCount = visitCount + 1;
}else{
}
session.setAttribute(visitCountKey, visitCount);
out.println(visitCount);