鸿 网 互 联 www.68idc.cn

当前位置 : 服务器租用 > 编程语言开发 > erlang > >

JavaEE基础知识

来源:互联网 作者:佚名 时间:2016-06-21 08:39
JSP的基本原理 JSP的本质是Servlet,当用户想指定Servlet发送请求时,Servlet利用输出流动态生成HTML页面,包括每一个静态HTML标签和所有HTML页面中出现的内容。 JSP的三个编译指令 page, include, taglib %@ page 属性% (2) include指令 这是一个静态includ
  1. JSP的基本原理
    JSP的本质是Servlet,当用户想指定Servlet发送请求时,Servlet利用输出流动态生成HTML页面,包括每一个静态HTML标签和所有HTML页面中出现的内容。
  2. JSP的三个编译指令
    page, include, taglib
    <%@ page 属性%>
    (2) include指令
    这是一个静态include指令,静态包含会将包含页面的额编译指令也包含进来,如果两个页面的编译指令冲突,那么页面就会出错。
  3. JSP动作指令
    (1) 七个
    jsp:forward, jsp:param, jsp:include, jsp:plugin, jsp:useBean, jsp:setProperty, jsp:getProperty
  4. JSP的9个内置对象
    application:
    config: JSP页面通常无需配置,该对象更多地在Servlet中有效;
    exception: 编译指令page的isErrorPage属性为true时,该对象才可以使用。常用的方法有getMessage()和printStackTrace()等;
    out:
    page: 通常没有太大用处。也就是Servlet中的this.
    pageContext: 代表JSP页面上下文,使用该对象可以访问页面中的共享数据,常用方法: getAttribute(String name): 取得page范围内的name属性; getAttribute(String name, int scope): 取得指定范围内的额那么属性,其中scope可以是四个值: PageContext.PAGE_SCOPE, PageContext.REQUEST_SCOPE, PageContext.SESSION_SCOPE, PageContext.APPLICATION_SCOPE。
    request: 常用方法: getParameter, getParameterValues, setAttribute, getAttribute, setCharacterEncoding;
    转发(forward)
    执行forward后依然是上一次请求
    Forward的目标页面可以访问原请求参数,因为依然是同一次请求,所有原请求的请求参数、request范围的属性全部存在
    地址栏里请求的URL不会改变
    重定向(redirect)
    执行redirect后生成第二次请求
    Redirect的目标页面不能访问原请求的请求参数,因为是第二次请求,所有原请求的请求参数、request方位的属性全部丢失
    地址栏改为重定向的目标URL。相当于在浏览器地址栏里输入新的URL后按回车键
    Cookie:
String name = request.getParameter("name");
Cookie c = new Cookie("username" , name);
c.setMaxAge(24 * 3600);
response.addCookie(c);
Cookie[] cookies = request.getCookies();
for (Cookie c : cookies)
{
    if(c.getName().equals("username"))
    {
        out.println(c.getValue());
    }
}
Cookie c = new Cookie("cnName" 
    , java.net.URLEncoder.encode("孙悟空" , "gbk"));
c.setMaxAge(24 * 3600);
response.addCookie(c);
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies)
{
    if(cookie.getName().equals("cnName"))
    {
        out.println(java.net.URLDecoder
            .decode(cookie.getValue()));
    }
}
response: 通常很少使用该对象直接响应,而是使用out对象,除非需要生成非字符响应。而response对象常用语重定向,常用方法getOutputStream, sendRedirect;
session: 代表一次会话,常用方法getAttribute, setAttribute;

5. Servlet
(1) Servlet和JSP的区别:
1) Servlet中没有内置对象,原来JSP中的内置对象都必须由程序显示创建;
2) 对于静态的HTML标签,Servlet都必须使用页面输出流逐行输出;
(2) 两种配置方式:
1) 在Servlet类中使用@WebServlet标记;
2) 在web.xml文件中进行配置;
(3) @WebServlet支持的常用属性
属性
是否必须
说明
asyncSupported

指定该Servlet是否支持异步操作模式。
displayName

指定该Servlet的显示名
initParams

用于为该Servlet配置参数
loadOnStartup

用于将该Servlet配置成load-on-startup的Servlet
name

