JavaEE基础知识
Posted David_Hernandez
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaEE基础知识相关的知识,希望对你有一定的参考价值。
- JSP的基本原理
JSP的本质是Servlet,当用户想指定Servlet发送请求时,Servlet利用输出流动态生成html页面,包括每一个静态HTML标签和所有HTML页面中出现的内容。 - JSP的三个编译指令
page, include, taglib
<%@ page 属性%>
(2) include指令
这是一个静态include指令,静态包含会将包含页面的额编译指令也包含进来,如果两个页面的编译指令冲突,那么页面就会出错。 - JSP动作指令
(1) 七个
jsp:forward, jsp:param, jsp:include, jsp:plugin, jsp:useBean, jsp:setProperty, jsp:getProperty - 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);
}
}
}
- 实用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>
- 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>
以上是关于JavaEE基础知识的主要内容,如果未能解决你的问题,请参考以下文章
JavaEE安卓Web前端微信小程序等接近四百篇基于代码实战的技术文章