Servlet是什么
就是运行在服务器端的 Java小程序
Servlet执行步骤:
2) 服务器将请求信息发送至 Servlet;
3) Servlet 生成响应内容并将其传给服务器。响应内容动态生成,通常取决于客户端的请求;
4) 服务器将响应返回给客户端。
Servlet的生命周期
A.加载和实例化:在第一次请求Servlet的时候,Servlet容器会创建Servlet实例;
B.初始化:容器加载完Servlet后,必须先进行初始化,调用init方法;
C.Servlet初始化后,处于响应请求的就绪状态,如果有客户端请求发送,则调用Servlet实例的service()方法,并根据请求方式,调用 doPost 或者 doGet方法
D.最后,Servlet容器负责销毁Servlet实例,调用destroy方法。
注意:
对于多次请求,Server创建会创建新的请求和响应对象,但是只调用一次init方法;
一般关闭Server时,调用destroy方法。
Servlet的配置文件(初始化参数配置)
在web.xml中配置:
<servlet>
<servlet-name>InitConfigParam</servlet-name>
<servlet-class>com.practice.InitConfigParam</servlet-class>
<init-param>
<param-name>userName</param-name>
<param-value>xiao</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>22</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>InitConfigParam</servlet-name>
<url-pattern>/InitConfigParam</url-pattern>
</servlet-mapping>
注意:上下两个 <servlet-name> 的值必须保持一致,完全一样
<init-param>用来配置初始化参数,需要的时候才配置
ServletContext::
WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。
1> servletContext的作用:
a>获取全局的初始化参数
b>实现资源的共享
c>获取web资源
2>如何获取servletContext?
a>this.getServletConfig.getContext()
b>this.getContext()
3>如何实现资源的共享的呢?
ServletContext context = this.getServletContext();
//存入共享的数据
context.setAttribute("name", "haha");
在其它的Servlet中利用ServletContext对象获取共享的数据
/*获取ServletContext对象*/
ServletContext context = this.getServletContext();
//获取共享的数据
String name = context.getAttribute("name");
System.out.println("共享的内容值是:"+name);
核心的类与接口
A. Servlet接口
B. GenericServlet抽象类
C. HttpServlet抽象类
D. ServletRequest,ServletResponse接口
E. ServletConfig接口
ServletContext getServletContext();
String getInitParameter(StringparaName);
F. HttpServletRequest接口
String getParameter(String name);
String[] getParameterValues(String name);
setCharacterEncoding(String code);
RequestDispatcher getRequestDispatcher(String url);
setAttribute(String name,Object obj);
Object getAttribute(String name);
removeAttribute(String name);
String getContextPath();
String getRequestURI();
HttpSession getSession()/getSession(boolean flag);
Cookie[] getCookies();
G. HttpServletResponse接口
setContentType(String str);
PrintWriter getWriter();
sendRedirect(String url);
encodeURL(String url);
encodeRedirectURL(String url);
addCookie(Cookie cookie);
H. ServletContext接口
String getRealPath(String str);
setAttribute(String name,Object obj);
Object getAttribute(String name);
removeAttribute(String name);
String getInitParameter(String name);
表单处理
A. 读取表单中的参数
//方式一
request.getParameter("username");
//方式二:如果一个名字对应多个参数值,例如checkbox
request.getParameterValues("checkbox"); //返回一个String类型的数组
//然后for循环输出
//也可用
Map map =request.getParameterMap();
String[] items =(String[])map.get("checkbox");
//当然 如果checkbox没有任何的值选定 要做个判断
if(s==null)..........
//方式三:如果servlet中不知道有哪几个参数名称
Enumeration e =request.getParameterNames()
String parameterName = null;
while(e.hasMoreElements()) {
parameterNames = (String) e.nextElement();
String values[] = request.getParameterValues(parameterName);
out.pritnln(parameterName);
//然后用for循环输出
}
//方式四:与3方法类似 道理一样 ;方法不同
Map map =request.getParameterMap()
Set set =map.keySet(); //set为所有参数名称
Iterator it = set.iterator();
String parameterNames = null;
while(it.hasNext()) {
parameterName=(String)it.next();
String values[] = request.getParameterValues(parameterName);
out.println(parameterName);
//然后用for循环输出
}
B. 处理中文乱码
1.用 post 方法提交表单
2.在接收参数的页面写上 response.setContentType("text/html;charset=utf-8");
3.接收到参数后进行编码转换 new String(request.getParameter("***").getBytes("iso-8859-1"), "utf-8");
Get请求与 post请求
默认是 get请求,表单中指定用 post则用 post请求
区别:
post 请求比 get 请求更安全,因为 get 请求会把提交的信息显示在地址栏 URL上,post 不会
get 请求传递的数据大小受到URL 长度的限制,多了会丢失数据,而 post 请求则几乎不受长度限制
get 请求的默认编码是 ASCII ,post 请求的默认编码是 ISO
post 发送数据并不提前转换编码,发送过来之后可以设置编码格式,而get发送数据是发送过来之前就已经编码了,并不能在接收数据的时候设置编码
post方式提交的数据可以设置请求编码格式
request.setCharacterEncoding("utf-8");
get方式提交的的数据需要做编码转换
//获取表单数据
String userName = request.getParameter("userName");
//转换字符编码格式
name = new String(userName.getBytes("iso-8859-1"),"utf-8");
转发(forward)与重定向(sendRedirect)
转发:客户端访问资源A,资源A让资源B给客户端构造了响应返回数据,使用RequestDispatcher对象的forward()
request.getRequestDispatcher("main.jsp").forward(request, response);
重定向:客户端访问资源A,资源A给浏览器构造了响应,告诉浏览器去请求资源B,资源B给浏览器构造了响应使用
response.sendRedirect("welcome.jsp");
区别:
跳转方式 请求转发 重定向
目标范围 只能转发到一个WEB应用的组件 可以是同一个WEB应用,也可以是其他站点
"/" 开头含义 表示WEB应用程序的根目录 表示整个WEB站点的根目录
地址栏显示URL 请求转发结束后,地址栏URL保持不变 重定向结束后,地址栏URL变成目标URL
请求对象和响应对象 只产生一次请求对象和响应对象 会产生两次请求对象和响应对象
资源A和资源B共享相同的请求和响应对象
Cookie
首先来了解什么是“会话”。会话是web技术中的一个术语,可以简单的理解为:用户打开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,这个过程称为一个会话。
如果在打开一个浏览器访问一个页面后,再打开一个浏览器访问同一个页面,那这就是有两个会话;而打开一个浏览器访问一个页面后,通过这个页面上的某个超链接是从新的浏览器打开的,那依然只算一个会话。
Cookie技术是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器时,就会带着各自的数据过去,这样web服务器处理的就是用户各自的数据了。
如何创建获得删除 cookie:以下是关键代码
String name = request.getParameter("username");
String passwd = request.getParameter("passwd");
Cookie cookie = new Cookie(name, passwd);//创建 cookie
response.addCookie(cookie);//添加到客户端
Cookie[] cookies = request.getCookies(); //获取 cookie
out.print("Cookie 中属性名和属性值的对应关系如下:<br/>");
if(cookies != null) {//循环输出
for(int i = 0; i < cookies.length; i++) {
Cookie ck = cookies[i];
String cookieName = ck.getName();
String cookieValue = ck.getValue();
out.println("name == " + cookieName + ",value == " + cookieValue);
}
}
cookie.setMaxAge(0);//删除 cookie
Session:
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,
由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中
的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
当用户打开浏览器,访问某个网站操作session时,服务器就会在服务器的内存为该浏览器分配一个session对象,该session对象被这个浏览器独占。
这个session对象也可以看做是一个容器,session默认存在时间为30min,可以修改。
得到session
// 返回这个request绑定的session对象,如果没有,则创建一个
HttpSession session = request.getSession();
// 返回这个request绑定的session对象,如果没有,则根据create的值决定是否创建一个
HttpSession session = request.getSession(boolean create)
//向session中添加属性
session.setAttribute(String name,Object val);
//从session中得到某个属性
String value = session.getAttribute(String name);
//从session中移除某个属性
session.removeAttribute(String name);
常用方法:
String getId();
String getRealPath(String str);
setAttribute(String name,Object obj);
Object getAttribute(String name);
setMaxInactiveInterval(int seconds);
invalidate();
ServletContext getServletContext();
禁止cookie后,如何继续使用 session
使用 Url 重写:
如何实现 url重写
encodeURL(String url);
encodeRedirectURL(String url);
1.jsp
<%
session.setAttribute("hi","Do you work or are you a student?");
%>
<a href="<%=response.encodeURL("2.jsp")%>">2.jsp</a>
2.jsp
<%=session.getAttribute("hi")%>
注意:
由于Cookie的禁用,这次请求协议头中虽然没有携带SessionID的信息,但SessionID的信息作为请求地址的一部分传到了服务器端,这就是URL重写的意义所在。
response的encodeURL方法将根据浏览器是否不支持Cookie决定是否将SessionID信息写入链接地址。
DAO
DAO是Data Access Object数据访问接口,数据访问:故名思义就是与数据库打交道。夹在业务逻辑与数据库资源中间。
DAO的功能:
1. DAO用来封装Data Source的..就比如,Connection conn = DAOFacotry.createConnection();
就可以把Driver. URL. username, passpword这一些放在DAO中
以后要更改数据库的类型.比如要把MySQL换成Oracle的话,只需要更改DAOFacory里面的getConnection()里面的Driver.URL.之类的。
2. DAO也是把对数据库的操作(比如最基本的CRUD操作)全部封装在里面..
比如说要要插入一个新的用户,那么在DAO中只需要提供一个insertUser(User user)这一个方法就可以了,具体的操作是在DAO中实现的。
那么对于要调用DAO的时候.只要知道insertUser(User)是用来插入一个新的用户,而不需要知道是如何实现的。
过滤器
web.xml中元素执行的顺序listener->filter->struts拦截器->servlet。
过滤器的概念
Java中的Filter并不是一个标准的Servlet,它不能处理用户请求,也不能对客户端生成响应。主要用于对HttpServletRequest进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链。
优点:过滤链的好处是,执行过程中任何时候都可以打断,只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容。而在实际使用时,就要特别注意过滤链的执行顺序问题
过滤器的作用描述
· 在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest。
· 根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。
· 在HttpServletResponse到达客户端之前,拦截HttpServletResponse。
· 根据需要检查HttpServletResponse,可以修改HttpServletResponse头和数据。
在web.xml中的配置
<!-- 编码过滤器 -->
<filter>
<filter-name>setCharacterEncoding</filter-name>
<filter-class>com.company.strutstudy.web.servletstudy.filter.EncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>setCharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 请求url日志记录过滤器-->
<filter>
<filter-name>logfilter</filter-name>
<filter-class>com.company.strutstudy.web.servletstudy.filter.LogFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>logfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 自定义过滤器-->
<filter>
<filter-name>IPFilter</filter-name>
<filter-class>com.practice.IPFilter</filter-class>
<init-param>
<param-name>ip</param-name>
<param-value>127.0.0.1</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>IPFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
监听器
Servlet监听器是Servlet规范中定义的一种特殊类,用于监听ServletContext、HttpSession和ServletRequest等域对象的创建与销毁事件,以及监听这些域对象中属性发生修改的事件。
监听对象:
1、ServletContext:application,整个应用只存在一个
2、HttpSession:session,针对每一个对话
3、ServletRequest:request,针对每一个客户请求
监听内容:创建、销毁、属性改变事件
监听作用:可以在事件发生前、发生后进行一些处理,一般可以用来统计在线人数和在线用户、统计网站访问量、系统启动时初始化信息等。
监听器的基本使用
创建步骤:
1、创建一个实现监听器接口的类
2、配置web.xml文件,注册监听器
<listener>
<listener-class>完整类名</listener-class>
</listener>
监听器的启动顺序:按照web.xml的配置顺序来启动
加载顺序:监听器>过滤器>Servlet
servlet的线程安全问题
1、servlet线程安全问题产生的原因在默认情况下,容器只会为每一个servlet类创建唯一的一个实例,当有多个请求到达容器,就有可能有多个线程同时访问同一个实例。
2、解决方式
1)使用局部变量:多线程不共享局部变量
2)使用同步代码块:要尽量缩小同步块的范围,否则影响效率
3)servlet的属性尽量设置成可读的,不要去修改。
4)不要再Servlet中创建自己的线程要完成某个功能,会导致线程执行复杂化,出现线程安全问题