Servlet各种核心类详解

      1、Servlet的参数配置

       1.Servlet的参数可以在web.xml中通过init-param元素来配置

       2.参数的读取需要借助ServletConfig对象(该对象由容器创建)

       3.每一个Servlet都有对应的ServletConfig对象,彼此间不共享

      2、可能出现的线程安全问题

       由于Servlet对象在内存中有一个,所有定义Servlet的实例变量,在用户访问时会有线程竞争问题。

       解决办法:

       1.同步处理。(不建议使用)

       2.搞出多个Servlet实例。(不建议使用)

       SingleThreadModel接口:如果某个Servlet实现了该接口,容器有可能会采用1或2的方式来应对。(不同服务器实现不同)

       Tomcat是采取了2方案。废弃的接口     

       3、原则:尽量把变量定义为局部变量。对于没法定义为局部变量的变量,应做同步处理,但同步代码块应尽可能的小。

      3、ServletConfig

       使用ServletConfig可以获取WEB-INF 配置文件init-param里面的值(非全局,只能获取当前Servlet里面的配置数据);

     1.获取指定参数名字的值

    //注意:init-param只能放在servlet-class配置标签后面

       String value = getServletConfig().getInitParameter("ppp"); 

    2.获取所有参数名字

       //获取顺序:按自然排序获取名字

        Enumeration names=   getServletConfig()

        .getInitParameterNames();

       while(names.hasMoreElements()){

           String name =(String) names.nextElement();

       }

   

      4、ServletContext

       1、ServletContext概念

           应用活多长,ServletContext对象就活多长(生命周期)

           容器在加载应用时就会创建ServletContext对象,它代表当前JavaWeb应用(全局)

           本身是一个域对象:该对象内部维护了一个Map(域对象)

                     访问域对象数据的方法:

                     ObjectgetAttribute(String name):通过名称获取对象。

                     voidsetAttribute(String name,Object obj):忘Map中塞一个对象。name在                           Map中不存在是添加,存在是替换

                     voidremove(String name)

                     getAttributeNames():获取Map中的所有key值

       2、作用

              1、实现各个Servlet间的数据共享。(数据共享)

              2、获取应用的全局参数配置(参数配置)

                     在web.xml里面配置

                           

                                   encoding

                                   UTF-8

                           

           3、 从web-xml配置文件中获得值的方法:

       //这个getServletContext方法在GenericServlet

       String value = getServletContext().getInitParameter("name");

      5、三种读取配置文件的方式

              1、ServletContextgetRealPath(Stringpath):根据path获取绝对路径。path必须以/         开始,相对于当前应用的绝对路径

                     特点:用户JavaWeb环境下,JavaWeb环境下可以读取到当前应用中的任何资        源。

              2、ResourceBundle:构造实例时,传入基名。(国际化的类)

                     特点:可以用在非web环境下,只能读取properties的资源文件;只能加载类         路径下的资源文件;

              3、ClassLoader

                     特点:可以用在非web环境下,只能加载类路径下的资源文件;读取类路径                 下的所有资源文件。

 

具体实例代码:

1.ServletContext读取类路径下的property资源文件      

       

       Stringpath = getServletContext().getRealPath

         ("/WEB-INF/classes/com/itheima/servlet/db11.properties");

       Properties pro = new Properties();

       pro.load(new FileInputStream(path));

       String value = pro.getProperty("url");

 

2.ResourceBundle读取资源文件

    //注意ResourceBundel的路径,没有/,没有后缀名,因为他知道是Properties文件,

    //并且把Properties当成类的读取方式来读取(如果有包,包名用.分隔),具体如下

       ResourceBundle rb = ResourceBundle.getBundle

        ("com.itheima.servlet.db11");

       String value = rb.getString("url");

   

3.用类加载器的URL类读取资源文件

 

       ClassLoader cl = MyServlet3.class.getClassLoader();

       //以相对路径的方法来读取文件

       //如果路径中有空格,tomcat就会把空格翻译为%20,就会出错,这就是为什么安装  

        //时为什么不能有空格路径

       URL url = cl.getResource

        ("com/itheima/servlet/db11.properties");

       //urlgetPath方法获取的是绝对路径

       String path = url.getPath();

       Properties pro = new Properties();

       pro.load(new FileInputStream(path));

       String value = pro.getProperty("url");

 

4.用类加载器的getResourceAsStream方法读取资源文件(获取资源的比较常用的方法)

   

       ClassLoader cl = MyServlet3.class.getClassLoader();

       //调用ResourceAsStream(以流的形式拿出资源);

       InputStream fis = cl.getResourceAsStream

        ("com/itheima/servlet/db11.properties");

       Properties pro = new Properties();

       pro.load(fis);

        String value = pro.getProperty("url");

   

6、HttpServletResponse

  字节流输出中文数据的乱码问题

       使用response.getOutputStream()获得字节流。

       sendRedirect是在httpServletResponse这个接口定义的,不是在ServletResponse定义的

       字节流以UTF-8编码输出中文数据getBytes("UTF-8"),而浏览器用默认编码(GBK)解码,这时就会有乱码

 解决:

       1.浏览器选择“查看”菜单选择UTF-8,解决乱码问题。(不可取)

       2.指示浏览器查看码表.response.setHeader("Content-Type","text/html;charset=UTF-8");

       3.向客户端收到的html内容中增加标记:

       4.发送时用Reponse. setCharacterEncoding(“utf-8”)

       5、调用response.setContentType("text/html;charset=UTF-8"):告知客户端使用的编码

