本篇说的是最基础的Java Web开发,也就是纯Servlet,不包含框架、JSP。
Servlet类库是J2EE中最重要的部分,其主要的接口有:
Filter
FilterChain
FilterConfig
RequestDispatcher
Servlet
ServletConfig
ServletContext
ServletContextAttributeListener
ServletContextListener
ServletRequest
ServletRequestAttributeListener
ServletRequestListener
ServletResponse
SingleThreadModel
本文涉及到的有Servlet,Filter,Session。
开发环境:
1、Tomcat服务器,作为Servlet Container和Web Container,我使用的是7.0版本。Web容器就像显示器,Servlet容器就像播放器,Servlet就像我们做的一个视频。要播放一个视频,两个容器缺一不可。
2、Eclipse,能把我写的代码按照Servlet的规范编译成class。
为了调试方面,我把Tomcat的默认项目路径改为了我的Eclipse项目的目录下。
Filter
这个接口是为了对用户请求的url进行处理。比如特定的跳转、权限的控制、关键词的拦截。当一个用户请求被Filter拦截后,会根据一定的条件决定如何处理。设计Filter主要做两件事:
1、编写java类实现Filter接口,并实现其doFilter方法。
2、在 web.xml 文件中使用<filter>和<filter-mapping>元素对编写的filter类进行注册,并设置它所能拦截的url。
Session
会话是为了给本身无状态的HTTP协议提供状态,这样就可以在服务器端记录某一特定用户的登录状态或访问状态。它本质上是服务器端的一个哈希表(或字典)。通过request.getSession()获得Session对象,关键字Key就是传递给用户浏览器的名为 jsessionid 的 Cookie 值。通过Session对象的getAttribute方法、setAttribute方法、removeAttribute方法来控制会话。
开发实践
我编写了一个简单的模型,一个主页面、一个用户的登陆页、一个用户专属页面。
在Eclipse下创建Dynamic Web Project。为每个Servlet创建一个类,为每个Filter创建一个类。
我编写了2个Filter,一个用来记录所有的URL访问日志,一个用于控制对用户专属页面的访问权限(只有登录状态时才可以访问)。
我编写了5个Servlet处理不同的请求,IndexPage.java呈现主页面,Login.java呈现登陆页,User1.java呈现用户专属页,Login.java、LoginOut.java处理登录/登出请求。
在Java代码里生成html实在太麻烦了,所以把所有的html写成单独的文件,用java去读取。
在Java代码里生成html实在太麻烦了,所以把所有的html写成单独的文件,用java去读取。
下面是web.xml配置文件,对Filter的url映射和对Servlet的url映射都要写在里面。
<span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<filter>
<filter-name>helloFilter</filter-name>
<filter-class>demo.HelloFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>helloFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>loginfilter</filter-name>
<filter-class>demo.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginfilter</filter-name>
<url-pattern>/lucky</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>index_page</servlet-name>
<servlet-class>demo.IndexPage</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>index_page</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>login_page</servlet-name>
<servlet-class>demo.Login</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>login_page</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>logincl_page</servlet-name>
<servlet-class>demo.LoginCL</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>logincl_page</servlet-name>
<url-pattern>/logincl</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>user_page</servlet-name>
<servlet-class>demo.User1</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>user_page</servlet-name>
<url-pattern>/lucky</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>loginout_page</servlet-name>
<servlet-class>demo.LoginOut</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>loginout_page</servlet-name>
<url-pattern>/loginout</url-pattern>
</servlet-mapping>
</web-app></span>
登录状态控制的过滤器:
<span style="font-size:18px;">package demo;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
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.HttpSession;
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig arg0) throws ServletException {
System.out.println("Filter LoginFilter init");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
// 将ServletRequest转换为HttpServletRequest
HttpServletRequest request = (HttpServletRequest) req;
// 获取当前的访问路径
String actionUrl = request.getServletPath();
// 获取HttpSession中的信息
HttpSession session = request.getSession();
String user = (String) session.getAttribute("user");
// 如果session中有flag标记,并且标记为已登录,则放行
if ( (!actionUrl.equals("/lucky")) || (user != null && user.equals("lucky")) )
{
chain.doFilter(req, res);
}
else
{
// 否则,会跳转到提示信息页
res.setContentType("text/html;charset=gbk");
PrintWriter out = ((HttpServletResponse)res).getWriter();
out.print("<script>alert('你没有登录!');location.href='/login'</script>");
}
}
@Override
public void destroy() {
System.out.println("Filter LoginFilter destroy");
}
}</span>
<span style="font-size:18px;">package demo;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class IndexPage extends HttpServlet{
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html;charset=gbk");
PrintWriter pw = res.getWriter();
String path = req.getSession().getServletContext().getRealPath(""); //获取当前工程的路径
File f1 = new File(path + "//templates//welcome.html");
InputStreamReader reader = new InputStreamReader(new FileInputStream(f1)); //建立一个输入流对象reader
BufferedReader br = new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言
String line = "";
line = br.readLine();
while (line != null) {
pw.println(line);
line = br.readLine();// 一次读入一行数据
}
}
}
</span>
其他的代码就不贴了,回头放在github上方便继续学习。