Servlet的分类
- 简单Servlet
- 过滤Servlet
- 监听Servlet
Servlet的生命周期
容器决定Servlet的生命周期。包括加载、初始化、服务、销毁、卸载5个部分。
换一种方式理解Servlet的生命周期
对于HttpServlet
类而言,里面的services
方法主要完成的功能是区分get请求还是post请求,从而分别对于doGet
和doPost
方法。但是子类一旦覆写了services
方法,则没有了区分能力——doGet
和doPost
方法都将失效。——实际上这种做法更像一种设计的模板操作,因为只需要按照它的要求将方法覆写了就可以完成相应的功能——模板设计模式。
使用Servlet取得其他内置对象
取得HttpSession实例
通过HttpServletRequest
接口提供的以下方法完成:
HttpSession getSession()
HttpSession getSession(boolean create)
public class HttpServletSession extends HttpServlet {
public HttpServletSession() {
super();
}
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession(); // 取得session
System.out.println("sessionID:" + session.getId());
session.setAttribute("username", "刘洋"); // 设置session属性
System.out.println("属性内容:" + session.getAttribute("username"));
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
web.xml
<servlet>
<servlet-name>sessiondemo</servlet-name>
<servlet-class>servlet.HttpServletSession</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sessiondemo</servlet-name>
<url-pattern>/HttpSessionDemoServlet</url-pattern>
</servlet-mapping>
取得application对象的实例
HttpServlet
的父类GenericServlet
提供了public ServletContext getServletContext()
方法可以取得ServletContext
接口的实例。
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext app = super.getServletContext();
System.out.println("项目的真实路径:" + app.getRealPath("/"));
}
表达式语言
Jsp2.0之后提供了表达式语言(Expression Language,简称EL),可以访问标志位page(pageContext)、request、session、application中的属性内容,这样就可以在jsp页面中有很少的script代码,可以避免null的问题语法如下:
${属性名称}
下面这个例子说明了使用EL和不使用EL的区别:
<%
request.setAttribute("username", "陶伟华");
%>
<!-- 使用表达式语言输出 -->
${username}
<!-- 不使用EL表达式,需要判断非空 -->
<%
if(request.getAttribute("username")!=null){
%>
<%=request.getAttribute("username") %>
<%
}
%>
表达式语言的内置对象
表达式内置对象 | 说明 |
---|---|
pageContext | javax.servlet.jsp.pageContext对象 |
pageScope | page属性范围查找输出属性 |
requestScope | request属性范围查找输出属性 |
sessionScope | session属性范围查找输出属性 |
applicationScope | application属性范围查找输出属性 |
param | 接收传递到本页面的参数 |
paramValues | 接收传递到本页面的一组参数 |
header | 取得一个头信息数据 |
headValues | 取得一组头信息数据 |
cookie | 取得cookie中的数据 |
initParam | 取得配置的初始化参数 |
EL表达式的查找范围:
<%
// pageContext.setAttribute("info", "page属性范围");
// request.setAttribute("info", "request属性范围");
session.setAttribute("info", "session属性范围");
application.setAttribute("info", "application属性范围");
%>
<!-- EL表达式查找范围示例 -->
${info}
如果在不同的属性范围之内保存了同名属性,则EL的查找范围是:page–>request–>session–>application。这个时候就可以使用EL内置对象帮助我们找到特定属性范围之内的属性。(PS:实际上在开发中应该尽量避免同名属性)。
<%
pageContext.setAttribute("info", "page属性范围");
request.setAttribute("info", "request属性范围");
session.setAttribute("info", "session属性范围");
application.setAttribute("info", "application属性范围");
%>
<!-- EL表达式查找特定属性范围的属性 -->
page属性内容:${pageScope.info }<br />
request属性内容:${requestScope.info }<br />
session属性内容:${sessionScope.info }<br />
application属性内容:${applicationScope.info }<br />
EL的内置对象中有pageContext。之前在JSP中我们可以通过pageContext取得request、session、application的JSP内置对象。我们可以直接使用EL直接完成内置对象的方法调用(实际上依靠的是java的反射机制)。
IP地址:${pageContext.request.remoteAddr}<br />
session ID:${pageContext.session.id}<br />
接收参数
表单和URL都可以传递参数。在EL中可以使用param
对象完成。
通过内置对象获取URL参数:<%=request.getParameter("ref") %><br/>
EL表达式获取URL参数:${param.ref}
接收一组参数paramValues
<form action="get_param.jsp">
请选择兴趣:
<input type="checkbox" name="inst" value="游泳">游泳
<input type="checkbox" name="inst" value="看电视">看电视
<input type="checkbox" name="inst" value="看书">看书
<input type="checkbox" name="inst" value="打游戏">打游戏
<input type="checkbox" name="inst" value="打篮球">打篮球
<input type="submit" value="提交">
</form>
使用EL表达式获取一组参数:<br />
第一个参数:${paramValues.inst[0] }<br />
第二个参数:${paramValues.inst[1] }<br />
第三个参数:${paramValues.inst[2] }<br />
第四个参数:${paramValues.inst[3] }<br />
第五个参数:${paramValues.inst[4] }
但是在实际的开发过程中使用最多的还是param
,接收多个参数的params
并不常用。因为从MVC设计模式上讲,所有的参数接收都应该交给Servlet。
EL表达式中的集合操作
List和Set接口的本质区别是List接口对Collection接口进行了扩充,而Set接口并没有对Collection接口进行扩充。
输出Collection
<%
List<String> all = new ArrayList<String>();
all.add("Tom");
all.add("Jack");
all.add("Thinking in java");
all.add("Effective java");
request.setAttribute("info", all); // 集合保存在request范围
%>
<!-- 输出集合中的内容 -->
第一个内容:${ info[0]}<br />
第二个内容:${ info[1]}<br />
第三个内容:${ info[2]}<br />
第四个内容:${ info[3]}<br />
第五个内容:${ info[4]}<br />
输出Map
<%
Map<String,String> all = new HashMap<String,String>();
all.put("001", "Tomcat");
all.put("002", "EJB");
all.put("003", "先序遍历");
all.put("004", "SSH");
request.setAttribute("info", all); // 集合保存在request范围
%>
<!-- 输出Map中的内容 -->
key为001的内容:${ info["001"]}<br />
key为002的内容:${ info["002"]}<br />
key为003的内容:${ info["003"]}<br />
key为004的内容:${ info["004"]}<br />
key为005的内容:${ info["005"]}<br />
在MVC中应用EL
在之前讲解MVC的时候一直都有DAO的存在,而且所有的对象都是保存在VO之中。如果将一个VO对象传递到JSP的话,则必须在JSP页面中导入VO包,如果现在使用了EL表达式的话,这个包的导入就没有任何意义了。
vo
package org.gpf.vo;
public class Dept {
private int deptno;
private String dname;
private String loc;
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String toString() {
return "Dept [deptno=" + deptno + ", dname=" + dname + ", loc=" + loc
+ "]";
}
}
Servlet:ELServlet
public class ELServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Dept dept = new Dept();
dept.setDname("学工部");
dept.setDeptno(1200);
dept.setLoc("武昌区");
request.setAttribute("deptinfo", dept);
request.getRequestDispatcher("dept_info.jsp").forward(request, response);
}
}
JSP页面deptinfo.jsp
部门编号:${deptinfo.deptno }<br />
部门名称:${deptinfo.dname }<br />
部门位置:${deptinfo.loc }<br />
${deptinfo }<br />
以上的JSP页面没有调用任何的getter就进行了对象的输出,则肯定应用到了反射机制。
使用MVC传递集合
ELServlet
public class ELServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
List<Dept> all = new ArrayList<Dept>();
Dept dept = new Dept();
dept.setDname("学工部");
dept.setDeptno(1200);
dept.setLoc("武昌区");
all.add(dept);
dept = new Dept();
dept.setDeptno(1300);
dept.setDname("卫生部");
dept.setLoc("黄浦区");