javaWeb部分

使用eclipse将项目发布到tomcat都做了那些事呢?
  步骤1: eclipse 会把src中java文件编译成class文件, 放到 WebRoot/WEB-INF/classes 目录下.
  步骤2: eclipse将WebRoot 复制粘贴到tomcat/webapps目录下, 并且将 WebRoot 改名为 项目名(如test).

servlet容器: tomcat(java的web服务器)
  sun公司要求服务器,创建servlet的同时,再去创建一个servletConfig对象.    
  ServletConfig包含了一些Servlet的配置信息.再调用servlet的init方法时,将
servletCongfig传给servlet servletConfig的内容是 是自己定义的. 在web.xml中 的servlet标签下书写servletConfig的内容

        <servlet>
            <servlet-name>DemoServlet</servlet-name>
            <servlet-class>cn.itcast.web.DemoServlet</servlet-class>
            <init-param>
              <param-name>path2</param-name>
              <param-value>C:/a.png</param-value>
            </init-param>
          </servlet>
          <servlet-mapping>
            <servlet-name>DemoServlet</servlet-name>
            <url-pattern>/demo</url-pattern>
          </servlet-mapping>
            @Override
            public void init(ServletConfig config) throws ServletException {
                        String initParameter = config.getInitParameter("path2");
                        System.out.println(initParameter);
                        //获取所有的初始化参数的名称
                        Enumeration<String> names = config.getInitParameterNames();
                        while(names.hasMoreElements()){
                                    System.out.println(names.nextElement());
                        }
                        System.out.println(config.getServletContext());
                        System.out.println(config.getServletName());
            }

          private String path=null;
            @Override
            public void init(ServletConfig config) throws ServletException {
                        path = config.getInitParameter("path");
            }
            public void doGet(HttpServletRequest request, HttpServletResponse response)
                                    throws ServletException, IOException {
                        //String path="C:/a.png";
                        FileInputStream in = new FileInputStream(new File(path));
                        ServletOutputStream out = response.getOutputStream();
                        int len=-1;
                        byte[] buf=new byte[1024];
                        while((len=in.read(buf))!=-1){
                                    out.write(buf, 0, len);
                        }
                        in.close();
            }

ServletContext接口
场景:
  在线人数:xxx万,吸引用户来注册。
  当用户进入系统,应该当前在线人数加一——servlet处理
  当用户退出系统,应该当前在线人数减一——servlet处理
需求:
  有在线人数的数据,必须,可以让两个servlet都可以获取使用。
  希望:有这么一个容器(保存数据),这个容器可以被多个servlet同时使用。

这个就是我们ServletContext容器:
总结:
 1 容器可以存储数据
 2 操作容器set get remove
 3 可以被多个Servlet使用共享。
  当tomcat启动时,会为每个web应用创建一个唯一的ServletContext对象代表当前Web应用.该对象不仅封装了当前web应用的所有信息,而且实现了多个servlet的数据共享.
  在每个项目中可以有多个Servlet程序,每个Servlet程序都是独立的。Servlet中的配置信息可以使用ServletConfig获取,而当前这个项目的配置信息,就必须使用
描述这个项目的ServletContext对象获取。

<context-param>
    <param-name>shanghai</param-name>
    <param-value>传智播客</param-value>
  </context-param>
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                                    throws ServletException, IOException {
                        //获取servletContext容器,测试存取删操作
                        ServletContext context = this.getServletContext();
                        context.setAttribute("addr", "东莞");
                        String addr = (String) context.getAttribute("addr");
                        System.out.println(addr);
                        context.removeAttribute("addr");
                        String addr2 = (String) context.getAttribute("addr");
                        System.out.println(addr2);

                        //获取web.xml中context-param标签的配置参数(因为ServletContext所以的servlet都可以获取,这些数据是全局配置参数)
                        Enumeration<String> names = context.getInitParameterNames();
                        while(names.hasMoreElements()){
                                    String next = names.nextElement();
                                    System.out.println(next+":"+context.getInitParameter(next));
                        }
                        //读取当前项目中c3p0配置文件  "/":表示从当前项目查找
                        // eclipse中的项目,src文件夹下的内容,在发布到服务器之后,保存在WEB-INF/classes文件夹下
                        //C:\software\apache-tomcat-7.0.81\webapps\Day35_request\WEB-INF\classes\c3p0-config.xml
                        String realPath = context.getRealPath("/WEB-INF/classes/c3p0-config.xml");
                        FileInputStream in = new FileInputStream(new File(realPath));
                        ServletOutputStream out = response.getOutputStream();
                        int len=-1;
                        byte[] buf=new byte[1024];
                        while((len=in.read(buf))!=-1){
                                    out.write(buf, 0, len);
                        }
                        in.close();
            }

