Servlet进阶API&过滤器&监听器

1Servlet API

1.ServletConfig接口

Web容器启动后会会读取Servlet设置信息,将Servlet类加载并实例化,每一个Servlet设置信息会产生一个ServletConfig对象,而后调用Servlet的init()方法并将ServletConfig对象当作参数传入。

GenericServlet类

GenericServlet接口类同时继承Servlet接口和SevletConfig接口.

1).ServletConfig对象

GenericServlet主要的目的,就是将初始Servlet调用init()方法传入的ServletConfig封装起来。

private transient ServletConfig config;
public void init(ServletConfig config) throw ServletException{
	this.config=config;
	this.init();
}
public void init() throws ServletException{
}	 

GenericServlet在实现Servlet的init()方法时,也调用了另一个无参数的init()方法,在编写Servlet时,如果有一些初始动作时,可以重新定义这个无参数的init()方法,而不是直接重新定义有ServletConfig参数的init()方法。

2).使用ServletConfig设置Servlet初始参数

	@WebServlet(name="ServletConfigDemo",urlPatterns={"/conf"},
		initParams={
			@WebInitParam(name="PARAM1",value="VALUE1"),
			@WebInitParam(name="PARAM2",value="VALUE2")
`		}
	)
	public class ServletConfigDemo extends HttpServelt(HttpServlet req
									HttpServletResponse resp){
		private String PARAM1;
		private String PARAM2;
		//初始化方法中取得初始参数
		public void init( ) throws ServeltException{
			PARAM1=getServeltConfig().getInitParameter("PARAM1");
			PARAM2=getServeltConfig().getInitParameter("PARAM2");
		}
	...
	}

GenericServlet定义了一些方法将ServletConfig封装起来,便于获取设置信息,所以取得Servlet初始参数的代码也可以写为:

@WebServlet(name="ServletConfigDemo",urlPatterns={"/conf"},
		initParams={
			@WebInitParam(name="PARAM1",value="VALUE1"),
			@WebInitParam(name="PARAM2",value="VALUE2")
`		}
	)
	public class ServletConfigDemo extends HttpServelt(HttpServlet req
									HttpServletResponse resp){
		private String PARAM1;
		private String PARAM2;
		//初始化方法中取得初始参数
		public void init( ) throws ServeltException{
			PARAM1=getInitParameter("PARAM1");
			PARAM2=getInitParameter("PARAM2");
		}
	...
	}

3)在web.xml中设置Servelt 初始参数

	<Servelt>
		<Servelt-name>ServletConfigDemo</Servelt-name>
		<Servelt-class>cc.ophenhome.ServletConfigDemo</Servelt-class>
		<init-param>
			<param-name>PARAM1<param-name>
			<param-value>VALUE1<param-value>
		</init-param>
		<init-param>
			<param-name>PARAM2<param-name>
			<param-value>VALUE2<param-value>
		</init-param>
	</Servelt>

2使用ServeltContext

1.getRequestDispatcher( )

该方法取得RequestDispatcher实例取得实例之后,就可以进行请求的转发或包含。
context.getRequestDispatcher( " /")
.forward(request,response);

2.getResourcePaths( )

想知道某个目录下有哪些文件

	for(String avatar: getServletContext( ).getResourcePaths("/avatars") ) {
		avatar= avatar.repalceFirst("/","");
		...
	}

3.getResourceAsStream( )

读取应用程序中某一个文件内容

	InputStream in =  getServletContext( ).getResourceAsStream(" ");
	OutputSteam out = response.getOutputStream( );
	writebytes(in,out);

2. 过滤器

在多个页面需要统一执行的代码,可以通过过滤器的 web 组件来完成

英文 Filter

1) 定义过滤器

@WebFilter(urlPattern="要过滤哪些路径")
class 过滤器类 implements Filter {

    // 初始化操作
    public void init() { }

    // 销毁操作
    public void destroy() { }