指定该Servlet的名称
urlPatterns/value

这两个属性的作用完全相同
如果打算使用注解配置Servlet,注意两点:
1) 不要在web.xml文件的根元素(

<?xml version="1.0" encoding="GBK"?>
<web-app 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"
    version="3.0">
    <!-- 配置Servlet的名字 -->
    <servlet>
        <!-- 指定Servlet的名字,
            相当于指定@WebServlet的name属性 -->
        <servlet-name>firstServlet</servlet-name>
        <!-- 指定Servlet的实现类 -->
        <servlet-class>lee.FirstServlet</servlet-class>
    </servlet>
    <!-- 配置Servlet的URL -->
    <servlet-mapping>
        <!-- 指定Servlet的名字 -->
        <servlet-name>firstServlet</servlet-name>
        <!-- 指定Servlet映射的URL地址,
            相当于指定@WebServlet的urlPatterns属性-->
        <url-pattern>/aa</url-pattern>
    </servlet-mapping>
    <servlet>
        <!-- Servlet名 -->
        <servlet-name>timerServlet</servlet-name>
        <!-- Servlet的实现类 -->
        <servlet-class>lee.TimerServlet</servlet-class>
        <!-- 配置应用启动时,创建Servlet实例
            ,相当于指定@WebServlet的loadOnStartup属性-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
        <!-- 配置Servlet名 -->
        <servlet-name>testServlet</servlet-name>
        <!-- 指定Servlet的实现类 -->
        <servlet-class>lee.TestServlet</servlet-class>
        <!-- 配置Servlet的初始化参数:driver -->
        <init-param>
            <param-name>driver</param-name>
            <param-value>com.mysql.jdbc.Driver</param-value>
        </init-param>
        <!-- 配置Servlet的初始化参数:url -->
        <init-param>
            <param-name>url</param-name>
            <param-value>jdbc:mysql://localhost:3306/javaee</param-value>
        </init-param>
        <!-- 配置Servlet的初始化参数:user -->
        <init-param>
            <param-name>user</param-name>
            <param-value>root</param-value>
        </init-param>
        <!-- 配置Servlet的初始化参数:pass -->
        <init-param>
            <param-name>pass</param-name>
            <param-value>32147</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <!-- 确定Servlet名 -->
        <servlet-name>testServlet</servlet-name>
        <!-- 配置Servlet映射的URL -->
        <url-pattern>/testServlet</url-pattern>
    </servlet-mapping>
</web-app>

(4) JSP/Servlet的声明周期
1) 创建Servlet实例有两个时机:
a) 客户端第一次请求某个Servlet时,系统创建该Servlet的实例:大部分的Servlet都是这种Servlet。
b) Web应用启动时立即创建Servlet实例,即load-on-startup Servlet;
2) 每个Servlet的运行都遵循如下声明周期:
a) 创建Servlet实例;
b) Web容器调用Servlet的init方法,对Servlet进行初始化;
c) Servlet初始化后,将一直存在于容器中,用于响应客户端请求。Get请求调用doGet方法响应;Post请求调用doPost方法响应请求。或者统一使用service()方法处理来响应用于请求。
d) Web容器决定销毁Servlet时,先调用Servlet的destroy方法,通常在关闭Web应用之时销毁Servlet。
6. Filter
Filter主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链。使用流程:Filter对用于请求进行预处理,接着讲请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
(1) Filter的几个用处:
1) 在HttpServletRequest到达Servlet之前,拦截用户的HttpServletRequest;
2) 根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据;
3) 在HttpServletResponse到达客户端之前,拦截HttpServletResponse。
4) 根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据;
(2) Filter种类
1) 用户授权的Filter:Filter负责检查用户请求,根据请求过滤用户非法请求;
2) 日志Filter: 详细记录某些特殊的用户请求;
3) 负责接吗的Filter:包括对非标准编码的请求解码;
4) 能改变XML内容的XSLT Filter等;
5) Filter可负责拦截多个请求或响应: 一个请求或响应也可被多个Filter拦截;
(3) 创建Filter的两个步骤:
1) 实现javax.servlet.Filter接口:三个方法: init, destroy, deFilter
2) web.xml文件中配置Filter;