编码处理
  1 处理get请求乱码 String string = new String(parameter.getBytes(“iso-8859-1”),”utf-8”);
  2 处理post请求乱码 request.setCharacterEncoding(“utf-8”);

//发送响应
//1 在获取打印流之前先设置好编码
//response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("<h1>test servlet Ok</h1>");
//writer.write("<h1>访问Servlet程序成功!!!</h1>");


/**
 * ServletContext容器可以存取数据,可以被多个servlet共享
 * request容器存取数据,可以被多个servlet共享
 *
 * 研究区别:
 * 1 ServletContext 生存时间:从项目启动到项目的停止
 * 2 request对象 生存时间:从请求到达服务器开始一直到响应发送给浏览器,request对象就失效。
 *
 * 具体应用的时候:
 * request容器该保存什么样的数据?
 * 答:一次请求中需要使用的数据。例如:商品数据存入request容器。
 *
 * ServletContext容器该保存什么样的数据?
 * 答:保存整个项目需要访问的数据。例如:在线人数。
 */

总结:
  当一个Web资源收到客户端的请求后,如果希望服务器通知另外一个资源处理.
  可以通过 转发对象 RequestDispatcher 对象的forward(request,response)方法,将当前请求传递给其他的Web资源进行处理,这种方式称为请求转发。

BeanUtils的populate方法模拟

public class BeanUtils {
            public static void populate(Object o, Map map) {
                        //当前obj对象,需要封装数据,需要获取当前对象的成员变量
                        // 由于传入的数据,已经转换成Object类型,无法直接操作成员变量
                        // 通过反射的方式操作,获取成员变量:
                        Class clazz = o.getClass();
                        Field[] fields = clazz.getDeclaredFields();
                        // 通过反射给成员变量添加数据
                        try {
                                    for(Field f:fields){
                                                //打开非法访问——取消java语言的访问检查
                                                f.setAccessible(true);
                                                f.set(o, map.get(f.getName()));
                                    }
                        } catch (Exception e) {
                                    e.printStackTrace();
                        }
            }
}
            //需求:
            // 1 提供一个map集合,保存了用户的数据。
            // 2 将用户的数据从map集合中取出来,
            // 3 封装到指定的对象(Person)中。
            @Test
            public  void test1() {
                        Map map=new HashMap();
                        map.put("name", "老王");
                        map.put("age", 18);

                        Person p=new Person();
                        //将封装数据,交给其他对象(BeanUtils)去完成
                        BeanUtils.populate(p,map);
                        System.out.println(p);
            }

response

            public void doGet(HttpServletRequest request, HttpServletResponse response)
                                    throws ServletException, IOException {
                                    //response.setStatus(500);
                                    //response.setHeader("Refresh", "3;url=http://www.jd.com");

                                    //设置重定向
                                    //response.setStatus(302);
                                    //response.setHeader("Location", "http://www.jd.com");

                                    //response.sendRedirect("http://localhost:9090/day09/1.html");

                                    response.setContentType("text/html;charset=utf-8");
                                    response.getWriter().write("<h1>努力到无能为力 拼搏到感动自己</h1>");
            }

