zoukankan      html  css  js  c++  java
  • Java Web开发总结(一)

    1、如何解决 tomcat 中文乱码问题?

    2、如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet

     <!-- 将ServletDemo2配置成缺省Servlet -->
      <servlet-mapping>
        <servlet-name>ServletDemo2</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>

     3、Servlet 线程安全:当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。

        3.1通过ServletContext获取web资源的绝对路径

        String path = this.getServletContext().getRealPath("/WEB-INF/classes/db/config/db3.properties");

    4、ServletContext对象

           WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用
      ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象。
      由于同一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象

    
    
    ServletContext context = this.getServletConfig().getServletContext();//获得ServletContext对象
    context.setAttribute("data", data);  //将data存储到ServletContext对象
    在另一个 servlet 中:
    
    
    String data = (String) context.getAttribute("data");//从ServletContext对象中取出数据
    
    

    5、获取WEB应用的初始化参数

    在web.xml文件中使用<context-param>标签配置WEB应用的初始化参数
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
        <display-name></display-name>
        <!-- 配置WEB应用的初始化参数 -->
        <context-param>
            <param-name>url</param-name>
            <param-value>jdbc:mysql://localhost:3306/test</param-value>
        </context-param>
        <welcome-file-list>
            <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
    </web-app>

     

    servlet 中 获取Web应用的初始化参数:

    
    
    ServletContext context = this.getServletContext();
    //获取整个web站点的初始化参数
    String contextInitParam = context.getInitParameter("url");
    
    

    6、页面跳转  用servletContext实现请求转发

    (6.1)Request对象实现请求转发

            A、通过 ServletContext 的 getRequestDispatcher(String path)方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发。 

    
    
    ServletContext context = this.getServletContext();//获取ServletContext对象
    RequestDispatcher rd = context.getRequestDispatcher("/servlet/ServletContextDemo5");//获取请求转发对象(RequestDispatcher)
    rd.forward(request, response);//调用forward方法实现请求转发
     
    RequestDispatcher reqDispatcher =this.getServletContext().getRequestDispatcher("/test.jsp");
    reqDispatcher.forward(request, response);
    
    

        B:2、通过request 对象提供的 getRequestDispatche(String path)方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发。

    request.getRequestDispatcher("/test.jsp").forward(request, response);
    <body>
          使用普通方式取出存储在request对象中的数据:
          <h3 style="color:red;"><%=(String)request.getAttribute("data")%></h3>
         使用EL表达式取出存储在request对象中的数据:
         <h3 style="color:red;">${data}</h3>
      </body>

     2、通过response实现请求重定向

     /**
             * 1.调用sendRedirect方法实现请求重定向,
             * sendRedirect方法内部调用了
             * response.setHeader("Location", "/JavaWeb_HttpServletResponse_Study_20140615/index.jsp");
             * response.setStatus(HttpServletResponse.SC_FOUND);//设置302状态码,等同于response.setStatus(302);
             */
            response.sendRedirect("/JavaWeb_HttpServletResponse_Study_20140615/index.jsp");
            
            //2.使用response设置302状态码和设置location响应头实现重定向实现请求重定向
            //response.setHeader("Location", "/JavaWeb_HttpServletResponse_Study_20140615/index.jsp");
            //response.setStatus(HttpServletResponse.SC_FOUND);//设置302状态码,等同于response.setStatus(302);
    
    

     7、利用ServletContext对象读取资源文件

    注意:通过类装载器读取资源文件的注意事项:不适合装载大文件,否则会导致jvm内存溢出
    (1.1)使用类装载器读取资源文件【用类装载器读取src目录下的db1.properties配置文件】
      private void readPropFile(HttpServletResponse response) throws IOException {
            //获取到装载当前类的类装载器
            ClassLoader loader = ServletContextDemo7.class.getClassLoader();
            //用类装载器读取src目录下的db1.properties配置文件
            InputStream in = loader.getResourceAsStream("db1.properties");
            Properties prop = new Properties();
            prop.load(in);
            String driver = prop.getProperty("driver");
            String url = prop.getProperty("url");
            String username = prop.getProperty("username");
            String password = prop.getProperty("password");
            response.getWriter().println("用类装载器读取src目录下的db1.properties配置文件:");
            response.getWriter().println(
                    MessageFormat.format(
                            "driver={0},url={1},username={2},password={3}", 
                            driver,url, username, password));
        }

     (1.2)读取类路径下面、包下面的资源文件

    //获取到装载当前类的类装载器
            ClassLoader loader = ServletContextDemo7.class.getClassLoader();
            //用类装载器读取src目录下的gacl.servlet.study包中的db4.properties配置文件
            InputStream in = loader.getResourceAsStream("gacl/servlet/study/db4.properties");
            Properties prop = new Properties();
            prop.load(in);
            String driver = prop.getProperty("driver");
            String url = prop.getProperty("url");
            String username = prop.getProperty("username");
            String password = prop.getProperty("password");
            response.getWriter().println("用类装载器读取src目录下的gacl.servlet.study包中的db4.properties配置文件:");
            response.getWriter().println(
                    MessageFormat.format(
                            "driver={0},url={1},username={2},password={3}", 
                            driver,url, username, password));
        }

     

    (2)//读取src目录下的db.config包中的配置文件
     /**
         * 通过ServletContext对象读取src目录下的properties配置文件
         * @param response
         * @throws IOException
         */
        private void readSrcDirPropCfgFile(HttpServletResponse response) throws IOException {
            /**
             * 通过ServletContext对象读取src目录下的db1.properties配置文件
             */
            InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db1.properties");
            Properties prop = new Properties();
            prop.load(in);
            String driver = prop.getProperty("driver");
            String url = prop.getProperty("url");
            String username = prop.getProperty("username");
            String password = prop.getProperty("password");
            response.getWriter().println("读取src目录下的db1.properties配置文件:");
            response.getWriter().println(
                    MessageFormat.format(
                            "driver={0},url={1},username={2},password={3}", 
                            driver,url, username, password));
        }

     

    (3)读取 src 下某个包中的配置文件【读取src目录下的gacl.servlet.study包中的db4.properties配置文件】
    private void readPropCfgFile2(HttpServletResponse response)
                throws IOException {
            InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/gacl/servlet/study/db4.properties");
            Properties prop = new Properties();
            prop.load(in);
            String driver = prop.getProperty("driver");
            String url = prop.getProperty("url");
            String username = prop.getProperty("username");
            String password = prop.getProperty("password");
            response.getWriter().println("读取src目录下的gacl.servlet.study包中的db4.properties配置文件:");
            response.getWriter().println(
                    MessageFormat.format(
                            "driver={0},url={1},username={2},password={3}", 
                            driver,url, username, password));
        }
    
    

     (4)读取src目录下的db.config包中的db3.properties配置文件

    //通过ServletContext获取web资源的绝对路径
            String path = this.getServletContext().getRealPath("/WEB-INF/classes/db/config/db3.properties");
            InputStream in = new FileInputStream(path);
            Properties prop = new Properties();
            prop.load(in);
            String driver = prop.getProperty("driver");
            String url = prop.getProperty("url");
            String username = prop.getProperty("username");
            String password = prop.getProperty("password");
            response.getWriter().println("读取src目录下的db.config包中的db3.properties配置文件:");
            response.getWriter().println(
                    MessageFormat.format(
                            "driver={0},url={1},username={2},password={3}", 
                            driver,url, username, password));
        }
    
    

     (5)通过ServletContext对象读取WebRoot目录下的properties配置文件

     /**
             * 通过ServletContext对象读取WebRoot目录下的properties配置文件
             * “/”代表的是项目根目录
             */
    InputStream in = this.getServletContext().getResourceAsStream("/db2.properties"); Properties prop = new Properties(); prop.load(in); String driver = prop.getProperty("driver"); String url = prop.getProperty("url"); String username = prop.getProperty("username"); String password = prop.getProperty("password"); response.getWriter().println("读取WebRoot目录下的db2.properties配置文件:"); response.getWriter().print( MessageFormat.format( "driver={0},url={1},username={2},password={3}", driver,url, username, password)); }

     8、向浏览器输出中文数据

    (1)response.getOutputStream() :得到输出 二进制数据 的 ServletOuputStream对象。

    (2)response.getWriter()方法:得到、输出文本数据Printwriter对象。

    (3)getOutputStream 和 getWriter这两个方法 互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。  

    (4)Servlet 程序向 ServletOutputStream 或 PrintWriter 对象中写入的数据将被Servlet引擎从 response 里面获取,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端。 

    (5)Serlvet 的 service方法结束后,Servlet引擎将检查 getWriter 或 getOutputStream 方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象。

    (8.1)以浏览器输出 binary data,字节流方式,需使用  OutputStream

    在服务器端,数据是以哪个码表输出的,那么就要控制客户端浏览器以相应的码表打开。

    比如:outputStream.write("中国".getBytes("UTF-8"));其意思是:使用OutputStream流向客户端浏览器输出中文,以UTF-8的编码进行输出;此时就要控制客户端浏览器以UTF-8的编码打开,否则显示的时候就会出现中文乱码。

    那么在服务器端如何控制客户端浏览器以以UTF-8的编码显示数据呢?

    (1)可以通过设置响应头控制浏览器的行为,例如:response.setHeader("content-type", "text/html;charset=UTF-8");其意思是:通过设置响应头控制浏览器以UTF-8的编码显示数据。

    String data = "中国";
    OutputStream outputStream = response.getOutputStream();//获取OutputStream输出流
    //通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码
    response.setHeader("content-type", "text/html;charset=UTF-8");
    byte[] dataByteArr = data.getBytes("UTF-8");//将字符转换成字节数组,指定以UTF-8编码进行转换
        /**
             * data.getBytes()是一个将字符转换成字节数组的过程,这个过程中一定会去查码表,
             * 如果是中文的操作系统环境,默认就是查找查GB2312的码表,
             * 将字符转换成字节数组的过程就是将中文字符转换成GB2312的码表上对应的数字
             * 比如: "中"在GB2312的码表上对应的数字是98
             *         "国"在GB2312的码表上对应的数字是99
             */
            /**
    //getBytes()方法如果不带参数,那么就会根据操作系统的语言环境来选择转换码表,如果是中文操作系统,那么就使用GB2312的码表
    outputStream.write(dataByteArr);//使用OutputStream流向客户端输出字节数组

    (8.2)使用PrintWriter流向客户端浏览器输出中文数据,字符流方式, character text

          使用PrintWriter流输出中文注意问题:

      在获取PrintWriter输出流之前 首先使用 "response.setCharacterEncoding(charset)" 设置字符以什么样的编码输出到浏览器

    如:response.setCharacterEncoding("UTF-8");设置将字符以"UTF-8"编码输出到客户端浏览器,

    然后再使用 response.getWriter(); 获取PrintWriter输出流,这两个步骤不能颠倒,如下:

    response.setCharacterEncoding("UTF-8");//设置将字符以"UTF-8"编码输出到客户端浏览器
    /**
    * PrintWriter out = response.getWriter();这句代码必须放在response.setCharacterEncoding("UTF-8");之后
    * 否则response.setCharacterEncoding("UTF-8")这行代码的设置将无效,浏览器显示的时候还是乱码
    */
    PrintWriter out = response.getWriter();//获取PrintWriter输出流

    然后再使用 response.setHeader("content-type", "text/html;charset=字符编码");设置响应头,控制浏览器以指定的字符编码编码进行显示,例如:

    response.setHeader("content-type", "text/html;charset=UTF-8");
    //通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码
    /**
    * 多学一招:使用HTML语言里面的<meta>标签来控制浏览器行为,模拟通过设置响应头控制浏览器行为
     *response.getWriter().write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>");
    * 等同于response.setHeader("content-type", "text/html;charset=UTF-8");
    */
    response.getWriter().write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>");

    具体实例:

    public void outputChineseByPrintWriter(HttpServletResponse response) throws IOException{
            String data = "中国";
            
            //通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码
            //response.setHeader("content-type", "text/html;charset=UTF-8");
            
            response.setCharacterEncoding("UTF-8");//设置将字符以"UTF-8"编码输出到客户端浏览器
            /**
             * PrintWriter out = response.getWriter();这句代码必须放在response.setCharacterEncoding("UTF-8");之后
             * 否则response.setCharacterEncoding("UTF-8")这行代码的设置将无效,浏览器显示的时候还是乱码
             */
            PrintWriter out = response.getWriter();//获取PrintWriter输出流
            /**
             * 多学一招:使用HTML语言里面的<meta>标签来控制浏览器行为,模拟通过设置响应头控制浏览器行为
             * out.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>");
             * 等同于response.setHeader("content-type", "text/html;charset=UTF-8");
             */
            out.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'/>");
            out.write(data);//使用PrintWriter流向客户端输出字符
        }
        
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
        }
    }

     9、response 文件下载

    文件下载功能是web开发中经常使用到的功能,使用HttpServletResponse对象就可以实现文件的下载

    文件下载功能的实现思路:

    1.   获取要下载的文件的绝对路径
    2.   获取要下载的文件名
    3.   设置 content-disposition 响应头控制浏览器以下载的形式打开文件
    4.   获取要下载的文件输入流
    5.   创建数据缓冲区
    6.   通过 response 对象获取 OutputStream 流
    7.   将 FileInputStream 流写入到 buffer 缓冲区
    8.   使用 OutputStream 将缓冲区的数据输出到客户端浏览器
      /**
           * 下载文件,通过OutputStream流
           * @param response
           * @throws FileNotFoundException
           * @throws IOException
           */
          private void downloadFileByOutputStream(HttpServletResponse response)
                  throws FileNotFoundException, IOException {
              //1.获取要下载的文件的绝对路径
              String realPath = this.getServletContext().getRealPath("/download/1.JPG");
              //2.获取要下载的文件名
              String fileName = realPath.substring(realPath.lastIndexOf("\")+1);
              //3.设置content-disposition响应头控制浏览器以下载的形式打开文件
              response.setHeader("content-disposition", "attachment;filename="+fileName);
      //需要注意的地方就是中文文件名要使用URLEncoder.encode方法进行编码(URLEncoder.encode(fileName, "字符编码")),否则会出现文件名乱码。
              response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));
      //4.获取要下载的文件输入流 InputStream in = new FileInputStream(realPath); int len = 0; //5.创建数据缓冲区 byte[] buffer = new byte[1024]; //6.通过response对象获取OutputStream流 OutputStream out = response.getOutputStream(); //7.将FileInputStream流写入到buffer缓冲区 while ((len = in.read(buffer)) > 0) { //8.使用OutputStream将缓冲区的数据输出到客户端浏览器 out.write(buffer,0,len); } in.close(); }
  • 相关阅读:
    emlog6.0代码审计
    Linux系统
    PHP反序列化链挖掘
    Yii框架反序列化RCE利用链分析
    CVE-2020-1472漏洞复现
    linux 报错 Input/output error
    SKimage
    layui 统计行totalRow 保留两位小数
    linux清空历史命令(history)
    shred 命令详解
  • 原文地址:https://www.cnblogs.com/quietwalk/p/8609162.html
Copyright © 2011-2022 走看看