JSP的本质是Servlet,当用户想指定Servlet发送请求时,Servlet利用输出流动态生成HTML页面,包括每一个静态HTML标签和所有HTML页面中出现的内容。
转发(forward) | 重定向(redirect) |
---|---|
执行forward后依然是上一次请求 | 执行redirect后生成第二次请求 |
Forward的目标页面可以访问原请求参数,因为依然是同一次请求,所有原请求的请求参数、request范围的属性全部存在 | Redirect的目标页面不能访问原请求的请求参数,因为是第二次请求,所有原请求的请求参数、request方位的属性全部丢失 |
地址栏里请求的URL不会改变 | 地址栏改为重定向的目标URL。相当于在浏览器地址栏里输入新的URL后按回车键 |
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()));
}
}
属性 | 是否必须 | 说明 |
---|---|---|
asyncSupported | 否 | 指定该Servlet是否支持异步操作模式。 |
displayName | 否 | 指定该Servlet的显示名 |
initParams | 否 | 用于为该Servlet配置参数 |
loadOnStartup | 否 | 用于将该Servlet配置成load-on-startup的Servlet |
name | 否 | 指定该Servlet的名称 |
urlPatterns/value | 否 | 这两个属性的作用完全相同 |
<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-name>firstServletservlet-name>
<servlet-class>lee.FirstServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>firstServletservlet-name>
<url-pattern>/aaurl-pattern>
servlet-mapping>
<servlet>
<servlet-name>timerServletservlet-name>
<servlet-class>lee.TimerServletservlet-class>
<load-on-startup>1load-on-startup>
servlet>
<servlet>
<servlet-name>testServletservlet-name>
<servlet-class>lee.TestServletservlet-class>
<init-param>
<param-name>driverparam-name>
<param-value>com.mysql.jdbc.Driverparam-value>
init-param>
<init-param>
<param-name>urlparam-name>
<param-value>jdbc:mysql://localhost:3306/javaeeparam-value>
init-param>
<init-param>
<param-name>userparam-name>
<param-value>rootparam-value>
init-param>
<init-param>
<param-name>passparam-name>
<param-value>32147param-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>testServletservlet-name>
<url-pattern>/testServleturl-pattern>
servlet-mapping>
web-app>
Filter主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链。使用流程:Filter对用于请求进行预处理,接着讲请求交给Servlet进行处理并生成响应,最后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));
}
}
设置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);
}
}
}
搜索引擎会优先考虑收录静态的HTML页面,大部分网站都是动态的。实现伪静态:可以通过Filter拦截所有发向.html请求,然后按某种规则将请求forward到实际的.jsp页面即可。
- 下载Jar包: http://www.tuckey.org/urlrewrite/
- 在web.xml文件中配置:
<filter>
<filter-name>UrlRewriteFilterfilter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilterfilter-class>
filter>
<filter-mapping>
<filter-name>UrlRewriteFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<urlrewrite>
<rule>
<from>/userinf-(\w*).htmlfrom>
<to type="forward">/userinf.jsp?username=$1to>
rule>
urlrewrite>
@WebListener
public class GetConnListener implements ServletContextListener
{
//应该启动时,该方法被调用。
public void contextInitialized(ServletContextEvent sce)
{
}
//应该关闭时,该方法被调用。
public void contextDestroyed(ServletContextEvent sce)
{
}
}
@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 + "的属性被替换了!");
}
}
@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 + "的属性被替换了!");
}
}
@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 online = (Map)
application.getAttribute("online");
if (online == null)
{
online = new Hashtable();
}
//将用户在线信息放入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 online = (Map)
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>
<listener>
<listener-class>com.lotus.TestListenerlistener-class>
listener>