应用场景: 浏览器显示的内容, 下载文件等.
  response 以流的形式,将内容输出给浏览器
  response.getWriter() 获取响应体的字符输出流,输出页面的时候使用
  response.getOutputStream() 获取响应体的字节输出流,输出文件(图片,avi等。。。。)的时候使用
通过这两个流可以向浏览器输出 响应体内容.
注意问题:
  1 文件数据传输: getOutputStream 手动生成响应内容时 使用 getWriter
  2 getOutputStream 和 getWriter 相互排斥,不能同时使用,否则会冲突.
  3 tomcat会自动调用response输出流的 close方法和flush方法, 因此不需要我们手动关闭流.

        public void doGet(HttpServletRequest request, HttpServletResponse response)
                                    throws ServletException, IOException {
                        //1  获取请求参数(知道用户需要下载什么数据)
                        String parameter = request.getParameter("fileName");
                        String fileName = new String(parameter.getBytes("iso-8859-1"),"utf-8");
                        //2  服务器中加载用户需要下载资源
                        String realPath = getServletContext().getRealPath("/download");
                        File file = new File(realPath, fileName);

                        //响应消息头设置:
                        //Content-Type 设置文件媒体格式 .txt .mp3
                        response.setContentType(getServletContext().getMimeType(fileName));

                        String header = request.getHeader("User-Agent");
                        if(header.contains("Firefox")){
                                    //火狐下载文件名乱码处理:(先判断是否是火狐浏览器)
                                    BASE64Encoder base64Encoder = new BASE64Encoder();
                                    fileName = "=?utf-8?B?"       + base64Encoder.encode(fileName.getBytes("utf-8")) + "?=";
                        }else{
                                    //谷歌浏览器(和主流其他浏览器)中文乱码处理:
                                    fileName = URLEncoder.encode(fileName,"utf-8");
                        }
                        ///Content-Disposition  设置要被下载的文件名
                        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

                        //3  将数据发送给浏览器
                        FileInputStream in = new FileInputStream(file);
                        ServletOutputStream out = response.getOutputStream();
                        int len=-1;
                        byte[] b=new byte[1024];
                        while((len=in.read(b))!=-1){
                                    out.write(b, 0, len);
                        }
                        in.close();
            }

重定向和转发的区别:
  1 转发操作发生在服务器内部,重定向是浏览器执行操作
  2 转发地址栏不变,重定向,地址栏变化(记住)
  3 转发在一次请求中完成,重定向是两次请求(记住)
  4 转发可以在一次请求中共享数据,重定向不行。

问题1 :ServletContext的getContext(),getContextPath(),getRealPath() 以及HttpServletRequst的getContextPath(),getRequestURI() getRequestURL()
getServletPath() 这些方法获得路径有什么区别和联系

答:
ServletContext
  getContext() :获取指定路径的项目,它的ServletContext对象,但是,处于安全考虑,如果获取其他的项目ServletContext都会拿到null,所以方法不常用
  getContextPath():获取当前项目根路径
  getRealPath():获取当前项目中,指定资源的路径
HttpServletRequst:
  getContextPath():获取当前项目根路径(同上)
  getRequestURI(): 获取请求地址,不包含协议,地址,端口
  getRequestURL(): 获取请求地址,包含协议,地址,端口
问题2 :ServletContext 与Servlet的在服务器中存在形式被称为什么? 使用ServletContext会出现并发问题么?如何解决
  1 对象 ServletContext tomcat在底层的实现类是org.apache.catalina.core.ApplicationContextFacade,这是一个容器存取数据的
Servlet是处理请求和响应的对象,由我们自己实现
  2 ServletContext对象在存取数据的时候使用ConcurrentHashMap,线程安全。
