Servlets入门

##1、ServletRequest
对于每个Http请求,Servlet容器会创建一个ServletRequest实例,并将它传给Servlet的Service方法,ServletRequest封装关于这个请求的信息
##2、ServletResponse
表示一个Servlet响应,在调用Servlet的Service方法之前,Servlet容器会首先创建一个ServletResponse,作为第二个参数传入Service方法,ServletResponse隐藏了向浏览器发送响应的复杂过程

在ServletResponse定义的方法里有getWriter方法,它返回了一个可以向客户端发送文本的PrintWriter。
##3、ServletConfig
Servlet容器初始化时会给init方法传入一个ServletConfig,ServletConfig封装了可以通过@WebServlet或部署描述符传给Servlet的配置信息,这样传入的每一条信息叫做一个初始化参数,一个初始化参数有key和value,可以通过调用ServletConfig的getInitParameter方法获取。
下面是ServletConfig的例子

@WebServlet(name = "ServletConfigDemo", urlPatterns = { "/ServletConfigDemo" }, initParams = {
		@WebInitParam(name = "admin", value = "Harry Taciak"),
		@WebInitParam(name = "email", value = "xxx@qq.com") }

)
public class ServletConfigDemo implements Servlet {

	private transient ServletConfig servletConfig;

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

	@Override
	public ServletConfig getServletConfig() {
		// TODO Auto-generated method stub
		return servletConfig;
	}

	@Override
	public String getServletInfo() {
		// TODO Auto-generated method stub
		return "ServletConfig demo";
	}

	@Override
	public void init(ServletConfig servletConfig) throws ServletException {
		// TODO Auto-generated method stub
		this.servletConfig = servletConfig;
	}

	@Override
	public void service(ServletRequest request, ServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		
		ServletConfig servletConfig = getServletConfig();
		String admin = servletConfig.getInitParameter("admin");
		String email = servletConfig.getInitParameter("email");
		response.setContentType("text/html");
		PrintWriter writer = response.getWriter();
		writer.print("<html><head></head><body>" + "Admin:" + admin
				+ "<br/>Email:" + email + "</body></html>");
	}

}

运行结果
这里写图片描述
##4、ServletContext
每个Web应用程序只有一个上下文,在将程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的Web应用都会有一个ServletContext对象
通过在ServletConfig中调用getServletContext方法,来获取ServletContext,得到后就可以共享从应用程序中的所有资料访问到的信息,而且还可以动态注册Web对象
##5、GenericServlet
抽象类GenericServlet让上面的ServletConfigDemo的代码更简单,GenericServlet实现了Servlet和ServletConfig接口,并完成了init()方法的ServletConfig赋值,还实现了Serlvet的所有方法提供默认的实现

@WebServlet(name = "GenericServletDemo", urlPatterns = { "/GenericServletDemo" }, initParams = {
		@WebInitParam(name = "admin", value = "jyx"),
		@WebInitParam(name = "email", value = "xxx@qq.com") })
public class GenericServletDemo extends GenericServlet {

	private static final long serialVersionUID=62500890L;
	
	@Override
	public void service(ServletRequest request, ServletResponse response)
			throws ServletException, IOException {
		ServletConfig servletConfig=getServletConfig();
		String admin=servletConfig.getInitParameter("admin");
		String email=servletConfig.getInitParameter("email");
		response.setContentType("text/html");
		PrintWriter writer = response.getWriter();
		writer.print("<html><head></head><body>" + "Admin:" + admin
				+ "<br/>Email:" + email + "</body></html>");	
	}
}

运行结果
这里写图片描述
效果一样,但代码变简洁了


##会话管理
###1、URL重写
URL重写是一种会话跟踪技术,它将一个或多个token添加到URL的查询字符串中,每个token通常是key=value形式,如
这里写图片描述

@WebServlet(name = "Top2Servlet", urlPatterns = { "/top10" })
public class Top2Servlet extends HttpServlet {

	private List<String> LondonAttrs;
	private List<String> ParisAttrs;

	@Override
	public void init() throws ServletException {
		LondonAttrs = new ArrayList<String>(10);
		ParisAttrs = new ArrayList<String>(10);
		LondonAttrs.add("London eye");
		LondonAttrs.add("2012 park");
		LondonAttrs.add("London eye");
		LondonAttrs.add("2012 park");
		LondonAttrs.add("London eye");
		LondonAttrs.add("2012 park");
		LondonAttrs.add("London eye");
		LondonAttrs.add("2012 park");
		LondonAttrs.add("London eye");
		LondonAttrs.add("2012 park");
	
		
		
		ParisAttrs.add("Notre Dame");
		ParisAttrs.add("Musee d");
		ParisAttrs.add("Notre Dame");
		ParisAttrs.add("Musee d");
		ParisAttrs.add("Notre Dame");
		ParisAttrs.add("Musee d");
		ParisAttrs.add("Notre Dame");
		ParisAttrs.add("Musee d");
		ParisAttrs.add("Notre Dame");
		ParisAttrs.add("Musee d");
		

	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String city = req.getParameter("city");
		if (city != null && (city.equals("london") || city.equals("paris"))) {
			showAttractions(req, resp, city);
		} else {
			showMainPage(req, resp);
		}
	}

