Servlet-JSP相关

来源:互联网 发布:唐嫣演技知乎 编辑:程序博客网 时间:2024/06/07 19:03
EL表达式    EL 全名为Expression Language , EL表达式语言    目的:        使用EL 和 JSTL 取代jsp中的脚本 --> jsp页面中没有java代码(底层还需要执行相应的java代码)    作用:        获得域中的数据        执行运算        获得web开发常用对象        调用java对象方法    格式:${el表达式}        注意:如果数据不存在,将返回空字符串""    EL内置对象(11个)        作用域:pageScope 、requestScope、sessionScope、applicationScope            示例:${requestScope.属性名}            注意:如果没有显示说明从哪个作用域取,则底层调用pageContext.findAttribute(name)方法.从小到大取        JSP上下文对象:pageContext            示例:<%((HttpServletRequest)pageContext.getRequest()).getContextPath()%>                el:${pageContext.request.contextPath}        请求参数:            param.name      --> request.getParameter(name)            paramValues.name    -->request.getParameterValues(name)        请求头信息:            header.name     --> request.getHeader(name)            headerValues.name   --> request.getHeaders(name)        获得cookie : cookie            获得指定cookie名称的值:${cookie.cookie名称.value}        web项目的初始化参数:            initParam.name --> servletContext.getInitParameter(name)    访问集合        访问List中的元素: list[0]        访问Map中的元素: map.key 或 map['key']    运算符        算术运算符 + - / % (5/2=2.5)        关系运算符 == != < <= > >=  (可以用对应英文缩写表示 eq ne lt le gt ge)        逻辑运算符 && || !  (非也可以用not)        其他            empty 表示是否为空 (null , "" , size()==0)  ${empty 变量名}            ${表达式 ? true : false}    三目运算符    注意        访问属性eWaiJiFen时,要写 对象.EWaiJiFen自定义标签库(了解)    概述        在jsp中书写自定义标签,在生成java代码时要被指定java代码替换,底层还是java代码        要关联自定义标签和替换的java代码,需要有配置文件(tld文件)    步骤        编写实现类            传统标签:必须实现Tag接口  --> 继承实现类 TagSupport ,如果需要标签体 继承BodyTagSupport (了解)            简单标签:必须实现SimpleTag接口 --> 继承实现类 SimpleTagSupport(源码tomcat中有)        编写配置文件 tld        使用            引入标签库 taglib            使用:<前缀:标签名称>    tld文件        标签库描述符(taglib description)        tld文件基于xml文件 ,扩展名为tld,但内容是xml        存放位置            1 WEB-INF目录下,但classes和lib目录除外            2 WEB-INF/lib目录下的jar文件中的META-INF目录下        tomcat将自动加载tld文件    示例(自定义foreach标签,用来遍历集合)        编写实现类            package tagImpl;            import java.io.IOException;            import java.util.ArrayList;            import javax.servlet.jsp.JspException;            import javax.servlet.jsp.PageContext;            import javax.servlet.jsp.tagext.SimpleTagSupport;            public class MyTagImpl extends SimpleTagSupport{                //页面的属性必须对应一个set方法                ArrayList<String> list;                String item;                public void setList(ArrayList<String> list){                    this.list=list;                }                public void setItem(String item){                    this.item=item;                }                public void doTag() throws JspException,IOException{                    PageContext page=(PageContext)this.getJspContext();                    for(String str : list){                        page.setAttribute(item, str);//存入page作用域,方便页面取出                        this.getJspBody().invoke(page.getOut());//把标签体中的内容输出到浏览器                    }                }            }        编写tld文件(位置:WEB-INF目录,名称任意)            <?xml version="1.0" encoding="UTF-8" ?>            <taglib 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-jsptaglibrary_2_1.xsd"                version="2.1">                <!-- 版本 -->                   <tlib-version>1.0</tlib-version>                <!-- 建议前缀 -->                <short-name>s</short-name>                <!-- 引用此文件的标识 -->                <uri>http://localhost:8080/demo/tagImpl/MyTagImpl</uri>                                <!-- 定义标签 -->                <tag>                    <!-- 标签名称 -->                    <name>foreach</name>                    <!-- 标签的实现类 -->                    <tag-class>tagImpl.MyTagImpl</tag-class>                    <!-- 标签体                        取值:                            JSP:不会用                            empty:空,没有标签体                            scriptless:支持EL表达式,不支持jsp脚本                            tagdependent:不会用                    -->                    <body-content>scriptless</body-content>                    <!-- 标签的属性 -->                    <attribute>                        <!-- 属性名称 -->                        <name>list</name>                        <!-- 是否是必须的 -->                        <required>true</required>                        <!-- 是否支持运行时表达式(EL) -->                        <rtexprvalue>true</rtexprvalue>                    </attribute>                    <attribute>                        <!-- 属性名称 -->                        <name>item</name>                        <!-- 是否是必须的 -->                        <required>true</required>                        <!-- 是否支持运行时表达式(EL) -->                        <rtexprvalue>true</rtexprvalue>                    </attribute>                </tag>            </taglib>        使用            在页面引用标签库                 <%@ taglib uri="http://localhost:8080/demo/tagImpl/MyTagImpl" prefix="s"%>            在页面使用标签                <s:foreach list="${list}" item="i">                    ${i}<br>                </s:foreach>    自定义标签细节(其实是自定义标签的生命周期)        1 父类SimpleTagSupport会缓存PageContext对象。可以PageContext page=(PageContext)this.getJspContext();获取jsp上下文对象        2 通过标签的属性attribute进行数据的传递,实现类需要提供相应的属性property的setter方法接受传递的数据        3 缓存了标签体,类型是JspFragment(代码片段),可以通过this.getJspBody()获得标签体.            可以执行invoke将标签体的内容输出到指定流中this.getJspBody().invoke(page.getOut());如果invoke参数为null,则默认输出到浏览器        4 doTag()方法,定义自定义标签功能的方法            如果在doTag标签体中,throw new SkipPageException(),表示当前标签执行之后,页面之后的内容将不输出。自定义函数库(了解)    概述        在jsp中使用 ${fn:函数名(参数...)} 执行固定的java方法完成操作        要关联固定的java代码,需要有配置文件(tld文件)    示例        编写自定义类,类中编写要调用的方法,必须是静态的,例:            package function;            public class MyFunction {                public static String join(String i,String j){                    return i + "/" + j;                }            }        编写tld文件(位置:WEB-INF目录,名称任意)            <?xml version="1.0" encoding="UTF-8" ?>            <taglib xmlns="http://java.sun.com/xml/ns/j2ee"              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"              xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"              version="2.0">                              <tlib-version>1.0</tlib-version>              <short-name>myfn</short-name>              <uri>http://localhost:8080/myFunctionTag/myFunction</uri>              <function>                <!-- 使用时的名称 -->                <name>join</name>                <!-- 对应的类 -->                <function-class>function.MyFunction</function-class>                <!-- 函数签名 -->                <function-signature>java.lang.String join(java.lang.String ,java.lang.String)</function-signature>              </function>            </taglib>        使用            引入标签库                <%@ taglib uri="http://localhost:8080/myFunctionTag/myFunction" prefix="myfn" %>            调用                ${myfn:join("q","w")}JSTL    JavaServer Pages Standard Tag Library, JSP标准标签库。    第三方实现apache        导入jar包(/jstl/)            jstl.jar            --> myeclipse自动添加的jar名称javax.servlet.jsp.jstl.jar            standard.jar        --> myeclipse自动添加的jar名称jstl-impl.jar        注意:myeclipse已经提供了相应的jar,并在将web项目发布到tomcat时,自动的将两个jar添加到web/WEB-INF/lib目录中    JSTL提供5种 标签库        核心库 : http://java.sun.com/jsp/jstl/core ,默认前缀:c        函数库 : http://java.sun.com/jsp/jstl/functions ,默认前缀:fn        国际化标签库,数据库标签库,XML标签库    核心库        先引入标签库            <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>        域操作            <c:set> 给指定作用域设置属性                var         属性的名称                value       属性的值                scope       作用域(page/request/session/application)                例:<c:set var="名称" value="值" scope="page"></c:set>            <c:remove/> 移除属性                var         要移除的属性的名称                scope       作用域,默认移除所有域中的指定名称的数据(page/request/session/application)                例:<c:remove var="username" />            <c:out> 向页面输出内容(可以进行html或js转义)                value       要输出的内容,支持EL表达式                escapeXml   是否进行标签内容转义(如:html代码在页面中原样输出,还是解析为html代码)默认为true                例:<c:out value="${username}"></c:out>        逻辑操作            <c:if> 相当于java中的if                test        判断条件                例:<c:if test="${empty username}">如果是真则输出</c:if>                注意:没有<c:else>            <c:choose> 相当于java中的switch                test        条件                子标签<c:when> 相当于java中的case                子标签<c:otherwise> 相当于java中的default                例:                    <c:choose>                        <c:when test="${param.num<10}">                            num小于10                        </c:when>                        <c:when test="${param.num<20}">                            num大于等于10且小于20                        </c:when>                        <c:otherwise>                            num大于等于20                        </c:otherwise>                    </c:choose>        循环操作            <c:forEach> 循环                items       需要遍历的数据,支持EL表达式                var         循环时每一项数据存放的变量名称,可以从域中获取当前项.只能在标签体内使用                begin       循环初始值                end         循环结束值                例:                    遍历集合或数组                        <c:forEach items="${list}" var="obj">                            ${obj} <br/>                        </c:forEach>                    遍历Map                        <c:forEach items="${map}" var="entry">                            ${entry.key} --> ${entry.value} <br/>                        </c:forEach>                    指定范围的循环                        <c:forEach begin="1" end="9" var="i">                            ${i} <br/>                        </c:forEach>                    注:访问对象的属性,就是调用对象的get方法        其它常用操作            <c:url> 将url添加项目名称后添加到域中                var         添加域中的属性的名称                value       要添加到域中的url                子标签<c:param> 给url后添加参数,此标签在<c:url>标签体中使用                    name        参数名称                    value       参数值,可以自动进行中文编码(base64)                例:                    <c:url var="oneURL" value="/oneServlet">                        <c:param name="username" value="sss"></c:param>                    </c:url>            <c:redirect> 重定向                url     要重定向的url,特别注意:当以/开头时不需要加项目名称                例:<c:redirect url="/index.jsp"></c:redirect>    函数库        先引入标签库            <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>        用法:            ${fn:函数名(参数...)}        包含了一下处理字符串的常用方法JSP模式    模式1 : JSP + JavaBean        小型项目,开发速度快。不好处扩展差,不易维护    模式2 : JSP + Servlet + JavaBean (推荐)        模式2 基于MVC思想MVC设计模式    MVC 软件设计模式,思想:一种分离业务逻辑与显示界面的设计方法 (业务逻辑 与 显示页面 相分离)    模块        Model模型 , 负责管理程序的业务数据        View视图 ,负责显示界面        Controller控制器 ,负责与用户进行交互(接收请求和选择响应视图)经典三层体系架构    在程序业务更加复杂的时候,会将Controller控制层继续划分为三层.        表示层(web层)        业务逻辑层(service层)        数据访问层(dao层)监听器Listener    servlet 三种技术 : servlet,listener(监听器),filter(过滤器)    web提供8接口,分别对ServletContext、HttpSession、ServletRequest 对象自身、属性(域)进行监听        域对象自身(3个)            ServletContextListener ,对ServletContext对象进行监听 (对象创建,与对象销毁)            HttpSessionListener ,对HttpSession对象进行监听 (对象创建,与对象销毁)            ServletRequestListener ,对ServletRequest对象进行监听 (对象创建,与对象销毁)            以上三个监听器,都提供了事件对象 xxxEvent,获得被监听对象。            需要在web.xml文件中进行注册。tomcat自动触发响应的方法。        域内容(对象属性)(3个)            ServletContextAttributeListener  对ServletContext属性进行监听 (属性添加,移除,替换)            HttpSessionAttributeListener 对HttpSession属性进行监听  (属性添加,移除,替换)            ServletRequestAttributeListener 对ServletRequest属性进行监听 (属性添加,移除,替换)            需要在web.xml文件中进行注册。tomcat自动触发响应的方法。        session中javabean(2个)            HttpSessionBindingListener : 对实现此接口的javabean在session域中的状态进行监听(绑定状态)                valueBound(HttpSessionBindingEvent event) ,当javabean对象添加到session属性触发此方法 (绑定)                void valueUnbound(HttpSessionBindingEvent event) ,当javabean对象从session属性移除时,触发此方法 (取消绑定)                应该以被监听的javaBean继承此接口,并且不需要再web.xml中注册            HttpSessionActivationListener : 对实现此接口的javabean在session域中的状态进行监听(持久化状态)                void sessionDidActivate(HttpSessionEvent se) ,在服务器启动时,如果已经钝化了javabean,则将javabean重新加载进内存。(活化 :硬盘 --> 内存 )                void sessionWillPassivate(HttpSessionEvent se) ,如果javabean在session中,当服务器正常关闭时,进行持久化此对象。(钝化 : 内存 --> 硬盘)                钝化时数据保持位置:%tomcat%\work\Catalina\localhost\day14_listener\SESSIONS.ser                应该以被监听的javaBean继承此接口,并且不需要在web.xml中注册                javabean必须实现java.io.Serializable接口        注册监听器(web.xml)            <listener>                <listener-class>类的完全限定名</listener-class>            </listener>        HttpSessionAttributeListener 和 HttpSessionBindingListener 区别:            HttpSessionAttributeListener ,对所有javabean生效            HttpSessionBindingListener ,对实现了此接口javabean生效            对同一件事的监听角度不同,一个从session角度进行监听,一个从javaBean角度进行监听国际化(i18n)    程序的界面可以支持多国语言。 internationalization ,i18n    国际化资源文件        文件名称:baseName_语言_国家|地区.properties            baseName,基名,自定义            后面的语言和国家不能乱写,可参见IE浏览器的internet选项-->常规-->语言 中的选项            例如:                message_zh_CN.properties ,简体中文                message_zh_TW.properties ,繁体中文                message_en.properties ,英语                message.properties ,默认配置文件        默认位置:src,ResourcBundle.getBundle("baseName");        Locale 对象表示了特定的地理、政治和文化地区            Locale(String language, String country) 指定 语言,国家|地区                例如 new Locale("zh", "CN")    使用时        文本            ResourceBundle.getBundle("message" ,request.getLocale()); 对资源文件进行解析,可以指定 Locale对象设置不同的语言            getString("usernameMsg") 获得指定名称的对象        数字            数字 NumberFormat.getNumberInstance(request.getLocale()).format(double)            百分比 NumberFormat.getPercentInstance(request.getLocale()).format(double)            货币 NumberFormat.getCurrencyInstance(request.getLocale()).format(double)        日期时间            DateFormat.getDateTimeInstance ,处理日期时间            DateFormat.getDateInstance  处理日期            DateFormat.getTimeInstance  处理时间            样式:FULL 、LONG 、MEDIUM (默认) 、 SHORT        消息格式化            MessageFormat.format ,将字符串中{n}进行内容自动的填充。    示例        在src下添加message_zh_CN.properties            usernameMsg=用户名            passwordMsg=密码        在src下添加message_en.properties            usernameMsg=username            passwordMsg=password        jsp页面            <%                ResourceBundle bundle = ResourcBundle.getBundle("message",request.getLocale());            %>            <%=bundle.getString("usernameMsg") %> : <input name="username"/> <br/>            <%=bundle.getString("passwordMsg") %> : <input type="password" name="password"/>        在IE浏览器的internet选项-->常规-->语言 中选择不同的语言,则网页显示效果不同过滤器Filter    对tomcat的请求会优先由过滤器进行处理    编写流程        1 编写实现类 ,实现Filter接口 (javax.servlet.Fitler)        2 在web.xml配置            格式                <filter>                    <filter-name>随便起个名,注意不要重复,一般为类名</filter-name>                    <filter-class>实现类的全限定名称</filter-class>                </filter>                <filter-mapping>                    <filter-name>上面的filter-name</filter-name>                    <url-pattern>/*</url-pattern>                    <!-- <dispatcher>request</dispatcher> -->                </filter-mapping>            注意                <url-pattern>和servlet的<url-pattern>用法相同,可参加<Servlet访问路径配置>                url-pattern和dispatcher标签可以有多个Filter接口(javax.servlet)    所有过滤器需要实现的父接口    方法        void init(FilterConfig filterConfig) 初始化        void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 过滤到请求时执行的方法        void destroy() 销毁    注意 chain.doFilter(request,response);为放行过滤器的生命周期    init ,初始化        时间:tomcat启动时。只要注册了过滤器,则tomcat就进行实例化        参数:            FilterConfig,当前过滤器配置对象                getFilterName() ,获得过滤器配置的名称<filter-name>的值                getInitParameter(java.lang.String name) 获得指定名称,过滤器初始化参数的值                getInitParameterNames() 获得所有的初始化参数的名称                getServletContext() 获得servlet的上下文对象    doFilter ,过滤执行        时间:接收到请求时。        参数:            FilterChain对象 过滤器链对象                服务器tomcat将所有符合要求的过滤器生成了一个链。                过滤器使用 FilterChain 调用链中的下一个过滤器,如果调用的过滤器是链中的最后一个过滤器,则调用链末尾的资源。                 方法                     void doFilter(ServletRequest request, ServletResponse response) 放行                注意:                    过滤器链中的所有过滤器的顺序,取决于web.xml配置文件<filter-mapping>配置顺序                    tomcat6.0 web.xml文件中<filter> 必须在<filter-mapping>之前    destroy,销毁        时间:服务器正常关闭时配置Filter的初始化参数    在web.xml中<filter>中的<filter-class>后添加<init-param>    例:        <filter>            <filter-name>            <filter-class>            <init-param>                <param-name>参数名</param-name>                <param-value>参数值</param-value>            </init-param>        </filter>dispatcher标签(过滤器的过滤类型)    位置:<filter-mapping>中的末尾    作用:设置当前过滤器的过滤类型    取值:        REQUEST,request : 对请求进行过滤(默认)        FORWARD,forward : 在进行请求转发时进行过滤        INCLUDE,include : 在进行包含操作时进行过滤        ERROR,error : 当页面出现错误,执行友好页面(web.xml <error-page>)时进行过滤        ASYNC,async :异步,Servlet3.0提供,用servlet3.0新技术异步时进行过滤。    注意        取值为FORWARD,INCLUDE,ERROR时,url-pattern应该写要转发到的页面或要包含的页面的url        当取值为ERROR时,可以不能看到自定义的错误页面,而是浏览器的错误页面.可在过滤器放行前将状态码设置为200(先强转).例:response.setStatus(200);过滤器案例    处理中文乱码(post)        添加过滤器,<url-pattern>为/*        在过滤器的doFilter方法放行前设置            request.setCharacterEncoding("utf-8");            response.setContentType("text/html;charset=UTF-8");    设置图片缓存时间        http响应提供三个头,进行页面缓存设置            pragma : no-cache            cache-control : no-cache            expires : 0         添加过滤器,<url-pattern>为*.jpg        在过滤器的doFilter方法放行前设置             response.setDateHeader("expires",System.currentTimeMillis() + 60 * 60 * 1000 * 24 * 30L); //一个月,加L是为了防止溢出处理中文乱码工具类    思想:        对request的getParameter和getParameterMap方法进行增强,在其中处理get中文乱码.然后将增强后的自定义request对象传递给servlet        tomcat提供了HttpServletRequestWrapper作为HttpServletRequest接口的装饰类,无任何增强的方法,供编程人员使用    代码:           package filter;        import java.io.IOException;        import java.io.UnsupportedEncodingException;        import java.util.HashMap;        import java.util.Map;        import javax.servlet.Filter;        import javax.servlet.FilterChain;        import javax.servlet.FilterConfig;        import javax.servlet.ServletException;        import javax.servlet.ServletRequest;        import javax.servlet.ServletResponse;        import javax.servlet.http.HttpServletRequest;        import javax.servlet.http.HttpServletRequestWrapper;        import javax.servlet.http.HttpServletResponse;        public class EncodingFilter implements Filter {            public void init(FilterConfig filterConfig) throws ServletException {            }            public void doFilter(ServletRequest req, ServletResponse res,                    FilterChain chain) throws IOException, ServletException {                //强转                HttpServletRequest request = (HttpServletRequest) req;                HttpServletResponse response = (HttpServletResponse) res;                //处理post请求乱码                request.setCharacterEncoding("utf-8");                //实例化自己的类(装饰者模式,增强了request的getParameter和getParameterMap方法,处理get请求乱码)                MyRequest myRequest = new MyRequest(request);                //放行                chain.doFilter(myRequest, response);//传递自己的类对象            }            public void destroy() {                            }        }        /**         * 自定义的用于增强tomcat的request对象的类         * @author Administrator         * HttpServletRequestWrapper为HttpServletRequest接口的装饰类,不过无任何增强的方法,供编程人员使用         */        class MyRequest extends HttpServletRequestWrapper{            public MyRequest(HttpServletRequest request) {                super(request);//父类缓存起来了            }            //增强方法            public String getParameter(String name){                //获取原来的值                String value = super.getParameter(name);                if(value == null){                    return null;                }                //对get请求乱码问题处理                if(super.getMethod().equalsIgnoreCase("get")){                    //get请求                    try {                        value = new String(value.getBytes("ISO8859-1"),super.getRequest().getCharacterEncoding());                    } catch (UnsupportedEncodingException e) {                        throw new RuntimeException(e);                    }                }                return value;            }            public Map<String, String[]> getParameterMap(){                Map<String,String[]> map = super.getParameterMap();                try {                    if(super.getMethod().equalsIgnoreCase("get")){                        Map<String,String[]> map2 = new HashMap<String,String[]>();                        for(String key : map.keySet()){                            String[] value = map.get(key);                            for(int i=0;i<value.length;i++){                                value[i] = new String(value[i].getBytes("ISO8859-1"),super.getCharacterEncoding());                            }                            map2.put(key, value);                        }                        map = map2;                    }                } catch (Exception e) {                    e.printStackTrace();                }                return map;            }        }    web.xml配置        <filter>            <filter-name>EncodingFilter</filter-name>            <filter-class>filter.EncodingFilter</filter-class>        </filter>        <filter-mapping>            <filter-name>EncodingFilter</filter-name>            <url-pattern>/*</url-pattern>        </filter-mapping>页面静态化    原因        每次请求会查询数据库,动态生成静态网页,速度很慢.对于一些固定的或访问量很大,很少更新的页面,可以使用静态页面    思想        首次访问Servlet将数据保存为静态html页面(而不是发送到浏览器),然后将html页面发送到浏览器.以后的访问不用查询数据库,直接返回第一次访问生成的html页面        Servlet(JSP)的响应内容默认通过request.getWriter方法输出到浏览器,增强response的getWriter方法修改目标输出位置        tomcat提供了HttpServletResponseWrapper作为Response接口的装饰类,无任何增强的方法,供编程人员使用    代码        package web.filter;        import java.io.File;        import java.io.FileOutputStream;        import java.io.IOException;        import java.io.OutputStreamWriter;        import java.io.PrintWriter;        import javax.servlet.Filter;        import javax.servlet.FilterChain;        import javax.servlet.FilterConfig;        import javax.servlet.ServletException;        import javax.servlet.ServletRequest;        import javax.servlet.ServletResponse;        import javax.servlet.http.HttpServletRequest;        import javax.servlet.http.HttpServletResponse;        import javax.servlet.http.HttpServletResponseWrapper;        public class PageStaticFilter implements Filter {            public void init(FilterConfig filterConfig) throws ServletException {            }            public void doFilter(ServletRequest req, ServletResponse res,                    FilterChain chain) throws IOException, ServletException {                //强转                HttpServletRequest request = (HttpServletRequest) req;                HttpServletResponse response = (HttpServletResponse) res;                //获取文件名(这里根据自己的需求写)                String id = request.getParameter("id");                String fileName = "/html/" + id + ".html";                //获取全路径                String filePath = request.getSession().getServletContext().getRealPath(fileName);                //判断文件是否存在                File htmlFile = new File(filePath);                if(!htmlFile.exists()){                    //不存在                    MyResponse myResponse = new MyResponse(response,htmlFile);                    //放行                    chain.doFilter(request, myResponse);//通过增强方法,会将数据保存为静态页面                }                //将文件发送给浏览器                request.getRequestDispatcher(fileName).forward(request, response);            }            public void destroy() {            }        }        /**         * 自定义的response类,修改getWriter方法的功能         * @author Administrator         * HttpServletResponseWrapper为tomcat的Response对象的装饰类,没有修改任何方法,供开发人员使用         */        class MyResponse extends HttpServletResponseWrapper{            private File htmlFile;//缓存的文件            PrintWriter writer;//缓存的打印流            public MyResponse(HttpServletResponse response,File htmlFile) {                super(response);                this.htmlFile = htmlFile;            }            //增强方法(将目的地改为指定文件)            public PrintWriter getWriter() throws IOException {                //此方法会调用两次,第一次tomcat获得流用来输出,第二次tomcat获得流是为了关闭流                if(writer == null){                    //第一次调用,实例化打印流                    String encoding = super.getResponse().getCharacterEncoding();//编码                    OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(htmlFile),encoding);//转换流                    writer = new PrintWriter(out);//此类编码为操作系统默认编码,要使用转换流指定编码,否则将出现乱码                }                return writer;            }        }    web.xml配置        <filter>            <filter-name>PageStaticFilter</filter-name>            <filter-class>web.filter.PageStaticFilter</filter-class>        </filter>        <filter-mapping>            <filter-name>PageStaticFilter</filter-name>            <url-pattern>路径自己写,某个servlet</url-pattern>        </filter-mapping>javamail    应用场景        注册账号时,进行账号激活        邮件订阅        生日祝福    名词        邮件服务器:安装有接收邮件、发送邮件功能的软件的计算机。        电子邮箱email:邮件服务器上申请的账号。    协议        SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,发送邮件服务器称为SMTP服务器,默认端口号:25        POP3(Post Office Protocol 3)即邮局协议,接收邮件服务器称为POP3服务器。默认端口:110        IMAP(Internet Mail Access Protocol)交互邮件访问协议,接收邮件服务器。默认端口:143            与POP3协议的主要区别是用户可以不用把所有的邮件全部下载,可以通过客户端直接对服务器上的邮件进行操作    发送邮件过程        xxx@163.com 发送到 xxx@126.com            首先发送到163邮件服务器的SMTP发送端,然后发送到126邮件服务器的SMTP发送端,并保存.            当用户读取时,通过126邮件服务器的POP3接收端读取邮件,返回给用户    手动发送邮件示例        命令行            telnet smtp.163.com 25      --连接163邮件服务器的smtp发送端(一般都为smtp.服务器.com)            ehlo itcast                 --随便说点啥            auth login                  --需要登陆            aXRjYXN0X2x0                --用户名(base64编码)            MXFhejJ3c3g=                --密码(base64编码)            mail from:<itcast_lt@163.com>   --发件人            rcpt to:<itcast_lt@126.com>     --收件人            data                            --需要书写邮件内容            from:<lkplovelyf@163.com>   --显示的发件人            to:<itcast_lt@126.com>      --显示的收件人            subject:good luck!!!        --主题            [空行]                      --与正文的分割            baidu welcome you!!!        --正文            .                           --结束邮件主体            quit                        --断开连接    base64编码与解码        解码:            sun.misc.BASE64Decoder类            sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();            byte[] bytes = decoder.decodeBuffer("要解码的字符串");            System.out.println(bytes);        编码:            sun.misc.BASE64Encoder类            sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();            String str = encoder.encode("要编码的字符串".getBytes());            System.out.println(str);        注意:            myeclipse默认没有上面两个类,换个jre库就好了(没搞明白为什么)            项目右键-->Properties-->Java Build Path-->Libraries-->删除原来的-->Add Library-->JRE System Library    javamail        使用java程序发送电子邮件。        sun公司提供            核心jar:mail.jar           --> javamail1_4_5.zip            依赖jar:activation.jar     --> jaf-1_1_1.zip (编写复杂邮件时使用,现阶段不用)    javamail 编写流程        1 获得会话 Session  -->相当于连接        2 编写消息 Message  -->相当于邮件        3 发送邮件 Transport    工具类        import java.util.Properties;        import javax.mail.Authenticator;        import javax.mail.Message;        import javax.mail.Message.RecipientType;        import javax.mail.PasswordAuthentication;        import javax.mail.Session;        import javax.mail.Transport;        import javax.mail.internet.InternetAddress;        import javax.mail.internet.MimeMessage;        /**         * 邮件工具包         * @author Administrator         *         */        public class MailUtils {            private static String serverHost = "localhost";//邮箱服务器地址(例:smtp.163.com)            private static String mail_username = "123";//用户            private static String mail_password = "123";//密码            private static String sendHost = "123@ss.cn";//发送人地址            /**             * 向用户发送邮件             * @param sendToUrl 目标邮箱             * @param subject 主题             * @param content 正文             */            public static void sendMail(String sendToHost,String subject,String content){                try {                    //获得会话                    // * 准备参数                    // ** 1 准备配置信息                    Properties props = new Properties();                    props.setProperty("mail.host", serverHost);//邮箱服务器地址                    props.setProperty("mail.smtp.auth", "true");//进行登录验证                    // ** 2 准备用户和密码                    Authenticator authenticator = new Authenticator() {                        protected PasswordAuthentication getPasswordAuthentication() {                            return new PasswordAuthentication(mail_username, mail_password);                        }                    };                    Session session = Session.getDefaultInstance(props, authenticator);                    //session.setDebug(true);// 设置debug模式 在控制台看到交互信息                    //编写消息                    Message message = new MimeMessage(session);                    // * 1 设置发件人                    message.setFrom(new InternetAddress(sendHost));                    // * 2 设置收件人                    message.setRecipient(RecipientType.TO, new InternetAddress(sendToHost));                    //TO:接收者;CC:抄送;BCC:暗送;(接收者知道所有被抄送的人,但不知道被暗送的人)                    // * 3 设置主题                    message.setSubject(subject);                    // * 4 设置正文                    message.setContent(content, "text/html;charset=utf-8");                    //发送                    Transport.send(message);                } catch (Exception e) {                    e.printStackTrace();                    throw new RuntimeException(e);                }            }            public static void main(String[] args) {                sendMail("456@ss.cn","主题1","正文");            }        }MIME类型    概述        多用途互联网邮件扩展(MIME,Multipurpose Internet Mail Extensions)        规定了各种各样数据类型的符号化方法,使邮件能够支持非ASCII字符,二进制格式附件等多种格式的消息        HTTP协议中也使用了MIME的框架,标准被扩展为互联网媒体类型    格式:content-type : type/subtype;parameter        例如:text/html;charset=UTF-8        type的所有取值            Text:用于标准化地表示的文本信息,文本消息可以是多种字符集和或者多种格式的;            Multipart:用于连接消息体的多个部分构成一个消息,这些部分可以是不同类型的数据;            Application:用于传输应用程序数据或者二进制数据;            Message:用于包装一个E-mail消息;            Image:用于传输静态图片数据;            Audio:用于传输音频或者音声数据;            Video:用于传输动态影像数据,可以是与音频编辑在一起的视频数据格式。        subtype常见取值            text/plain(纯文本)            text/html(HTML文档)            image/gif(gif图像)            image/jpeg(jpeg图像)            image/png(png图像)            application/msword(Microsoft Word文件)            application/x-www-from-urlencoded(HTTP的POST方式提交表单)            multipart/form-data (用于文件上传)        %tomcat%/conf/web.xml 提供常见的MIME类与扩展名的映射关系。案例:使用本地服务器发送邮件    软件介绍        易邮邮件服务器:邮件服务器软件,可以注册账号发送和接收邮件        Foxmail:使用客户端管理邮箱    安装易邮邮件服务器    设置易邮邮件服务器        工具-->服务器设置-->作为局域网的邮件服务器,单域名:ss.cn        新建账号            账号123     账号123     联系邮件地址123@ss.cn            账号456     账号456     联系邮件地址456@ss.cn    安装Foxmail    设置Foxmail        第一次启动时创建用户:手动设置            邮件账号    123@ss.cn            密码        123            POP服务器   localhost            SMTP服务器  localhost        启动后创建用户:在已有用户上右击-->设置-->新建-->手动设置            邮件账号    456@ss.cn            密码        456            POP服务器   localhost            SMTP服务器  localhost    可以试试用Foxmail用两个账号互相发送邮件    使用java代码发送邮件        设置工具类MailUtils中的成员变量的值            private static String serverHost = "localhost";//邮箱服务器地址(例:smtp.163.com)            private static String mail_username = "123";//用户            private static String mail_password = "123";//密码            private static String sendHost = "123@ss.cn";//发送人地址        发送邮件            MailUtils.sendMail("456@ss.cn","主题","正文");文件上传    概述        将用户本地的资源,通过浏览器发送给服务器,服务器保存到服务器端        浏览器:选择文件,提交        服务器:获得数据,保存    步骤        1 通知浏览器,可以选择文件、可以将文件进行提交            提交: <form> <input type="submit"/>            选择:<input type="file" name=""/>            发送上传内容:给form表单添加属性enctype="multipart/form-data" ,设置method="post". 注意:默认情况只发送文件的名称                enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码                    取值:                        application/x-www-form-urlencoded 在发送前编码所有字符(默认)                         multipart/form-data 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。            注意:                上传文件时,request.getParameter方法不能获取方法体传递的参数                    可以在表单的action后面使用?追加参数                    可以在当前servlet上添加servlet3.0的注解@MultipartConfig        2 服务器接收数据,并保存文件。            第一种:使用servlet的api解析上传内容,需要手动对内容进行分析。比较繁琐                request提供的getInputStream() 用来获得请求体的所有内容。            第二种:使用第三方工具 -- apache commons组件--fileupload                jar                    核心jar:commons-fileupload-1.2.2.jar   --> 来自commons-fileupload-1.2.2-bin.zip                    依赖jar:commons-io-2.3.jar             --> 来自commons-io-2.3-bin.zip                核心类:ServletFileUpload                api见工具类            第三种:Servlet3.0支持文件上传,参见下面的<servlet3.0>            第四种: struts2的文件上传,参见<struts>中的<文件上传>    工具类FileUploadApacheUtils        package util;        import java.io.File;        import java.io.FileOutputStream;        import java.io.InputStream;        import java.io.OutputStream;        import java.util.HashMap;        import java.util.List;        import java.util.Map;        import java.util.UUID;        import javax.servlet.http.HttpServletRequest;        import org.apache.commons.fileupload.FileItem;        import org.apache.commons.fileupload.disk.DiskFileItemFactory;        import org.apache.commons.fileupload.servlet.ServletFileUpload;        public class FileUploadApacheUtils {            /**             * 处理文件上传             * @param request 请求对象             * @return Map:普通表单字段的name-value,上传文件的name-保存名称             */            @SuppressWarnings("unchecked")            public static Map<String,String> fileUpload(HttpServletRequest request){                //判断是否表单是否是文件上传 ,即判断enctype是否为"multipart/form-data"                boolean isMultipart = ServletFileUpload.isMultipartContent(request);                if(!isMultipart){                    throw new RuntimeException("表单不是文件上传类型");                }                int sizeThreshold = 1024 * 1024;//设置临界点大小,当文件大小大于临界点大小时,将会产生临时文件                String tempPath = "/WEB-INF/tempFile";//临时文件存放位置                String savePath = "/WEB-INF/uploadFile";//保存路径                Map<String,String> map = new HashMap<String,String>();                try {                    //准备工厂,进行配置(出于安全性考虑,当文件过大时每接收一点先缓存到临时文件中)                    DiskFileItemFactory factory = new DiskFileItemFactory();                    factory.setSizeThreshold(sizeThreshold);//设置临界点大小,当文件大小大于临界点大小时,将会产生临时文件                    String tempPath2 = request.getSession().getServletContext().getRealPath(tempPath);                    factory.setRepository(new File(tempPath2));//设置临时文件存放位置                    //准备解析文件                    ServletFileUpload upload = new ServletFileUpload(factory);//核心类                    upload.setHeaderEncoding("utf-8");//设置文件名的编码,否则文件名含有中文时会出现乱码.如果不设置则使用request的编码                    List<FileItem> allFileItem = upload.parseRequest(request);//解析request,获得文件项                    for(FileItem fileItem : allFileItem){                        if(fileItem.isFormField()){                            //表单字段                            String name = fileItem.getFieldName();                            String value = fileItem.getString("utf-8");//参数为编码方式,不设置可能出现中文乱码                            map.put(name, value);                        }else{                            //上传的文件                            String fieldName = fileItem.getFieldName();//name属性                            String fileName = fileItem.getName();//文件名称                            fileName = getFileName(fileName);//处理文件名称                            InputStream in = fileItem.getInputStream();//获得文件流                            //将文件流保存到文件                            String path = request.getSession().getServletContext().getRealPath(savePath);//保存路径                            File file = new File(path,fileName);                            OutputStream out = new FileOutputStream(file);                            byte[] bytes = new byte[128 * 1024];                            int len = 0;                            while( (len = in.read(bytes)) > 0 ){                                out.write(bytes,0,len);                            }                            in.close();                            out.close();                            fileItem.delete();//删除临时文件(如果有的话)                            map.put(fieldName, fileName);                        }                    }                    return map;                } catch (Exception e) {                    e.printStackTrace();                    throw new RuntimeException(e);                }            }            /**             * 返回经过处理的文件名称,保证不重复             * @param fileName 要处理的文件名称             * @return 经过处理的文件名称             */            private static String getFileName(String fileName){                fileName = fileName.substring(fileName.lastIndexOf("/") + 1);//处理兼容,因为ie8在xp下返回的是全路径                fileName = UUID.randomUUID().toString().replace("-", "") + "_" + fileName;//避免重复                return fileName;            }        }    上传文件示例        导入jar包和工具类            核心jar:commons-fileupload-1.2.2.jar   --> 来自commons-fileupload-1.2.2-bin.zip            依赖jar:commons-io-2.3.jar             --> 来自commons-io-2.3-bin.zip            工具类:自定义工具类FileUploadApacheUtils        在WEB-INF下创建tempFile和uploadFile文件夹        index.jsp            <form action="${pageContext.request.contextPath }/userServlet" method="post" enctype="multipart/form-data">                <input name="username" value="jack"><br>                <input type="file" name="uploadFile"><br>                <input type="submit" value="提交">            </form>        userServlet            public void doPost(HttpServletRequest request, HttpServletResponse response)                    throws ServletException, IOException {                Map<String,String> map = FileUploadApacheUtils.fileUpload(request);                System.out.println(map);            }    上传文件请求        请求头            Content-Type: multipart/form-data; boundary=---------------------------7de32138c0540        请求体            -----------------------------7de32138c0540            Content-Disposition: form-data; name="username"            jack            -----------------------------7de32138c0540            Content-Disposition: form-data; name="password"            123            -----------------------------7de32138c0540            Content-Disposition: form-data; name="uploadFile1"; filename="123.txt"            Content-Type: text/plain            上传文件内容...            -----------------------------7de32138c0540            Content-Disposition: form-data; name="uploadFile2"; filename="456.txt"            Content-Type: text/plain            上传文件内容...        注意:上面上传了两个普通表单字段和两个文件.(请求体中的空行我去掉了)        请求头生成一串随机字符串,然后用此字符串将请求体的多个键-值分隔文件下载    概述        服务器提供下载资源,当浏览器发送请求时,通知浏览器保存到本地        服务器:读取资源,发送到浏览器,通知浏览器下载        浏览器:下载    浏览器下载文件时,如果浏览器可以解析将直接显示,如果不能解析则提供下载。    通知浏览器总是进行下载:response.setHeader("content-disposition", "attachment;filename=文件名称");    文件中文显示乱码处理:value = new String(value.getBytes("GBK") , "ISO-8859-1");    示例        public void doGet(HttpServletRequest request, HttpServletResponse response)                throws ServletException, IOException {            String fileName = "图片.jpg";            //处理fileName中文乱码问题(响应头不支持中文)            //http协议进行iso8859-1编码,客户端进行gbk(操作系统默认编码)解码,所以要反着来一下            fileName = new String(fileName.getBytes("gbk"),"iso8859-1");            //通知浏览器内容类型为附件            response.setHeader("content-disposition", "attachment;filename=" + fileName);            //获得文件            InputStream in = request.getSession().getServletContext().getResourceAsStream("/图片.jpg");            //发送            OutputStream out = response.getOutputStream();            byte[] bytes = new byte[128 * 1024];            int len = 0;            while( (len = in.read(bytes))>0 ){                out.write(bytes,0,len);            }            in.close();        }    注意:处理文件名称中文乱码的代码通常放在过滤器中,处理图片名称含有中文的问题(向tomcat请求不到名称含有中文的图片)servlet3.0    servlet3.0提供注解        @WebServlet, 用于取代servlet的配置web.xml <servlet>...配置内容            属性                name用来配置servlet名称,不写的话默认为当前类名                urlPatterns 和 value 作用一样,都用来配置servlet访问路径                例: @WebServlet("/one") 或 @WebServlet({"/one","/two"})         @WebFilter ,用于取代过滤器的配置 web.xml <filter>...配置内容,属性同上        @WebListener ,用于取代监听器的配置 <listener><listener-class>        @MultipartConfig,通知tomcat当前servlet将开启文件上传的处理,无属性    servlet3.0对文件上传进行支持        通过request.getPart(名称)获得上传内容,Part对象等价 commons FileItem        默认情况servlet不支持上传,需要在当前servlet上添加注解@MultipartConfig,无属性        注意:当使用@MultipartConfig注解时,request.getParameter()可以获得普通表单字段的值        工具类FileUploadServlet3Utils            public class FileUploadServlet3Utils {                /**                 * 保存上传文件                 * @param request 请求对象                 * @param name input的name值                 * @return 保存路径                 */                public static String saveUploadFile(HttpServletRequest request,String name){                    String fileDir = "/WEB-INF/uploadFile";//保存文件夹                    try {                        // 获得上传文件内容对象                        Part part = request.getPart(name);                        if(part==null){                            throw new RuntimeException("没有找到上传的文件");                        }                        // * 获得上传文件名称                        String fileName = getFileName(part);                        String savePath = fileDir+"/"+fileName;                        // * 获得文件内容 --流                        InputStream is = part.getInputStream();                        // * 保存                        String realSavePath = request.getServletContext().getRealPath(savePath);                        FileOutputStream out = new FileOutputStream(new File(realSavePath));                        byte[] buf = new byte[128*1024];                        int len = -1;                        while( (len = is.read(buf)) != -1 ){                            out.write(buf, 0, len);                        }                        out.close();                        is.close();                        return savePath;                    } catch (Exception e) {                        e.printStackTrace();                        throw new RuntimeException("保存上传文件失败");                    }                }                /**                 * 获得文件名称,保证不重复                 * @param part                 * @return                 */                private static String getFileName(Part part){                    // * 获取文件名称                    String headerValue = part.getHeader("Content-Disposition");                    int beginIndex = headerValue.indexOf("filename=\"") + "filename=\"".length();                    int endIndex = headerValue.length() -1;                    String fileName = headerValue.substring(beginIndex, endIndex);                    // * 处理文件名称 --浏览器兼容                    fileName = fileName.substring(fileName.lastIndexOf("/") + 1);//处理兼容,因为ie8在xp下返回的是全路径                    // * 处理文件名称 --不重复                    fileName = UUID.randomUUID().toString().replace("-", "") + "_" + fileName;//避免重复                    return fileName;                }            }        使用示例            在WEB-INF下创建uploadFile文件夹            index.jsp                <form action="${pageContext.request.contextPath }/userServlet" method="post" enctype="multipart/form-data">                    <input name="username" value="jack"><br>                    <input type="file" name="uploadFile"><br>                    <input type="submit" value="提交">                </form>            userServlet                @MultipartConfig                public class UserServlet extends HttpServlet {                    public void doGet(HttpServletRequest request, HttpServletResponse response)                            throws ServletException, IOException {                        String savePath = FileUploadServlet3Utils.saveUploadFile(request, "uploadFile");                        System.out.println(savePath);                    }                    public void doPost(HttpServletRequest request, HttpServletResponse response)                            throws ServletException, IOException {                        doGet(request, response);                    }                }
0 0
原创粉丝点击