servlet学习笔记

表单数据

  • 读取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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值