@WebFilter(filterName="log"
    ,urlPatterns={"/*"})
public class LogFilter implements Filter 
{
    //FilterConfig可用于访问Filter的配置信息
    private FilterConfig config;
    //实现初始化方法
    public void init(FilterConfig config)
    {
        this.config = config; 
    }
    //实现销毁方法
    public void destroy()
    {
        this.config = null; 
    }
    //执行过滤的核心方法
    public void doFilter(ServletRequest request,
        ServletResponse response, FilterChain chain)
        throws IOException,ServletException
    {
        //---------下面代码用于对用户请求执行预处理---------
        //获取ServletContext对象,用于记录日志
        ServletContext context = this.config.getServletContext(); 
        long before = System.currentTimeMillis();
        System.out.println("开始过滤...");
        //将请求转换成HttpServletRequest请求
        HttpServletRequest hrequest = (HttpServletRequest)request;
        //输出提示信息
        System.out.println("Filter已经截获到用户的请求的地址: " + 
            hrequest.getServletPath());
        //Filter只是链式处理,请求依然放行到目的地址
        chain.doFilter(request, response);
        //---------下面代码用于对服务器响应执行后处理---------
        long after = System.currentTimeMillis();
        //输出提示信息
        System.out.println("过滤结束");
        //输出提示信息
        System.out.println("请求被定位到" + hrequest.getRequestURI() + 
            "   所花的时间为: " + (after - before)); 
    } 
}
(4) 一个较为实用的Filter
    设置request编码的字符集,从而避免每个JSP、Servlet都需要设置;而且还会验证用户是否登录,如果用户没有登录,系统直接跳转到登录页面;
@WebFilter(filterName="authority"
    , urlPatterns={"/*"}
    , initParams={
        @WebInitParam(name="encoding", value="GBK"),
        @WebInitParam(name="loginPage", value="/login.jsp"),
        @WebInitParam(name="proLogin", value="/proLogin.jsp")})
public class AuthorityFilter implements Filter 
{
    //FilterConfig可用于访问Filter的配置信息
    private FilterConfig config;
    //实现初始化方法
    public void init(FilterConfig config)
    {
        this.config = config; 
    }
    //实现销毁方法
    public void destroy()
    {
        this.config = null; 
    }
    //执行过滤的核心方法
    public void doFilter(ServletRequest request,
        ServletResponse response, FilterChain chain)
        throws IOException,ServletException
    {
        //获取该Filter的配置参数
        String encoding = config.getInitParameter("encoding");
        String loginPage = config.getInitParameter("loginPage");
        String proLogin = config.getInitParameter("proLogin");
        //设置request编码用的字符集
        request.setCharacterEncoding(encoding);         //①
        HttpServletRequest requ = (HttpServletRequest)request;
        HttpSession session = requ.getSession(true);
        //获取客户请求的页面
        String requestPath = requ.getServletPath();
        //如果session范围的user为null,即表明没有登录
        //且用户请求的既不是登录页面,也不是处理登录的页面
        if( session.getAttribute("user") == null
            && !requestPath.endsWith(loginPage)
            && !requestPath.endsWith(proLogin))
        {
            //forward到登录页面
            request.setAttribute("tip" , "您还没有登录");
            request.getRequestDispatcher(loginPage)
                .forward(request, response);
        }
        //"放行"请求
        else
        {
            chain.doFilter(request, response);
        }
    } 
}
  1. 实用URL Rewrite实现网站伪静态
    搜索引擎会优先考虑收录静态的HTML页面,大部分网站都是动态的。实现伪静态:可以通过Filter拦截所有发向.html请求,然后按某种规则将请求forward到实际的.jsp页面即可。
    (1) 下载Jar包: http://www.tuckey.org/urlrewrite/
    (2) 在web.xml文件中配置:
<filter>
        <filter-name>UrlRewriteFilter</filter-name>
        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
(3) 在WEB-INF路径下增加urlrewrite.xml文件,该文件定义了伪静态映射规则,这份伪静态规则是基于正则表达式的。
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN"
    "http://tuckey.org/res/dtds/urlrewrite3.2.dtd">