    // 过滤方法          子类对象                子类对象                    过滤器链
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain ) throws ... {
        // 要统一执行的代码
        //chain.doFilter(request, response); // 调用此方法,让请求继续前进
    }
}

2) 过滤路径格式

  1. 精确匹配 /servlet1, 只会进入servlet1之前进入过滤器
  2. 后缀匹配 *.jsp , 只要请求的后缀是 jsp 结尾的,就会进入过滤器
  3. 前缀匹配 /user/* , 例如 /user/insert /user/update, 都会经过此过滤器

只要过滤器的路径与目标路径匹配,这个过滤器就会被执行,因此,在请求前进的过程中会经过多个过滤器

顺序和过滤器的名字有关, 按名字排序

3) request和response的类型转换

filter中的request,response 声明的是父类型,有些方法没有,需要转为子类型对象(实际就是子类对象,可以安全转换)

HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse) response;

4) 过滤器的应用

  1. post 请求的中文乱码,可以采用字符编码过滤器来解决
    req.setCharacterEncoding(“解码字符集”);
    req.getParameter()

  2. 登录检查过滤器 (见 cookie和 session的代码)
    /*
    req.getRequestURI 排除一些特殊的路径

    /user/insert.jsp
    重定向到 index.jsp 如果没有加/ 是相对路径
    http://localhost:8080/user/index.jsp

    如果加了 / ,就是相对于主机名和端口号 也就是直接在路径前加 http://localhost:8080

    结论:如果路径中有多层目录,建议以 / 写一个完整路径

  3. cookie 自动登录过滤器

在 LoginServlet 中登录成功后,补充代码

// 如果勾选了 自动登录
String autoLogin = req.getParameter("autoLogin");
if(autoLogin != null && autoLogin.equals("true")) {
    Cookie cookie = new Cookie("up", username + ":" + password);
    cookie.setMaxAge(24 * 3600);
    resp.addCookie(cookie);
}

在 LoginFilter 过滤器中补充代码:

// 找到 up cookie
Cookie[] cookies = req.getCookies();
Cookie up = null;
for(Cookie c : cookies) {
    if (c.getName().equals("up")) {
        up = c;
        break;
    }
}
if(up != null) {
    String[] split = up.getValue().split(":");
    String name = split[0];
    String password = split[1];
    // 验证cookie 用户名密码是否正确
    User user = userDao.findByUsername(name);
    if(user!=null && user.getPassword().equals(password)) {
        // 正确了,向 session中存入登录标记并放行
        req.getSession().setAttribute("username", username);
        chain.doFilter(req, resp);
        return;
    }
}

在注销时:

// 删除 自动登录 cookie
Cookie up = new Cookie("up", "");
up.setMaxAge(0);
resp.addCookie(up);

3. 监听器

Listener 没有路径,特定事件发生时,会执行监听器代码

  • ServletRequestListener 在请求对象初始化和销毁时
  • HttpSessionListener 在 session 对象创建后和销毁时
  • ServletContextListener application 对象创建和销毁时
public interface ServletContextListener extends EventListener{
	public void contextInitialized(ServletContextEvent sce);
	public void contextDestroyed(ServletContextEvent sce);
}
  • ServletRequestAttributeListener 请求中作用域变量发生改变时
  • HttpSessionAttributeListener session 中作用域变量发生改变时
  • ServletContextAttributeListener application 中作用域变量发生改变时
public interface ServletContextAttributeListener extends EventListener{
	public void attributeAdded(ServletContextAttributeEvent scab);	
	public void attributeRemoved(ServletContextAttributeEvent scab);	
	public void attributeReplaced(ServletContextAttributeEvent scab);	
 }
  • HttpSessionActivationListener 在session 钝化(内存存入磁盘)和活化(从磁盘恢复到内存)
    session 中存储对象,对象要实现 Serializable 接口
  • HttpSessionBindingListener
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值