三、servlet: 用于开发动态web资源的技术,如果java程序要向浏览器输出数据,必须完成两个步骤:
  1.创建一个java类,实现servlet接口。
  2.把java类部署到服务器中。Servlet程序是由web服务器调用的,服务器在收到客户端请求后,首先会检查是否创建了Servlet对象,否(创建Servlet对象,调用
init方法,创建封装请求的HttpServletRequeset对象和响应消息的HttpServletResponse对象,然后调用service方法将请求和响应做为参数传递),是(直接创建封装请求的HttpServletRequeset对象和响应消息的HttpServletResponse对象,然后调用service方法将请求和响应做为参数传递),web应用在停止会重新启动的时候,Servlet会调用destroy方法卸载Servlet。 servlet接口有两个默认实现类,GenericServlet,HttpServlet。HttpServlet能够处理HTTP请求的servlet,比
原有Servlet接口上添加了与HTTP协议的处理方法,所以在编写Servlet时,应继承这个类。HttpServelt在实现Servlet接口时,复写了service方法,会自动判断请
求方式,所以只要复写doGet和doPost方法就好。

四、ServletConfig: 获取Servlet的初始化参数。在Servlet配置文件中,可以用  标签为servlet配置初始化信息,当servlet配置了初始化参数时,web容器在创建servlet实例对象时,会自动将初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。所以
通过ServletConfig对象就可以活的当前servlet的初始化参数信息。

五、ServletContext(域对象):
  web容器(服务器)在启动时,会给每个web应用都创建一个ServletContext对象代表当前web应用,
封装了当前web应用的所有信息,而且一个web应用中的所有Servlet共享一个ServletContext对象。
所以Servlet对象之间可以通过ServletContext对象来实现通讯。

Cookie
  总结:session容器的获取全部依赖于cookie,服务器自动解析cookie,根据cookie中jsessionid,获取指定的容器对象。
  一般情况下,关闭浏览器之后,再次访问,是无法获取到Session中的数据的。
因此在服务器针对当前用户的第一次请求创建的唯一的Session容器对象,而在给这次请求的之后,服务器需要给用户响应数据,在响应的时候,服务器把当前Session容器对象的JSESSIONID以Cookie的形式发送给了浏览器。而这个Cookie并没有设置有效时间,那么这个Cookie就属于临时Cookie,在关闭浏览器之后,再次打开浏览器的时候,上次的Cookie已经消失了,用户虽然拿同一个浏览器访问服务器,可是这时没有JSESSIONID,服务器端的Session容器依然存在,但是没JSESSIONID,服务器内部无法获取到这个session对象把包含了JSESSIONID的Cookie在客户端持久化。

            public void doGet(HttpServletRequest request, HttpServletResponse response)
                                    throws ServletException, IOException {
                                    HttpSession session = request.getSession();
                                    System.out.println(session);
                                    Cookie cookie = new Cookie("JSESSIONID", session.getId());
                                    cookie.setMaxAge(60*60*24);
                                    cookie.setPath("/Day37_Cookie");
                                    response.addCookie(cookie);
            }

jsp技术最终还是用java类,执行网页内容,jsp说到底还是一个Servlet

<body>
            <!-- html注释 -->
            <!--
                                    html注释无法对java代码起作用
                                    java自己的注释,会原封不动翻译到.java文件

                         -->
            <!-- java注释 -->
            <% //int i=0;%>
            <%-- JSP注释:只能在jsp源文件中才能看到 --%>
                        <%--
                                    总结:html注释 在html源码中
                                        java注释在java源码中
                                        jsp注释在jsp源码中

                                    问题:什么时候使用哪一种注释?
                                    答:希望在那种源文件中看到注释,就使用相同的技术。
                         --%>
            <%=session %>>
</body>

JSP的内置对象&动作标签介绍
  什么是内置对象:在jsp中能直接使用的对象就是jsp的内置对象。(request response session exception)
内置对象在哪里?
  Jsp底层实际上还是一个java类,可以在jsp中直接使用的,必然存在在jsp翻译后的java类中
JSP的内置对象9个:
  这9个内置对象,已经掌握5个,可以在JSP翻译之后的对应的Java源代码的service方法中找到:
HttpServletRequest request
请求

HttpServletResponse response
响应

HttpSession session session
会话

ServletContext application
表示当前项目对象