Tips: GBK包含ascll

 

7、Servlet的字符流输出

           获取Servlet字符输出流方法response.getWriter():

           Servlet的字符输出流输出时查的码表为iso-8859-1Servlet规范指定的)

        字符流和字节流互斥。在同一个Servlet中,只能用其中的一个流。

         容器会自动关闭response开启的流。

       字符流乱码解决办法:

     两步:

              1.设置输出字符数据时查的码表:response.setCharacterEncoding(“utf-8”)

              2.通知客户端以什么码表进行解码。

         response.setHeader(“Content-type”,”text/html;charset=utf-8”)

 

              response.setContentType("text/html;charset=UTF-8")能提供上述两步功能(字符流)。

       所以使用字符流时调用setContentType()方法能轻松解决乱码问题

8、HttpServletRequest

1.常用的方法

 

 request.getRequestURL()//获取请求url地址:http://localhost:8080/day05/servlet/RequestDemo1

 request.getRequestURI()//获取请求的资源地址:/day05/servlet/RequestDemo1

 request.getQueryString()//get方式的数据:username=admin&password=123

 request.getRemoteAddr()//客户端的IP地址

 request.getRemoteHost()//客户端的主机名称

 request.getRemotePort()//客户端的端口号 1024~65535之间的任意一个没有被占用的端口

 request.getMethod()//请求方式:get或post

 request.getContextPath()// 当前应用的名称   /day05

 2.获取请求头的值

  //获取所有的请求头名称和值

       privatevoid test3(HttpServletRequest request, HttpServletResponse response)

                     throwsServletException, IOException {

              Enumeration enumers = request.getHeaderNames();

              while(enumers.hasMoreElements()){

                     StringheaderName = (String)enumers.nextElement();

                     System.out.println(headerName+"="+request.getHeader(headerName));

              }

       }

 //获取重名头的值

       privatevoid test2(HttpServletRequest request, HttpServletResponse response)

                     throwsServletException, IOException {

              Enumerationenumers = request.getHeaders("Accept-Encoding");

              while(enumers.hasMoreElements()){

                     Stringvalue = (String)enumers.nextElement();

                     System.out.println(value);

              }

       }

//获取单一的头

       privatevoid test1(HttpServletRequest request, HttpServletResponse response)

                     throwsServletException, IOException {

              String value =request.getHeader("Accept-Encoding");

              System.out.println(value);

       }

3.获取正文所有内容

       //方法:请求的输入流

       OutputStream out = response.getOutputStream();

       InputStream is = request.getInputStream();

       int length = -1;

       byte[] by =new byte[1024];

       while((length=is.read(by))!=-1){

           out.write(by,0,length);

    }

4.封装javaBean

    //将页面数据封装到JavaBean:利用BeanUtils框架(需要jar)

 

       User user = new User();

        //注意事项!这里的mapvalue值是String[]类型,因为同一个名字可以有多个值

       Map map = request.getParameterMap();

       BeanUtils.populate(user, map);

   

    //将页面数据封装到JavaBean中(第一种)

       User user = new User();

       //获得页面所有属性的名字

       Enumeration names = request.getParameterNames();

       while(names.hasMoreElements()){

           String name =names.nextElement();

            String value =request.getParameter(name);

           //获得属性描述器,内省

           PropertyDescriptorpd =  new      

            PropertyDescriptor(name,User.class);

           Method method = pd.getWriteMethod();

           method.invoke(user, value);

       }

    //将页面数据封装到JavaBean(第二种)

       User user = new User();

       //获取页面所有属性的Map

       Map map = request.getParameterMap();

        //注意事项!这里的mapvalue值是String[]类型,因为同一个名字可以有多个值

       for(Map.Entry entry:map.entrySet()){

           String name = entry.getKey();

           String[] value = entry.getValue();

           PropertyDescriptor pd = new

             PropertyDescriptor(name,User.class);

           Method method = pd.getWriteMethod();

           method.invoke(user, value);

 

       }

9、指示浏览器下载图片案例

doGet(){

       //获取图片绝对路径

       String path = getServletContext().getRealPath("/美女.jpg");

       //获取图片名绝对路径名称:G:xxx\xxx\美女.jpg

       String name = path.substring(path.lastIndexOf("\\")+1);

       FileInputStream fis = new FileInputStream(path);

        //如果显示图片,就需要设置Content-Typeapplication/octet-stream

       response.setHeader("Content-Type","application/octet-stream");

 

    响应消息头要遵循html的规则,必须把不安全的东西重新编码(加密变成安全字符集里面

的字符),因为中文也为不安全的字符集,所以就需要使用URLEncoder类把String类型变成application/x-www-form-urlencoded(表单默认类型,安全字符集),如果不重新编码,就会有中文乱码问题

    下载文件是浏览器会自动帮你对安全字符集解码

 

       response.setHeader

       ("Content-Disposition","attachment;filename="

        +URLEncoder.encode(name),"utf-8"));

       int length = - 1;

       byte[] b =new byte[1024];

        while((length =fis.read(b))!=-1){

           response.getOutputStream().write(b,0,length);

         }

        }

你可能感兴趣的:(servlet,string,properties,classloader,user)