<urlrewrite>
    <rule>
        <!-- 所有配置如下正则表达式的请求 -->
        <from>/userinf-(\w*).html</from>
        <!-- 将被forward到如下JSP页面,其中$1代表
            上面第一个正则表达式所匹配的字符串 -->
        <to type="forward">/userinf.jsp?username=$1</to>
    </rule>
</urlrewrite>
  1. Listener
    (1) 常用的Web事件监听器接口:
    1) ServletContextListener: 用于监听Web应用的启动和关闭;
@WebListener
public class GetConnListener implements ServletContextListener
{
    //应该启动时,该方法被调用。
    public void contextInitialized(ServletContextEvent sce)
    {

    }
    //应该关闭时,该方法被调用。
    public void contextDestroyed(ServletContextEvent sce)
    {

    }
}
    2) ServletContextAttributeListener: 用于监听ServletContext范围(application)内属性的改变;
@WebListener
public class MyServletContextAttributeListener
    implements ServletContextAttributeListener
{
    //当程序向application范围添加属性时触发该方法
    public void attributeAdded(ServletContextAttributeEvent event) 
    {
        ServletContext application = event.getServletContext();
        //获取添加的属性名和属性值
        String name = event.getName();
        Object value = event.getValue();
        System.out.println(application + "范围内添加了名为"
            + name + ",值为" + value + "的属性!");
    }
    //当程序从application范围删除属性时触发该方法
    public void attributeRemoved(ServletContextAttributeEvent event)
    {
        ServletContext application = event.getServletContext();
        //获取被删除的属性名和属性值
        String name = event.getName();
        Object value = event.getValue();
        System.out.println(application + "范围内名为"
            + name + ",值为" + value + "的属性被删除了!");
    }
    //当application范围的属性被替换时触发该方法
    public void attributeReplaced(ServletContextAttributeEvent event)
    {
        ServletContext application = event.getServletContext();
        //获取被替换的属性名和属性值
        String name = event.getName();
        Object value = event.getValue();
        System.out.println(application + "范围内名为"
            + name + ",值为" + value + "的属性被替换了!");
    }
}
    3) ServletRequestListener: 用于监听用户请求;
    4) ServletRequestAttributeListener: 用于监听ServletRequest范围(request)范围内属性的改变;
@WebListener
public class RequestListener
    implements ServletRequestListener , ServletRequestAttributeListener
{
    //当用户请求到达、被初始化时触发该方法
    public void requestInitialized(ServletRequestEvent sre)  
    {
        HttpServletRequest request = (HttpServletRequest)sre.getServletRequest();
        System.out.println("----发向" + request.getRequestURI()
            + "请求被初始化----");    }
    //当用户请求结束、被销毁时触发该方法
    public void requestDestroyed(ServletRequestEvent sre) 
    {
        HttpServletRequest request = (HttpServletRequest)sre.getServletRequest();
        System.out.println("----发向" + request.getRequestURI()
            + "请求被销毁----");
    }
    //当程序向request范围添加属性时触发该方法
    public void attributeAdded(ServletRequestAttributeEvent event) 
    {
        ServletRequest request = event.getServletRequest();
        //获取添加的属性名和属性值
        String name = event.getName();
        Object value = event.getValue();
        System.out.println(request + "范围内添加了名为"
            + name + ",值为" + value + "的属性!");
    }
    //当程序从request范围删除属性时触发该方法
    public void attributeRemoved(ServletRequestAttributeEvent event)
    {
        ServletRequest request = event.getServletRequest();
        //获取被删除的属性名和属性值
        String name = event.getName();
        Object value = event.getValue();
        System.out.println(request + "范围内名为"
            + name + ",值为" + value + "的属性被删除了!");
    }
    //当request范围的属性被替换时触发该方法
    public void attributeReplaced(ServletRequestAttributeEvent event)
    {
        ServletRequest request = event.getServletRequest();
        //获取被替换的属性名和属性值
        String name = event.getName();
        Object value = event.getValue();
        System.out.println(request + "范围内名为"
            + name + ",值为" + value + "的属性被替换了!");
    }
}
    5) HttpSessionListener: 用于监听用户session的开始和结束;
    6) HttpSessionAttributeListener: 用于舰艇和HttpSession范围(session)内属性的改变;