ServletConfig config
专门获取当前这个Servlet的配置信息

新接触的:(要学习的部分)
Object page = this
它的表示是当前那个JSP页面对象。

PageContext pageContext
它表示的是当前jsp页面的上下文对象 作用:它的主要功能就是可以获取到JSP页面上的其他八个内置对象

Throwable exception
主要是保存JSP页面上的异常信息的对象

JspWriter out
它相当于我们在Servlet中使用的response.getWriter

问题:为什么数据保存在page容器中,只能在当前jsp页面使用?
  Page对象定义在——_JspService()方法中,当方法进栈的时候,对象创建可以存取数据,当方法出栈的时候,page对象也随之消失,所以page中存放的数据只能在当前页面使用。
  理解:因为page对象定义在_JSPService方法中,当方法执行完成之后,所有的局部变量都消失,所在page对象中保存的数据,只能在当前的jsp中使用。
  
Page容器中,应该存什么样的数据?
  只在当前页面使用的数据,就应该存在page容器中。
例子:页面使用java代码做循环,比如:i<6,这样的6这个数据,不会再其他页面使用,那么就存入page容器。

总结:web中的四个域对象(容器对象)范围比较从小到大依次为:
  Page(当前页面) (当前项目的根路径) < request(一次请求)(商品) < session(一次会话,多次请求)(昵称) < ServletContext(整个项目)在线人数

补充:为什么request比page范围大?
  Request.getrequestdispather(“/index.jsp”).forward(request,response);获取转发器之后,可以将存入请求对象的数据转发到index.jsp这个页面上。Request中存贮的数据,可以跨越一个servlet和一个jsp,因为page中存贮数据,只能在当前页面使用。

简单总结:一次请求,不止一个页面,一次会话,不止一次请求。
工作的时候:不用page的方法,使用PageContext对象来操作page。

pageContext使用
作用:
1. 获取其他八个内置对象(9个)
2. 向四个web容器(page request session application )设置数据
3. 向四个web容器(page request session application )获取数据

 <%=pageContext.getException() %><br/>
 <%=pageContext.getOut() %><br/>
 <%=pageContext.getRequest() %><br/>
 <%=pageContext.getResponse() %><br/>
 <%=pageContext.getServletConfig() %><br/>
 <%=pageContext.getServletContext() %><br/>
 <%=pageContext.getSession() %><br/>
 <%=pageContext.getPage() %><br/>

<%=pageContext.APPLICATION_SCOPE %><br/>    4
<%=pageContext.SESSION_SCOPE %><br/>    3
<%=pageContext.REQUEST_SCOPE %><br/>    2
<%=pageContext.PAGE_SCOPE %>    1

一、JSP的内置对象(也叫隐含对象)是指不需要预先声明就可以在脚本代码和脚本表达式中使用的对象,一共有9个。
按照它们的作用域可以分为四类:
  1.作用域为Page(页面执行期):response、pageContext、out、config、page、exception
  2.作用域为Request(用户当次请求):request
  3.作用域为Session(当次会话):session

二、域对象的作用为:保存数据、获取数据、共享数据
  1.page域对象中的数据只能在当前用户请求的JSP页面中使用。只要页面跳转了,page中的数据就不见了。
  2.request域对象中的数据有效范围是当前请求周期。在这个周期中可能使用forward方式跳转了多个JSP页面,在这些页面中都可以使用这个变量。
  3.seesion域对象中的数据的有效范围是当前会话
  4.application域对象中的数据有效范围是整个Web应用。这些数据会一直保存到服务器关闭。

EL表达式
  需求:需要一种新的jsp页面使用java代码的方式,方便直接输出内容。
  EL全称:Expression Language
  作用:代替jsp中脚本表达式的功能,简化对java代码的操作。

EL要学习内容:
  获取数据(获取四个容器中数据)
  执行运算(EL执行运算)
  快速操作常用的javaweb对象(11个内置对象)

EL表达式
  在JSP中提供了EL表达式,可以快速的从web容器(page、request、session、ServletContext)中取出数据。
  
