1.了解servlet
Servlet(Server Applet),全称Java Servlet,是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。
Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于 CGI,Servlet 有以下几点优势:
- 性能明显更好。
- Servlet 在 Web 服务器的地址空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。
- Servlet 是独立于平台的,即继承了java的跨平台性,因为它们是用 Java 编写的。
- 服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet 是可信的。
- Java 类库的全部功能对 Servlet 来说都是可用的。它可以通过 sockets 和 RMI 机制与 applets、数据库或其他软件进行交互。
servlet与jsp的区别:
早期servlet是将业务逻辑与网页代码写在一起,这给web开发带来诸多不便,后来将网页代码独立出来由jsp负责实现,因此jsp更具显示层的意义,而jsp文件在第一次请求时会被编译为servlet文件,再通过容器调用servlet进行处理
当servlet需要调用servlet api对http请求进行处理时,jsp页面的内置对象则可以直接提供帮助
2.servlet的架构(介于server和database之间,在MVC设计模式中,起控制器作用)
客户端发送请求到服务端中,服务端通过servlet调用业务逻辑层,实现连接数据库,对数据库中的数据进行增删改查等操作
3.servlet任务
- 读取客户端(浏览器)发送的显式的数据。这包括网页上的 HTML 表单,或者也可以是来自 applet 或自定义的 HTTP 客户端程序的表单。
- 读取客户端(浏览器)发送的隐式的 HTTP 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
- 处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。
- 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
- 发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。
4.servlet的生命周期
- 在servlet实例池中加载servlet类
在web容器(类似tomcat)启动或客户机第一次启动时,容器将servlet类加在到servlet实例池中 - 初始化(init)
只在servlet第一次被调用时创建servlet对象(只创建一次),而servlet的调用次数与浏览器无关,只与服务器有关,服务器重启后servlet也将重新初始化,
而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。 处理客户端请求(service)
service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。
每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。
service() 方法由servlet容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以,我们不用对 service() 方法做任何动作,只需要根据来自客户端的请求类型来重载 doGet() 或 doPost() 即可。
service()是GenericServlet中的方法,HttpServlet继承了GenericServlet,重载service(),以doGet() 和 doPost()等 方法来处理客户端请求,后面的接口实现类会具体介绍下面是service()方法的特征:
public void service(ServletRequest request,
ServletResponse response)
throws ServletException, IOException{
//service方法的执行代码
}
终止(destroy)
destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。
在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收,由java的垃圾回收机制回收
5.servlet的运行过程
6.servlet接口实现类
Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServlet、HttpServlet。(其中HttpServlet 则是继承了GenericServlet ,以doGet和doPost方法代替了service方法)
HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大。因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。
HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法。
7.servlet环境配置
由于客户端是通过URL地址访问web服务器中的资源,所以Servlet程序若想被外界访问,必须把servlet程序映射到一个URL地址上,这个可以通过配置文件或注解完成servlet 的映射。
- 配置文件
在项目中的WebContent/WEB-INF/中的 web.xml 文件中创建以下条目
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>servletTest</display-name>
<servlet>
<!--servlet的名字及类名-->
<servlet-name>Hello</servlet-name>
<servlet-class>com.servletTest.Hello</servlet-class>
</servlet>
<servlet-mapping>
<!--servlet的名字及映射路径-->
<servlet-name>Hello</servlet-name>
<url-pattern>/Hello</url-pattern>
</servlet-mapping>
</web-app>
- 注解方式
直接通过eclipse创建servlet文件,它会自动配置映射路径
/**
* Servlet implementation class CheckServlet
*/
//这个就是注解的映射路径
@WebServlet("/CheckServlet")
public class CheckServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
访问路径可以直接为:http://localhost:8080/项目名/CheckServlet
8.servletConfig对象
在Servlet的配置文件中,可以使用一个或多个<init-param>
标签为servlet配置一些初始化参数。 当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息
(注意:这里init初始化servletConfig是由父类调用init方法实现的,因此在子类继承时,不能重写init方法,否则会报空指针错误)
- 在web.xml中添加初始化参数
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>servletTest</display-name>
<servlet>
<servlet-name>doServlet</servlet-name>
<servlet-class>com.servletTest.doServlet</servlet-class>
<init-param>
<!--初始化参数-->
<param-name>color</param-name>
<param-value>red</param-value>
</init-param>
<!--servlet加载顺序-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>doServlet</servlet-name>
<url-pattern>/doServlet</url-pattern>
</servlet-mapping>
</web-app>
- 访问改初始化参数
//获取在config文件中初始化的对象
String color = getServletConfig().getInitParameter("color");
response.getWriter().write(color);
- 也可以直接在servlet中创建初始化参数
//初始化对象,并将初始化内容添加到config中
this.getServletConfig().getServletContext().setAttribute("name", "coco");
String name=(String) this.getServletConfig().getServletContext().getAttribute("name");
System.out.println(name);
9.servletContext对象
context对象的应用:
- 多个servlet通过servletContext实现数据共享
- 获取初始化参数,具体例子如第8点
- 实现servlet的转发
//跳转到hello.java的页面中
getServletContext().getRequestDispatcher("/hello").forward(req, resp);
- 读取资源文件(获取文件的真实路径或读取第三方文件)
如下例,在项目中写了一个properties文件用已保存用户的键对值(name=coco),通过访问这个servlet的servletContext对象获得该文件的真实路径
Properties pro=new Properties();
//获取这个properties的路径
pro.load(new FileReader (this.getServletContext().getRealPath("config.properties")));
//获取其中的键对值
response.getWriter().write(pro.getProperty("name"));
10.HttpServlet response和HttpServlet request
request和response对象即然代表请求和响应,那我们要获取客户机提交过来的数据,只需要找request对象就行了。要向客户机输出数据,只需要找response对象就行了
HttpServletRequest扩展 javax.servlet.ServletRequest 接口,为 HTTP servlet 提供请求信息。 servlet 容器创建 HttpServletRequest 对象,并将该对象作为参数传递给 servlet 的 service 方法(doGet、doPost,等等)。
HttpServletResponse扩展 ServletResponse 接口以提供特定于 HTTP 的发送响应功能。例如,该接口拥有访问 HTTP 头和 cookie 的方法,servlet 容器创建 HttpServletResponse 对象,并将该对象作为参数传递给 servlet 的 service 方法(doGet、doPost,等等)。
11.response的用法:
- 向系统输出内容(两种方式)(注意:解决乱码,即要求解码方式与编码方式一致)
response.getOutputStream().write("我是不会".getBytes());
response.getWriter().write("我是不会");
- 实现刷新重定向
//刷新本页面
response.getWriter().write(new Date().toLocaleString());
response.setHeader("refresh","1");
//重定向
response.setContentType("text/html;charset=utf-8");
response.getWriter().write(new Date().toLocaleString());
response.setHeader("refresh","1;url=http://www.baidu.com");
- 在html文件中也可以设置刷新和重定向:
<meta http-eqiv="refresh" content="1;url=http://www.baidu.com">
- 设置文件缓存(为保证效果,三个设置都要写)
//允许缓存,并设置缓存时间
response.setDateHeader("expires",new Date().getTime()+1000*60*60*24);
response.setHeader("Cache-control","no-cache");
response.setHeader("Pragma","no-cache");
response.getWriter().write(new Date().toLocaleString());
12. request的用法:
- 获取客户机信息
//获取客户端的请求路径
System.out.println(request.getRequestURL());
//获取请求中资源部分的路径
System.out.println(request.getRequestURI());
//请求中的参数部分
System.out.println(request.getQueryString());
//获取请求主机的ip地址
System.out.println(request.getRemoteAddr());
//返回请求方式
System.out.println(request.getMethod());
//获取当前web应用的虚拟目录名称
System.out.println(request.getContextPath());
//获取相对路径
String path=request.getContextPath();
response.sendRedirect(path+"/index.html");
- 防盗链(防止别人盗用链接,如果不是由指定的位置跳转,则必须转回指定位置)
//防盗链
//获取当前网页是从哪个地址跳转过来
String referer=request.getHeader("regerer");
//如果他的上一个跳转路径不是指定路径,则会先回到网站目录
if(referer==null||"".equals(referer)||!referer.equals("http://localhost:8080/request/index.html")){
response.sendRedirect("http:www.baidu.com");
}
- 获取表单数据
request.getParameter("name");
request.getParameter("password");
- 通过request的转发,可以实现数据资源的共享
request.setAttribute("name","coco");
request.getRequestDispatcher("/servlet1").forward(request,response);
//在servlet1中可以接受到转发过来的数据
request.getAttribute("name");
13.区分重定向和转发:
重定向:相当于客户端跳转,请求两次,响应两次,他显示的url是最后跳转的location
转发:相当于服务端跳转,请求一次,响应一次,他最后的url是一开始请求的location(建议:根据适当的情况,推荐使用转发实现跳转,减少请求次数)
- RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect 方法还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。
- 调用HttpServletResponse.sendRedirect方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;调用RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。
- HttpServletResponse.sendRedirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求;RequestDispatcher.forward方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。
- RequestDispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程;而HttpServletResponse.sendRedirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。
14.关于其中的编码方式
在http请求过程中,经常会遇到乱码问题,一般都是由编码方式和解码方式不同的原因在承德,一般的解决乱码的方法如下:
- 设置自己的编码方式(这里还需在指定浏览器的解码方式):
response.setCharacterEncoding("utf-8");
- 设置浏览器的解码方式(同时也指定了编码方式):
response.setContentType("text/html;charset=utf-8");
- 设置浏览器的解码方式:
response.setHeader("contentType", "text/html;charset=utf-8");
注意:getOutputStream和getWriter互相排斥,因为getOutputStream要将内容写入客户端时,需要刷新一次,但是刷新的同时也是响应行为,一次请求只能对应一次响应,所以两个不能同时用于一次请求中,互相排斥
15.servlet过滤器
Servlet过滤器就是服务器与客户端请求与响应的中间层组件,在实际项目开发中Servlet过滤器主要用于对浏览器的请求进行过滤处理,将过滤后的请求再转给下一个资源。
Filter是在Servlet 2.3之后增加的新功能,当需要限制用户访问某些资源或者在处理请求时提前处理某些资源的时候,就可以使用过滤器完成。过滤器是以一种组件的形式绑定到WEB应用程序当中的,与其他的WEB应用程序组件不同的是,过滤器是采用了“链”的方式进行处理的。(类似责任链的设计模式,一个过滤器放行了才能前往下一个过滤器或到达servlet中)
- 过滤器
在Servlet中,如果要定义一个过滤器,则直接让一个类实现javax.servlet.Filter接口即可,此接口定义了三个操作方法:
//初始化调用的方法
public void init(FilterConfig filterConfig) throws ServletException;
//拦截时调用的方法
//doFilter中有个chain.doFilter(request, response);的方法,表示可以将被拦截的请求传送过去
public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws IOException,ServletException;
//销毁时调用的方法
public void destroy()
- FilterChain接口的主要作用是将用户的请求向下传递给其他的过滤器或者是Servlet:
public void doFilter(ServletRequest request,ServletResponse response) throws IOException,ServletException
- 两种创建过滤器的方法:一种配置web.xml,一种直接创建filter(类似servlet的配置映射路径,不过filter的配置目的却是配置需要执行过滤动作的页面请求)
配置web.xml,其中的url-pattern表示拦截的网址
<filter>
<filter-name>FilterTest</filter-name>
<filter-class> FilterTest.FilterTest</filter-class>
</filter>
<!--这个是配置拦截路径-->
<filter-mapping>
<filter-name>FilterTest</filter-name>
<url-pattern>/JspTest.jsp</url-pattern>
</filter-mapping>
同servlet,可在web.xml中为过滤器配置初始化参数,并在过滤器中调用,这一点可以用于在确定某一网址要被拦截时,则将该网址加入初始化内容
@WebFilter("/*")
//默认访问该项目下面的所有资源都会被全部拦截
public class AllFilter implements Filter {
public AllFilter() {
// TODO Auto-generated constructor stub
}
当一个web应用被启动时,监听器最先被启动,之后是过滤器 ,最后是servlet(servlet只有在被调用时才会被初始化)
16.Cookie
- 添加cookie
//将登陆的时间添加到cookie中
Long date=new Date().getTime();
Cookie hc=new Cookie("time",date+"");
//使用表头信息添加
response.setHeader("Set-Cookie",hc);
//最常见的添加方法
response.addCookie(hc);
- 获取cookie的数组
//获取cookie数据组,同时取出名字为time的cookie
Cookie[] cookies=request.getCookies();
Cookie cook=null;
if(cookies!=null){
for(Cookie cookie:cookies){
if(cookie.getName().equals("time")){
cook=cookie;
}
}
}
- 设置cookie的保存时间
//设置cookie的存储时间,默认cookie的存储时间为一个会话时间
hc.setMaxAge(60*2);
- 设置某个网址中的路径(即可以设置前往某个路径时带着cookie)
//表示访问某个地址时带上cookie,默认的当前路径
//這获取的是web应用路径
String path=request.getContextPath();
hc.setPath(path);
response.getWriter().write(path);
在实际项目开发中,cookie存在诸多弊端,首先cookie不可靠,易被用户清除,一旦清除,就无法达到保存数据的目的,第二点是cookie由于是缓存在浏览器上的,为了不影响浏览器的运行,浏览器的cookie存储个数有限制,而且cookie的大小也必须小于4k,一旦超出该大小则会会被截断,而cookies数量超出限制,浏览器会删除原先的cookie
17.session
因此出现了session,session是基于cookie实现的,不同的是,session是将数据内容保存在服务器上,只是将sessionId存储在浏览器中,通过判断sessionId来判断session是否存储相应内容,而且后来出现的web storage进一步解决了本地存储的问题,但cookie作为http协议的扩展部分存在了
我们可知,在session中sessionId是基于cookie实现的,将sessionId保存在cookie中。这种绝大多数是用于加密的和小内容的数据存储,而现今大多数浏览器都会金庸cookie以提高安全性能,遇到这种情况,可通过url重写的方式,将sessionId附在url之后,达到传递session的效果
- 创建session
//创建session
HttpSession hs=request.getSession();
hs.setAttribute("a","b1");
- 调取session中的数据
//取出session中的数据,并判断是否为空,不为空则输出
HttpSession hc=request.getSession();
if(hc!=null){
response.getWriter().write((String)hc.getAttribute("a"));
}
- 销毁session
request.getSession().invalidate();
在jsp中调用页面会自动创建一个session,如果jsp只是单纯的html页面,不需要用到session,则将page信息中将session的值设为false,则禁止此页面调用session,减少内存的占用
学习到cookies,就还要联系到html5中新添加的本地存储功能webStorage,webStorage与session,cookie的具体区别在下面这篇博客文中有介绍:
http://www.tuicool.com/articles/fM32ier
18.servlet怎么获取文件
在servlet3.0出来之前,从表单中获取文件是一件较为复杂的事情,但是在servlet3.0中可以通过他的特性@MultiPartConfig来实现
这一点,在我的博文中也会有相应的介绍:
http://blog.csdn.net/yadicoco49/article/details/61416563