服务器对象Servlet

2023-01-03  本文已影响0人  不会写诗的苏轼

Servlet : server applet

 <servlet>
        <servlet-name>demo1</servlet-name>
        <servlet-class>com.xjbt.servlet.ServletGo</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>demo1</servlet-name>
        <url-pattern>/demo1</url-pattern>
    </servlet-mapping>

  1. init(ServletConfig servletConfig)被创建:
    init方法,只执行一次

说明一个servlet在内存中只存在一个对象,servlet是单例的
多个用户同时访问时,可能存在线程安全问题。
解决∶尽量不要在servlet中定义成员变量。即使定义了成员变量,也不要修改值

servlet什么时候被创建?
在配置文件web.xml=》<Servlet></Servlet>标签体中配置

指定Servlet创建时机
            指定servelet第一次访问时创建 默认
            <load-on-startup>-1</load-on-startup>
            指定servelet在服务器启动时创建
            <load-on-startup>1</load-on-startup>
  1. service(ServletRequest servletRequest, ServletResponse servletResponse)提供服务:
    执行service方法,执行多次
    每次访问servlet时,service方法都会被调用一次。
  2. destroy()被销毁:
    执行destroy方法,只执行一次
    只有服务器正常关闭时,才会执行destroy方法。
    destroy方法在servlet被销毁之前执行,一般用于释放资源