EL表达式的格式:
keyrequest.setAtttribute(username,zhangsan): 在 域 中 保 存 的 数 据 的 k e y 值 r e q u e s t . s e t A t t t r i b u t e ( “ u s e r n a m e ” , ” z h a n g s a n ” ) 如 : {requestScope.username}
相当于 request.getAttribute(“username”)

<!-- 演示获取四个容器中的数据 -->
<%
pageContext.setAttribute("name", "林志玲",pageContext.APPLICATION_SCOPE);
pageContext.setAttribute("name", "林志颖",pageContext.SESSION_SCOPE);
pageContext.setAttribute("name", "林正英",pageContext.REQUEST_SCOPE);
pageContext.setAttribute("name", "林心如",pageContext.PAGE_SCOPE);
%>
${pageScope.name}<br/>
${requestScope.name}<br/>
${sessionScope.name}<br/>
${applicationScope.name}<br/>
<hr/>
${name}<br/>

<body>
<%--获取请求参数 --%>
${param}<br>
${paramValues}<br>
${paramValues.hobby[1] }
<hr/>
<%--获取请求头 --%>
${header }<br><br>
${headerValues }<br><br>
<hr/>
<%--
${cookie }        cookie数组
${cookie.cookie的名称 }        cookie对象
${cookie.JSESSIONID.name } 获取cookie的名称
${cookie.JSESSIONID.value } 获取cookie的值
--%>
${cookie }<br>
${cookie.JSESSIONID.name }<br>
${cookie.JSESSIONID.value }<br>
<hr/>
<%--pageContext获取的是JSP的八个内置对象 不管是EL内置对象的pageContext还是jsp的内置对象pageContext都是获取jsp的其他八个内置对象 --%>
${pageContext.request.contextPath}
<hr/>
${initParam.sh}
</body>

EL的11个内置对象使用
其中大家已经掌握的:
 pageScope
 requestScope
 sessionScope
 applicationScope

param
 获取用户提交的请求参数
 测试代码: param cookie cookiecookie < p a r a m   c o o k i e   它 获 取 到 的 一 个 c o o k i e 数 组 , 获 取 所 有 的 c o o k i e 数 据   测 试 代 码 : < {cookie }获取了cookie数组,如果获取数组中的指定cookie,使用点名称的方式获取 –%>
cookie c o o k i e {cookie.JSESSIONID.name }
${cookie.JSESSIONID.value }

pageContext
 它就和JSP内置对象pageContext功能一致(获取其他内置对象:jsp的内置对象)
 测试代码:<%– 使用pageContext,获取了 request,调用request对象的方法–%>
 ${pageContext.request.contextPath}

  细节:使用pageContext的getAttribute方法或者findAttribute方法从4个容器中取出数据的时候,如果指定的key不存在会得到null,而使用el表达式取出的时候指定的key不存在,页面上什么都没有

<body>
            <%--
                        test属性值为true 执行标签体中的内容 false:不执行
                        var属性:保存了test属性执行结果
                        scope:指定var属性数据保存的容器
             --%>
            <c:if test="${true }"  var="mm" scope="session">
                        测试if标签 test==false pageScope:${pageScope.mm }| sessionScope:${sessionScope.mm }
            </c:if>

            <%--
                        var:${mm }
             --%>
</body>
<body>
            <%--
                        set演示保存数据
                        int i = 0;
                        var:声明一个变量名称(int i)
                        value:给var属性声明的变量赋值
                        set标签保存数据,默认是存在page容器中。        
                        scope:指定数据保存的容器
            --%>
            <c:set var="root" value="${pageContext.request.contextPath }" scope="session"></c:set>
            pageScope:${pageScope.root }<br/>
            sessionScope:${sessionScope.root }

            <hr/>
            <%--
            set演示修改数据
            target:目标 靶子
 --%>

 <%
            Person p=new Person();
            pageContext.setAttribute("p",p);
 %>
            ${p }
            <c:set target="${p }" property="name" value="黑马警长"></c:set>
            ${p }
