servlet笔记—day03
监听器与过滤器
过滤器
在开发过程中经常使用,它可以过滤数据,和生活中的过滤器类似,例如自来水的过滤。过滤器主要过滤请求,当前端请求过来时,如果没有过滤器,直接进入服务器servlet中,加入过滤器,前端请求过来,先进入过滤器,过滤器过滤之后,才进入服务器。
使用场景:在编码格式转换时可以使用,前端可能存在编码格式不一样的情况,这时在过滤器拦截所有请求,然后进行转码
代码实现的过程:
1.需要类去实现filter接口,里面有三个方法init(),doFilter(),destroy()
2.在xml文件中配置过滤器或者注解的方式,或者直接创建Filter
配置过滤器在xml文件注册时,filter放在servlet上面,或者把dtd约束干掉
//xml
<filter>
<filter-name>UserFilter</filter-name>
<filter-class>com.zll.filter.UserFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UserFilter</filter-name>
<url-pattern>/*</url-pattern> //*代表过滤所有
</filter-mapping>
//注解的方式
@WebFilter(filterName="UserFilter",urlPatterns={"/*"})
注意:过滤器在tomcat容器启动时就已经启动,servlet在请求过来时启动,过滤器不仅要过滤请求,还要过滤响应。启动时,filter先启动,servlet后启动。过滤器的销毁在tomcat关闭的时候执行,servlet先关闭,filter后关闭。
过滤器的本质是一个回调函数的使用,过滤器的实现也就是通过回调函数来实现
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
System.out.println("进入到过滤的方法,可以过滤请求");
String priv=request.getParameter("priv");
System.out.println(priv);
if(priv.equals("hb")) {
response.getWriter().print("你是高风险地区人员,请原路返回");//后面的代码就不执行了
}else {
chain.doFilter(request, response);//继续往后走的方法
}
}
使用过滤器:前后端编码格式不一样,造成的乱码问题。
使用post方式乱吗,get方式不乱码
原因:编码和解码方式不一致
tomcat版本:8.5及以上版本
get请求方式,request对象使用的字符集默认为utf-8
post请求方式:request对象使用的编码方式为ISO8859-1
public class Filter01 implements Filter{
String encoding=null;
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
System.out.println("过滤器被创建,初始化方法被调用");
encoding=filterConfig.getInitParameter("encoding");//获取xml中的编码格式
System.out.println(encoding);
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
if(encoding!=null) {
request.setCharacterEncoding(encoding);
response.setCharacterEncoding(encoding);
response.setContentType("text/html;charset="+encoding);
}
chain.doFilter(request, response);
}
public void destroy() {
// TODO Auto-generated method stub
System.out.println("过滤器被销毁");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("请求已进入servlet");
String user=request.getParameter("user");
String password=request.getParameter("password");
System.out.println(user+"\t"+password);
}
<filter>
<filter-name>Filter01</filter-name>
<filter-class>com.zll.filter.Filter01</filter-class>
<!-- 初始化时创建一个变量encoding,后面就可以直接使用-->
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Filter01</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
监听器
监听器其实也是一个类,里面有8大接口,实现哪个接口就监听哪个内容,会监听各种内容。当你想要使用哪个监听器,直接选择即可,或者实现它的接口,也会在xml文件中注册
监听器的核心是观察者模式(就是一种设计模式)。
监听器的接口不一样,生命周期也不一样。例如ServletContextListener在tomcat启动时监听,tomcat关闭时销毁。ServletRequestListener在请求发送过来时监听,请求结束时销毁。
监听器的实现方式:
1.xml文件
2.注解
3.直接创建
<listener>
<listener-class>com.zll.filter.UserListener</listener-class>
</listener>
ServletContext application=this.getServletContext();
application.setAttribute("username", "zll");//添加
application.setAttribute("username", "lxy");//修改
application.removeAttribute("username");//移除
public class UserListener implements ServletContextListener,ServletContextAttributeListener {
public UserListener() {
// TODO Auto-generated constructor stub
}
public void contextDestroyed(ServletContextEvent sce) {
// TODO Auto-generated method stub
System.out.println("listener销毁");
}
public void contextInitialized(ServletContextEvent sce) {
// TODO Auto-generated method stub
System.out.println("启动了");
}
public void attributeAdded(ServletContextAttributeEvent event) {
// TODO Auto-generated method stub
System.out.println("application中添加内容时触发");
}
public void attributeRemoved(ServletContextAttributeEvent event) {
// TODO Auto-generated method stub
System.out.println("application中移除内容时触发");
}
public void attributeReplaced(ServletContextAttributeEvent event) {
// TODO Auto-generated method stub
System.out.println("application中修改内容时触发");
}
}
MVC模型
把项目进行划分
V—view,视图层,主要进行页面的展示
C—controller(控制),把所有的请求进行控制,进入到不同的方法中去执行
M—model(持久层),能够对数据库金星操作的内容就是持久层,进行数据库的连接,以及数据库的各种操作,都在里面写。
软件开发的过程中,除了使用MVC模型外,还有:
1.表示层(视图层——view):通过html,jsp等把数据进行页面的展示。
2.控制层(controller层):接收数据,处理数据,返回数据
3.业务层(service):通过控制层,进入到业务中
4.持久层(dao层):具体的数据库的操作
String日期转换为date类型
String date1=request.getParameter("date");
SimpleDateFormat simpleDeteFormat=new SimpleDateFormat("yyyy-MM-dd");
Date date=simpleDeteFormat.parse(date1);
session
session与cookie都是用来记录用户的信息的,比如用户登录成功之后,就可以把数据写入到session中,以后登录时判断有没有你的用户信息,有就直接登录,没有就重新登录。
session是一次会话,当前浏览器不关闭就一直存在,但是session有默认超时时间,一般为30分钟。当时间到期时,session就清除
服务器端为了保存用户的状态而创建的一个特殊的对象(即session对象)。
当浏览器第一次访问服务器时,服务器会创建session对象(该对象有一个唯一的id,一般称之为sessionId),接下来服务器会将sessionId以cookie的方式发送给浏览器。当浏览器再次访问服务器时,会将sessionId发送过来,服务器就可以依据sessionId找到对应sessinon对象。
设置超时时间:
1.session.setMaxInactiveInterval(30*60);//秒数,30分钟
2.xml文件中(分钟数)
<session-config>
<session-timeout>120</session-timeout>
</session-config>
删除session
session.invalidate();
session中的数据都是存储在服务器中,当服务器超时,会清除session,重启服务器时,也会清除session
session优点:可以放入的数据比较多,存储在服务器中,安全。在本地服务器是没有数据的。每次请求过来之后都会让服务器创建session,如果数据多了,服务器的压力会过大。
请求转发之后的内容还会继续执行,重定向后面的内容不会继续执行
session中的数据有时间限制,可以当做缓存来用
超时时间:(优先级从高到低)
1.java代码中设置
2.当前项目的web.xml中设置
3.tomcat中设置
@WebServlet("/OrderServlet")
public class OrderServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
int id=Integer.valueOf(req.getParameter("id"));
String name=req.getParameter("name");
int number=Integer.valueOf(req.getParameter("number"));
double price=Double.valueOf(req.getParameter("price"));
Order order=new Order(id, name, number, price);
HttpSession session=req.getSession();
session.setAttribute("order", order);
session.setMaxInactiveInterval(30);
req.getRequestDispatcher("/GetOrderServlet").forward(req, resp);//请求转发后面的内容还会执行
resp.sendRedirect("GetOrderServlet");//重定向之后的数据不会继续执行
System.out.println("*************");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
@WebServlet("/GetOrderServlet")
public class GetOrderServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session=req.getSession();
Order order=(Order) session.getAttribute("order");
System.out.println(order.getId()+"\t"+order.getName()+"\t"+order.getNumber()+"\t"+order.getPrice());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<center>
<h1>外卖订单</h1>
<form action="OrderServlet" method="post">
订单编号:<input type="text" name="id">
订单名称:<input type="text" name="name">
订单数量:<input type="text" name="number">
订单价格:<input type="text" name="price">
<input type="submit">
</form>
</center>
</body>
</html>
public class Order {
private int id;
private String name;
private int number;
private double price;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Order(int id, String name, int number, double price) {
super();
this.id = id;
this.name = name;
this.number = number;
this.price = price;
}
public Order() {
super();
}
}
cookie
cookie和服务器有关系,它返回的sessionid是存储在cookie中的,但是把数据存储在客户端的浏览器中,它占用浏览器的空间,它的信息都在本地存储。cookie的功能类似于生活中的会员卡。
当浏览器访问服务器的时候,服务器会产生一个sessionid,这个sessionid就是我们存储会话的时候的那个id, 同时他也会把这个sesssionid发到客户端上,客户端把serssionid 存储到cookies里,当你下一次请求的时候,浏览器会带着这个sessionid 往上走。服务就会对比这个id,如果有就进行相关的操作。
类似我们在日常生活中使用的用户登录,用户登录判断是在服务端进行判断,返回一个sessionid给客户端浏览器中存储cookies, 过几天你又带着你的sessionid 到你的服务器,就可以直接登录。如果你换了机器,sessionid是没有的,需要你进行重新登录。
@WebServlet("/CookieServlet")
public class CookieServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
String uname=req.getParameter("uname");
String password=req.getParameter("password");
String ck=req.getParameter("ck");
System.out.println(uname+"\t"+password+"\t"+ck);
if("on".equals(ck)) {//记住密码被选中,写入数据到cookie
Cookie cookie=new Cookie("users",uname+"--"+password);
cookie.setMaxAge(60);//秒
resp.addCookie(cookie);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<%
String names="";
String pwd="";
//取出Cookie
Cookie [] c=request.getCookies();
for(int i=0;i<c.length;i++){
if(c[i].getName().equals("users")){
//存着数据(用户名+密码)
names=c[i].getValue().split("--")[0];
pwd=c[i].getValue().split("--")[1];
//再一次的存起来(备用)
request.setAttribute("xiaoming",names);
request.setAttribute("mima", pwd);
}
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="CookieServlet" method="post">
用户名:<input type="text" name="uname" id="uname" value=${xingming }><br>
密码:<input type="password" name="password" id="password" value=${mima }><br>
<input type="checkbox" name="ck">记住用户名和密码<br>
<input type="submit" value="登录">
</form>
</body>
</html>