步骤

  1. 创建]avaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
  2. 定义一个类,实现servlet接口
  3. 复写方法
  4. 在类上使用@webservlet注解,进行配置@webservlet(“Servlet资源路径")
    告诉计算机(Tomcat服务器)程序的资源路径(“Servlet资源路径),程序全类名称不用写,注释在哪儿就是哪个类

HTTP


字符串格式∶
POST /login.html HTTP/1.1     -请求行
Host:localhost
User-Agent: Mozilla/5.0 (windows NT 6.1; win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0Accept: text/html,application/xhtml+xml, application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-Tw;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflate
connection: keep-alive
upgrade-Insecure-Requests: 1  -请求头 
                              -请求空行
username=zhangsanl            -请求体 POST方式才有请求体
  1. 请求行
    请求方式【GET/POST】 请求url【/login.html】 请求协议/版本【HTTP/1.1】

    请求方式:HTTP协议有7中请求方式,常用的有2种
    GET:
    1. 请求参数在请求行中,在url后。
    2. 请求的url长度有限制的
    3. 不太安全
    POST :
    1.请求参数在请求体中
    2.请求的url长度没有限制的
    3.相对安全

  2. 请求头:客户端浏览器告诉服务器一些信息
    请求头名称:请求头值

    常见的请求头:
    User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
    可以在服务器端获取该头的信息,解决浏览器的兼容性问题
    Referer : http://localhost/login.html
    *告诉服务器,我(当前请求)从哪里来?
    作用:
    1. 防盗链:防止其他网站的地址指向当前地址的资源页面
    2. 统计工作:

  3. 请求空行
    空行

  4. 请求体(正文)


HTTP/1.0 200 oK                     =>响应行
content-Type: text/html;            =>响应头
charset=UTF-8content-Length: 101        
Date: wed,06 Jun 2018 07:08:42GMT
                                    =>响应空行
<html>                              =>响应体
<head>
<title>$Title$</title></ head>
<body>
hello , response< / body>
</html>
  1. 响应行
    协议/版本【HTTP/1.0】 响应状态码【200】 状态码描述【oK】

    状态码都是3位数字
    分类:
    1xx:服务器接收客户端消息,但没有接收完成,等待一段时间后,发送1xx多状态码
    2xx:成功。代表:200
    3xx:重定向。代表:302(重定向),304(访问缓存,浏览器访问服务器图片,浏览器如果有该图片的缓存,服务器发送304,表示不用在请求这张图片)
    4xx:客户端错误。
    404:(请求路径没有对应的资源)
    405:请求方式没有对应的doXxx方法
    5xx:服务器端错误。代表:500(服务器内部出现异常)

  2. 响应头

    content-Type∶服务器告诉客尸端本次响应体数据格式以及编码格式
    content-disposition:服务器告诉客户端以什么格式打开响应体数据
    值:
    in-line:默认值,在当前页面内打开
    attachment;filename=xxx∶以附件形式打开响应体。文件下载

  3. 响应空行

  4. 响应体:传输的数据


  1. 获取请求数据:
    1. 获取请求行数据
      请求行:GET /xjbt/demo1?name=zhangsan HTTP/1.1
      方法∶
      string getMethod()获取请求方式:GET
      *string getcontextPath()获取虚拟目录:/day14
      string getservletPath()获取servlet路径:/demo1
      string getQuerystring()获取get方式请求参数: name=zhangsan
      /day14/demo1获取请求URI
      *string getRequestURI() /day14/demo1
      *stringBuffer getRequestURL() http://localhost/day14/demo16
      string getProtocol()获取协议及版本:HTTP/1.1
      string getRemoteAddr() 获取客户机的IP地址

    2. 获取请求头数据
      方法∶
      *string getHeader(string name):通过请求头的名称获取请求头的值
      Enumeration<string> getHeaderNames():获取所有的请求头名称
      示例:

      @WebServlet("/ServletText02")
      public class ServletText02 extends HttpServlet {
       protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
        1,获取请求头 user-agent
        String agent = req.getHeader("user-agent");
        if(agent.contains("Chrome")){
                System.out.println("谷歌浏览器");
        }else if(agent.contains("Firefox")){
                System.out.println("火狐浏览器");
        }
        System.out.println("----------------------------------------------------");
        2,所有请求头名子
        Enumeration<String> headerNames = req.getHeaderNames();
        while (headerNames.hasMoreElements()){
                String headerName = headerNames.nextElement();
                //根据名称获取请求头值
                String header = req.getHeader(headerName);
                System.out.println(headerName+"---"+header);
        }
        System.out.println("=====================================================");
        3,获取请求头 referer  是从哪里访问
        String referer = req.getHeader("referer");
        System.out.println(referer);
        System.out.println("-----------");
      3,防盗链
        if(referer != null){
            if( referer.contains ("newServlet")){
            //正常访问
            response.setContentType( "text/htm1;charset=utf-8" );
            response.getWriter().write("播放电影...." );
        }else{
            //盗链
            response.setContentType( "text/html;charset=utf-8");
            response.getWriter().write("想看电影吗?来优酷吧...");
        }
      }
      }
      }
      
    3. 获取请求体数据:
      请求体∶只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
      步骤∶

      1. 获取流对象
        BufferedReader getReader():获取字符输入流,只能操作字符数据
        *servletInputstream getInputstream()∶获取字节输入流,可以操作所有类型数据【文件上传】
      2. 再从流对象中拿数据
      @WebServlet("/RequestText02")
      public class RequestText02 extends HttpServlet {
         protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
      1获取请求体
         1)获取字符输入流
         BufferedReader reader = req.getReader();
         String line=null;
         2)读取字符
         while((line=reader.readLine())!=null){     =>按行读取数据
             System.out.println(line);
         }
        }
      }
      
  2. 其他功能︰
    1. 获取请求参数通用方式
      string getParameter(String name) :根据参数名称获取参数值username=zs&password=123
      String[] getParametervalues(string name) :根据参数名称获取参数值的数组hobby=xx&hobby-game
      Enumeration<string> getParameterNames():获取所有请求的参数名称
      Map<String,string[]> getParameterMap():获取所有参数的map集合

      @WebServlet("/RequestText03")
      public class RequestText03 extends HttpServlet {
      protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
      获取请求参数通用方式
          1)通过参数名称获取参数值对应到页面的name值 适用于单个键值对
          String username = req.getParameter("username");
          //System.out.println(username);
          2)通过参数名获取参数值数据,复选框 数组
          String[] hobbies = req.getParameterValues("hobby");
              for (String hobby: hobbies) {
                  //System.out.println(hobby);
          }
          3)获取所有的参数名
          Enumeration<String> parameterNames = req.getParameterNames();
          while (parameterNames.hasMoreElements()){
          System.out.println(req.getParameter(parameterNames.nextElement()));
          }
          4)获取所有的参数名 map集合
          Map<String, String[]> parameterMap = req.getParameterMap();
          Set<String> keySet = parameterMap.keySet();    =>获取name【map的key[]】
          for (String name:keySet){
              System.out.println(name);
              String[] values = parameterMap.get(name);  =>获取每个name对应的值【通过map的key获取map的值values[]】
             for (String value:values){
                 System.out.println(value);
             }
              System.out.println("--------");
          }
      
      }
      
      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      this.doPost(request,response);    =>复用用dopost方法
      }
      }
      

      中文乱码问题:
      get方式:,tomcat 8 已经将get方式乱码问题解决了
      post方式会乱码
      解决∶在获取参数前,设置request的编码request.setcharacterEncoding("utf-8");

    2. 请求转发︰—种在服务器内部的资源跳转方式
      步骤︰
      1.通过request对象获取请求转发器对象︰RequestDispatcher getRequestDispatcher(String path)
      2.使用RequestDispatcher对象来进行转发∶forward(ServletRequest request,ServletResponse response)
      特点∶
      1.浏览器地址栏路径不发生变化。
      2.只能转发到当前服务器内部资源中。
      3.转发是一次请求。

    3. 共享数据
      域对象:一个有作用范围的对象,可以在范围内共享数据
      reauest域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
      方法:
      void setAttribute(string name,object obj):存储数据
      object getAttitude(string name):通过键获取值
      void removeAttribute(string name):通过键移除键值对