</body>

JavaBean介绍
  JavaBean:它是一个简单的Java类。属性要求是private 这个类中拥有get或set方法即可,但要求这个类必须有一个公开的空参数的构造函数。

特点:
  1、一定要有一个无参数的构造函数—public 无参的构造函数
  2、属性必须是 private的。
  3、为这个私有的属性,提供公有的访问方法getter ,setter。

JavaWeb中的过滤器是什么呢?
Filter接口:功能——对请求和响应进行增强,或者进行拦截。

        @Override
        public void init(FilterConfig config) throws ServletException {
                    System.out.println("getInitParameter:"+config.getInitParameter("sh"));//获取初始化参数
                    System.out.println("getFilterName:"+config.getFilterName());//获取过滤器名称
                    Enumeration<String> names = config.getInitParameterNames();
                    while(names.hasMoreElements()){
                                String next = names.nextElement();
                                System.out.println(next);//获取初始化参数
                    }
                    System.out.println("getServletContext:"+config.getServletContext());//获取上下文
        }

servlet生命周期:
生:第一次调用servlet程序初始化(执行一次)
死:服务器关闭

Cookie生命周期:
生:new Cookie(“username”,”tom”)

Session:
生:第一次调用getSession方法,默认访问jsp
死:默认30分钟自动死亡,服务器强制关闭,调用session的invalidate()方法

Filter:
创建:在服务器启动的时候

补充(装饰(包装)设计模式口诀):

1. 定义一个类,实现被装饰对象的接口
2. 定义一个成员变量,记住被装饰对象的引用
3. 定义构造方法,传入被装饰对象的实例
4. 改写要修改的方法
5. 不需要改写的方法,调用被装饰对象的原来的方法
public class MyRequest extends HttpServletRequestWrapper{
            private HttpServletRequest request;
            private boolean flag=false;
            public MyRequest(HttpServletRequest request) {
                        super(request);
                        this.request=request;
            }
            @Override
            public Map<String, String[]> getParameterMap() {
                        String method = request.getMethod();
                        if("post".equalsIgnoreCase(method)){
                                    try {
                                                request.setCharacterEncoding("utf-8");
                                                return request.getParameterMap();
                                    } catch (UnsupportedEncodingException e) {
                                                e.printStackTrace();
                                                return super.getParameterMap();
                                    }
                        }else if("get".equalsIgnoreCase(method)){
                                    //将所有的请求参数获取出来,然后,一个一个地处理乱码
                                    Map<String, String[]> map = request.getParameterMap();
                                    if(flag){
                                                return map;
                                    }
                                    if(map!=null){
                                                for(String key:map.keySet()){
                                                            String[] strings = map.get(key);
                                                            for(int i=0;i<strings.length;i++){
                                                                        try {
                                                                                    String string = new String(strings[i].getBytes("iso-8859-1"), "utf-8");
                                                                                    strings[i]=string;
                                                                        } catch (UnsupportedEncodingException e) {
                                                                                    e.printStackTrace();
                                                                                    //如果出异常,希望后边,还没有循环到的数据,继续处理乱码
                                                                                    //结束当前循环,开启下一个循环
                                                                                    continue;
                                                                        }
                                                            }
                                                }
                                    }
                                    flag=true;
                                    return map;
                        }else{
                                    return super.getParameterMap();
                        }
            }
            @Override
            public String[] getParameterValues(String name) {
                        Map<String, String[]> map = this.getParameterMap();
                        if(map!=null){
                                    String[] values = map.get(name);
                                    return values;
                        }
                        return super.getParameterValues(name);
            }
            @Override
            public String getParameter(String name) {
                        String[] values = this.getParameterValues(name);
                        if(values!=null){
                                    return values[0];
                        }
                        return super.getParameter(name);
            }
}

javaweb监听器介绍
  JavaWEB中的监听器主要监听JavaWEB中的request、session、ServletContext对象的各种变化(创建和销毁、保存的数据)。
  Javaweb中事件源(request、session、ServletContext)