	private void showMainPage(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		resp.setContentType("text/html");
		PrintWriter write = resp.getWriter();
		write.print("<html><head>" + "<title>Top 10</title>" + "</head><body>"
				+ "please select city:"
				+ "<br/><a href='?city=london'>London</a>"
				+ "<br/><a href='?city=paris'>Paris</a>" + "</body></html>");
	}

	private void showAttractions(HttpServletRequest req,
			HttpServletResponse resp, String city) throws IOException {
		int page = 1;
		String pageParameter = req.getParameter("page");
		if (pageParameter != null) {
			page = Integer.parseInt(pageParameter);
			if (page > 2) {
				page = 1;
			}
		}
		List<String> attrs = null;
		if (city.equals("london")) {
			attrs = LondonAttrs;
		} else if (city.equals("paris")) {
			attrs = ParisAttrs;
		}
		resp.setContentType("text/html");
		PrintWriter write = resp.getWriter();
		write.println("<html><head>" + "<title>top 10 result</title>"
				+ "</html></head>");
		write.println("<a href='top2'>Select city</a>");
		write.println("</hr> page"+ page+"<hr/>");
		int start=page*5-5;
		for(int i=start;i<start+5;i++){
			write.println(attrs.get(i)+"<br/>");
		}
		write.println("<hr style='Color:blue'/>"+
		                "<a href ='?city="+city+"&page=1'>page 1</a>"
				);
		write.println(
                "&nbsp; <a href ='?city="+city+"&page=2'>page 2</a>"
		);
		write.println("</body></html>");
	}

}

这里写图片描述
这里写图片描述


##Session
本实例说明了如何使用 HttpSession 对象获取 session 会话创建时间和最后访问时间。如果不存在 session 会话,我们将通过请求创建一个新的 session 会话。

/**
 * Created by 在云端 on 2017/6/9.
 */
@WebServlet(name="MyServletSession", urlPatterns = { "/MyServletSession" })
public class MyServletSession extends HttpServlet {
    /*
    如果你修改了此类, 要修改此值。否则以前用老版本的类序列化的类恢复时会出错。为了在反序列化时,确保类版本的兼容性,
    最好在每个要序列化的类中加入private static final long serialVersionUID这个属性,具体数值自己定义。
     */
    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response) throws ServletException, IOException {
        //如果不存在session会话,则创建一个session对象
        HttpSession session = request.getSession(true);
        //获取session创建时间
        Date createTime = new Date(session.getCreationTime());
        //获取该网页的最后一次访问时间
        Date lastAccessTime = new Date(session.getLastAccessedTime());

        //设置日期输出的格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String title = "Servlet Session";
        Integer visitCount = new Integer(0);
        String visitCountkey = new String("visitCount");
        String userIDKey = new String("userID");
        String userID = new String("Runoob");
        //检查网页是否有新的访问者
        if (session.isNew()) {
            title = "Servlet Session";
            session.setAttribute(userIDKey, userID);
        } else {
            visitCount = (Integer) session.getAttribute(visitCountkey);
            visitCount = visitCount + 1;
            userID = (String) session.getAttribute(userIDKey);
        }
        session.setAttribute(visitCountkey, visitCount);
        //设置响应内容类型
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        String docType = "<!DOCTYPE html>\n";
        out.println(docType +
                "<html>\n" +
                "<head><title>" + title + "</title></head>\n" +
                "<body bgcolor=\"#f0f0f0\">\n" +
                "<h1 align=\"center\">" + title + "</h1>\n" +
                "<h2 align=\"center\">Session 信息</h2>\n" +
                "<table border=\"1\" align=\"center\">\n" +
                "<tr bgcolor=\"#949494\">\n" +
                "  <th>Session 信息</th><th>值</th></tr>\n" +
                "<tr>\n" +
                "  <td>id</td>\n" +
                "  <td>" + session.getId() + "</td></tr>\n" +
                "<tr>\n" +
                "  <td>创建时间</td>\n" +
                "  <td>" + df.format(createTime) +
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>最后访问时间</td>\n" +
                "  <td>" + df.format(lastAccessTime) +
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>用户 ID</td>\n" +
                "  <td>" + userID +
                "  </td></tr>\n" +
                "<tr>\n" +
                "  <td>访问统计:</td>\n" +
                "  <td>" + visitCount + "</td></tr>\n" +
                "</table>\n" +
                "</body></html>");

    }
}

这里写图片描述


##Servlet Context监听器
ServletContext,是一个全局的储存信息的空间,服务器开始,其就存在,服务器关闭,其才释放。request,一个用户可有多个;session,一个用户一个;而servletContext,所有用户共用一个。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息

ServletContext的监听器接口有两个:ServletContextListener和ServletContextAttributeListener