需求:
1.编写login.html登录页面
2.username & password 两个输入框
2.使用Druid数据库连接池技术,操作mysql, day14数据库中user表
4.使用JdbcTemplate技术封装JDBC
5.登录成功跳转到successservlet展示:登录成功!用户名,欢迎您
6.登录失败跳转到Failservlet展示:登录失败,用户名或密码错误


  3. 验证码:
  ```
   int width=100;
    int height=50;
    //1.创建—对象,在内存中图片(验证码图片对象)
    BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);

    //2.美化图片
    Graphics graphics = image.getGraphics();//画笔对象
    //填充粉红色
    graphics.setColor(Color.pink);//设置画笔颜色
    graphics.fillRect(0,0,width,height);//填充

    //蓝色边框
    graphics.setColor(Color.blue);
    graphics.drawRect(0,0,width-1,height-1);

    //写数字
    String str="ABCDEFGHIJKLMNOPQISCUVWSYZabcdefghijklmnopqiscuvwsyz0123456789";
    //生成随机角标
    Random rand = new Random();
    for (int i = 1; i <=4 ; i++) {
        int index = rand.nextInt(str.length());
        //获取随机字符
        char c = str.charAt(index);//随机字符
        graphics.drawString(c+"",width/5*i,height/2);
    }

    //4画干扰线
    graphics.setColor(Color.green);
    for (int i = 1; i <=10; i++) {
        int x1=rand.nextInt(width);
        int y1=rand.nextInt(height);
        int x2=rand.nextInt(width);
        int y2=rand.nextInt(height);
        graphics.drawLine(x1,y1,x2,y2);
    }


    //3.将图片输出到页面展示
    ImageIO.write(image,"jpg",response.getOutputStream());
  ```
  ```
  var randimg = document.getElementById("randImg");
  randimg.onclick=function(){
    var date=new Date().getTime();//时间戳,永远不会重复

    randimg.src="/newServlet/ServletResponseTest03?"+date
  }
  ```

//1.获取请求参数
            String filename = request.getParameter("filename");

            //2.使用字节输入流加载文件进内存
                //找到文件服务器路径
                ServletContext servletContext = this.getServletContext();
                //获取文件真实路径
                String realPath = servletContext.getRealPath("/img/" + filename);
                //使用字节流关联
                FileInputStream fils = new FileInputStream(realPath);

            //3.设置response的响应头
                //3.1设置响应头类型:content-type
                String mimeType = servletContext.getMimeType(filename);//获取文件的mime类型
                response.setHeader("content-type" ,mimeType);


        //解决中文文件名问题
        //1.获取user-agent请求头、
        String agent = request.getHeader( "user-agent");
        //2.使用工具类方法编码文件名即可
        filename = DownLoadUtils.getFileName(agent,filename);

        //3.2设置响应头打开方式: content-disposition
        response.setHeader("content-disposition","attachment;filename="+filename);

            //4.将输入流的数据写出到输出流中
            ServletOutputStream sos = response.getOutputStream();
            byte[] buff = new byte[ 1024* 8];//缓冲区
            int len = 0;//读到的个数
            while( ( len = fils.read(buff))!=-1){
                        sos.write( buff,0,len);
             }
             fils.close();
上一篇下一篇

猜你喜欢

热点阅读