监听request、ServletContext 、session对象的创建和销毁 (练习)
  ServletRequestListener
  ServletContextListener
HttpSessionListener

监听request、session、ServletContext 对象存放的数据变化情况(练习)
  ServletContextAttributeListener
  HttpSessionAttributeListener
ServletRequestAttributeListener

监听session中保存的JavaBean的状态
HttpSessionBindingListener

public void contextInitialized(ServletContextEvent servletContextEvent) {
                        System.out.println("contextInitialized。。。");
//                    Timer timer=new Timer();
//                    timer.schedule(new TimerTask() {
//                                @Override
//                                public void run() {
//                                            String localeString = new Date().toLocaleString();
//                                            System.out.println(localeString);
//                                }
//                    }, 5000, 1000);
                        //初始化在线人数
                        ServletContext context = servletContextEvent.getServletContext();
                        context.setAttribute("onLineNumber", 0);
            }

public void sessionCreated(HttpSessionEvent httpSessionEvent)  {
         System.out.println("sessionCreated。。。");
         //创建session的时候在线人数增加1
         ServletContext context = httpSessionEvent.getSession().getServletContext();
         Integer num = (Integer) context .getAttribute("onLineNumber");
         context.setAttribute("onLineNumber", num+1);
    }
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent)  {
         System.out.println("sessionDestroyed。。。");
       //创建session的时候在线人数减少1
         ServletContext context = httpSessionEvent.getSession().getServletContext();
         Integer num = (Integer) context .getAttribute("onLineNumber");
         context.setAttribute("onLineNumber", num-1);
    }

Session中的bean(JavaBean)监听
  需求:当我们给Session中保存一个Java对象(JavaBean)的时候,或者把Java对象从Session中移除的时候会触发专门用来监听Session中对象变化的监听器中的方法。拥有这个方法的对象——HttpSessionBindingListener接口

属性监听和bean监听的区别:
  属性监听:是对三个容器中的任何属性(包括对象和不是对象的数据,基本类型数据)的变化,进行监听
  Bean监听:它只监听javabean对象往session中保存和session中移出的过程。

  注意:当服务器加载项目的时候,会读取web.xml文件中listener标签,那么服务器会自动创建监听器对象,并且自动调用其方法
自动调用其方法,也是通过反射调用(因为他的方法名称和参数是固定的)
监听器的小结:

1. 创建一个类,实现监听器接口
2. 在监听器对象的方法中,书写相关的代码
3. 在web.xml中配置当前监听器。
public class BaseServlet extends HttpServlet {
            @Override
            protected void service(HttpServletRequest req, HttpServletResponse resp)
                                    throws ServletException, IOException {
                        String methodName = req.getParameter("methodName");
                        try {
                                    Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
                                    method.invoke(this, req,resp);
                        } catch (Exception e) {
                                    e.printStackTrace();
                        }
            }
}


            public static String getDir(String fileName) {
                        //根据文件的名称计算文件路径
                        int hashCode = fileName.hashCode();
                        /**
                         * int hashCode 0000 0101 0101 0101 0101 0101 1111 1111
                         *                          &0000 0000 0000 0000 0000 0000 0000 1111
                         *           ------------------------------------------------------------------------------
                         *                           0000 0000 0000 0000 0000 0000 0000 1111
                         *                0000 0101 0101 0101 0101 0101 1101 1111
                         *             &0000 0000 0000 0000 0000 0000 0000 1111
                         *             --------------------------------------------------------------------------
                         *                                             0000 0000 0000 0000 0000 0000 0000 1101
                         * 每4个位获取一个数字,获取到8个数字,每个数字都作为文件目录
                         * 每个数字有16个变化——16^8个变化
                         *
                         * */
                        int dir1 = hashCode & 15;
                        hashCode = hashCode >> 4;
                        int dir2 = hashCode & 15;
                        return "/"+dir1+"/"+dir2;
            }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值