@WebListener
public class OnlineListener 
    implements HttpSessionListener
{
    //当用户与服务器之间开始session时触发该方法
    public void sessionCreated(HttpSessionEvent se) 
    {
        HttpSession session = se.getSession();
        ServletContext application = session.getServletContext();
        //获取session ID
        String sessionId = session.getId();
        //如果是一次新的会话
        if (session.isNew())
        {
            String user = (String)session.getAttribute("user");
            //未登录用户当游客处理
            user = (user == null) ? "游客" : user;
            Map<String , String> online = (Map<String , String>)
                application.getAttribute("online");
            if (online == null)
            {
                online = new Hashtable<String , String>();
            }
            //将用户在线信息放入Map中
            online.put(sessionId , user);
            application.setAttribute("online" , online);
        }
    }
    //当用户与服务器之间session断开时触发该方法
    public void sessionDestroyed(HttpSessionEvent se)
    {
        HttpSession session = se.getSession();
        ServletContext application = session.getServletContext();
        String sessionId = session.getId();
        Map<String , String> online = (Map<String , String>)
            application.getAttribute("online");
        if (online != null)
        {
            //删除该用户的在线信息
            online.remove(sessionId);
        }
        application.setAttribute("online" , online);
    }
}
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title> 用户在线信息 </title>
    <meta name="website" content="http://www.crazyit.org" />
</head>
<body>
在线用户:
<table width="400" border="1">
<%
Map<String , String> online = (Map<String , String>)application
    .getAttribute("online");
for (String sessionId : online.keySet())
{%>
<tr>
    <td><%=sessionId%>
    <td><%=online.get(sessionId)%>
</tr>
<%}%>
</body>
</html>
@WebListener
public class RequestListener
    implements ServletRequestListener
{
    //当用户请求到达、被初始化时触发该方法
    public void requestInitialized(ServletRequestEvent sre)  
    {
        HttpServletRequest request = (HttpServletRequest)
            sre.getServletRequest();
        HttpSession session = request.getSession();
        //获取session ID
        String sessionId = session.getId();
        //获取访问的IP和正在访问的页面
        String ip = request.getRemoteAddr(); 
        String page = request.getRequestURI();
        String user = (String)session.getAttribute("user");
        //未登录用户当游客处理
        user = (user == null) ? "游客" : user;
        try
        {
            DbDao dd = new DbDao("com.mysql.jdbc.Driver"
                , "jdbc:mysql://localhost:3306/online_inf"
                , "root"
                , "32147");
            ResultSet rs = dd.query("select * from online_inf where session_id=?"
                , true , sessionId);
            //如果该用户对应的session ID存在,表明是旧的会话
            if (rs.next())
            {
                //更新记录
                rs.updateString(4, page);
                rs.updateLong(5, System.currentTimeMillis());
                rs.updateRow();
                rs.close();
            }
            else
            {
                //插入该用户的在线信息
                dd.insert("insert into online_inf values(? , ? , ? , ? , ?)",
                    sessionId , user , ip , page , System.currentTimeMillis());
            }
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }
    //当用户请求结束、被销毁时触发该方法
    public void requestDestroyed(ServletRequestEvent sre) 
    {
    }
}
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title> 用户在线信息 </title>
    <meta name="website" content="http://www.crazyit.org" />
</head>
<body>
在线用户:
<table width="640" border="1">
<%
DbDao dd = new DbDao("com.mysql.jdbc.Driver"
    , "jdbc:mysql://localhost:3306/online_inf"
    , "root"
    , "32147");
//查询online_inf表(在线用户表)的全部记录
ResultSet rs = dd.query("select * from online_inf" , false);
while (rs.next())
{%>
<tr>
    <td><%=rs.getString(1)%>
    <td><%=rs.getString(2)%>
    <td><%=rs.getString(3)%>
    <td><%=rs.getString(4)%>
</tr>
<%}%>
</body>
</html>
(2) 配置Listener
    1) 使用@WebListener修饰Listener实现类;
    2)在web.xml文件中使用<listener.../>元素进行配置;
<listener>
    <listener-class>com.lotus.TestListener</listener-class>
</listener>
网友评论
<