(1)ServletContextListener
ServletContextListener能对ServletContext的创建和销毁做出响应

/*
 *
 */
@WebListener
public class AppListener implements ServletContextListener {

//销毁ServletContext时调用
	@Override
	public void contextDestroyed(ServletContextEvent arg0) {
		// TODO Auto-generated method stub
	}
//创建ServletContext时调用
	@Override
	public void contextInitialized(ServletContextEvent ace) {
		ServletContext ServletContext = ace.getServletContext();
		Map<String, String> countries = new HashMap<String, String>();
		countries.put("ca", "Canada");
		countries.put("us", "United States");
		//设置ServletContext属性
		ServletContext.setAttribute("countries", countries);
	}
}

注意要添加jstl包

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Country List</title>
</head>
<body>
	<c:forEach items="${countries}" var="country">
		<li>${country.value}</li>
	</c:forEach>
</body>
</html>

这里写图片描述

(2)ServletContextAttributeListener

//实现这个接口会收到web 应用中的servlet context属性链修改的通知  
public interface ServletContextAttributeListener extends EventListener {  
    /** Notification that a new attribute was added to the servlet context. Called after the attribute is added.*/  
    //一个属性被添加给servlet context之前会通知  
public void attributeAdded(ServletContextAttributeEvent scab);  
    /** Notification that an existing attribute has been removed from the servlet context. Called after the attribute is removed.*/  
    //属性被删除之后通知  
public void attributeRemoved(ServletContextAttributeEvent scab);  
    /** Notification that an attribute on the servlet context has been replaced. Called after the attribute is replaced. */  
    //属性被替换后通知  
public void attributeReplaced(ServletContextAttributeEvent scab);  
}  

##Session Listener
(1)HttpSessionListener
同样销毁和创建时会调用它两个方法sessionDestroyed()、sessionCreated()

@WebListener
public class SessionListener implements HttpSessionListener,ServletContextListener{
	
	@Override
	public void sessionCreated(HttpSessionEvent se) {
		HttpSession session=se.getSession();
		ServletContext servletContext=session.getServletContext();
		AtomicInteger userCounter=(AtomicInteger) servletContext.getAttribute("userCounter");
		int userCount=userCounter.incrementAndGet();
		System.out.println("userCount incremented to :"+userCount);
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		HttpSession session=se.getSession();
		ServletContext servletContext=session.getServletContext();
		AtomicInteger userCounter=(AtomicInteger) servletContext.getAttribute("userCounter");
		int userCount=userCounter.decrementAndGet();
		System.out.println("--------userCount decremented to:"+userCount);	
	}

	@Override
	public void contextDestroyed(ServletContextEvent se) {	
	}

	@Override
	public void contextInitialized(ServletContextEvent arg0) {
		ServletContext servletContext=arg0.getServletContext();
		servletContext.setAttribute("userCounter", new AtomicInteger());
	}
      
}

这个监听器用来统计HttpSession的数量,也就不同浏览器访问的个数,它使用AtomicInteger对象来统计,并且将这个对象保存成ServletContext范围的属性,每当有个HttpSession被创建,这个AtomicInteger对象就加一,每当有个HttpSession被销毁,这个AtomicInteger对象就减一,使用AtomicInteger是为了保证同步进行加减

访问http://jyx:8080/ServletDemo/countries.jsp效果
这里写图片描述
注意不同的浏览器访问才加1

**(2)HttpSessionBindingListener **
当有属性绑定或者解绑定到HttpSession时,这个监听器就会被调用

public class Product implements HttpSessionBindingListener {
	private String id;
	private String name;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	private double price;

	@Override
	public void valueBound(HttpSessionBindingEvent event) {
		String attributeName = event.getName();
		System.out.println(attributeName + " valueBound");
	}

	@Override
	public void valueUnbound(HttpSessionBindingEvent event) {
		String attributeName = event.getName();
		System.out.println(attributeName + " valueUnBound");
	}

}

##ServletRequest Listener
ServletRequestListener会监听ServletRequest 的创建和销毁

public class PerfStatListener implements ServletRequestListener{

	@Override
	public void requestDestroyed(ServletRequestEvent arg0) {
		ServletRequest servletRequest=arg0.getServletRequest();
		Long start=(Long) servletRequest.getAttribute("start");
		Long end=System.nanoTime();
	    //将servletRequest强制转换为HttpServletRequest
		HttpServletRequest httpServletRequest=(HttpServletRequest) servletRequest;
		String uri=httpServletRequest.getRequestURI();
		System.out.println("time taken to execute "+uri+
				":"+((end-start)/1000)+"micoseconds");
	}

	@Override
	public void requestInitialized(ServletRequestEvent arg0) {
		ServletRequest servletRequest=arg0.getServletRequest();
		//java中System.nanoTime()返回的是纳秒
		servletRequest.setAttribute("start", System.nanoTime());
	}

}

总结
这些监听器分为三类:application范围、session范围和request范围,可以通过两种方法注册监听器,在实现类使用@WebListener注解或者在部署描述文件中增加listener元素

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值