* 什么是 Servlet?
1. Servlet 的命名能够看出 sun 命名的特色,如 Applet 表示小应用程序;Scriptlet = Script + Applet,表示小脚本程序;一样 Servlet = Service + Applet,表示小服务程序
2. Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是做为来自 Web 浏览器或其余 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层
3. 使用 Servlet,能够收集来自网页表单的用户输入,能够与其它服务器资源(如数据库或基于 Java 的应用程序)进行通讯,还能够动态建立网页
4. Servlet 是和平台无关的服务器端组件(java 编写的,跨平台),它运行在 Servlet 容器中
* 什么是 Servlet 容器?
1. Servlet 容器主要是 JavaWeb 应用提供运行时环境,因此也能够称之为 JavaWeb 应用容器,或者 Servlet/JSP 容器
2. Servlet 容器负责 Servlet 和客户的通讯以及调用 Servlet 的方法,Servlet 和客户的通讯采用“请求/响应”的模式
3. Servlet 容器有哪些:目前最流行的 Servlet 容器软件包括: Tomcat、Jetty、Jboss 等
4. 下图显示了 Servlet 在 Web 应用程序中的位置
* Servlet 生命周期可被定义为从建立直到毁灭的整个过程,如下是 Servlet 遵循的过程:
1. Servlet 经过调用 init () 方法进行初始化
2. Servlet 调用 service() 方法来处理客户端的请求
3. Servlet 经过调用 destroy() 方法终止(结束)
4. 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的
* 注意:
1. Servlet 建立于用户第一次调用该 Servlet 的 URL 时,但能够在 web.xml 中配置 <load-on-startup>1</load-on-startup>,来指定 Servlet 在服务器第一次启动时被加载
2. init() 方法只会被调用一次,它在第一次建立 Servlet 时被调用。一般状况下你能够在 init() 方法中初始化数据库链接、打开文件以及其余相似的初始化活动
3. service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doHead、doPut、doDelete 等方法
4. destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用
5. destroy() 方法可让你的 Servlet 关闭数据库链接、中止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其余相似的清理活动
6. 在调用 destroy() 方法以后,Servlet 对象被标记为垃圾回收
* 下图显示了一个典型的 Servlet 生命周期方案
1. 第一个到达服务器的 HTTP 请求被委派到 Servlet 容器
2. Servlet 容器在调用 service() 方法以前加载 Servlet
3. 而后 Servlet 容器处理由多个线程产生的多个请求,每一个线程执行一个单一的 Servlet 实例的 service() 方法
* 1. 默认状况下,Servlet 应用程序位于路径 <Tomcat-installation-directory>/webapps/ROOT 下,且类文件放在 <Tomcat-installation-directory>/webapps/ROOT/WEB-INF/classes 中
* 2. 若是你有一个彻底合格的类名称 com.myServlet.Servlet类名,那么这个 Servlet 类必须位于 WEB-INF/classes/com/myServlet/Servlet类名.class 中
* 3. 把 Servlet类名.class 复制到 <Tomcat-installation-directory>/webapps/ROOT/WEB-INF/classes 中,并在位于 <Tomcat-installation-directory>/webapps/ROOT/WEB-INF/ 的 web.xml 文件中建立如下条目:
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class>com.myServlet.Servlet类名</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>myServlet</servlet-name>
<url-pattern>/Servlet别名</url-pattern>
</servlet-mapping>
* 4. 最后,使用 <Tomcat-installation-directory>\bin\startup.bat(在 Windows 上)或 <Tomcat-installation-directory>/bin/startup.sh(在 Linux/Solaris 等上)启动 Tomcat 服务器,最后在浏览器的地址栏中输入 http://localhost:8080/Servlet别名
* 若是是用 JavaWeb 建立的项目,则向浏览器发送的请求格式为:http://localhost:8080/项目名/Servlet别名
* 1. 200 OK:请求成功
* 2. 404 Not Found:服务器没法找到所请求的页面,可能缘由:
a. 在请求地址中 Servlet 的别名书写错误
b. 虚拟项目名称拼写错误
* 3. 405 Method Not Allowed:请求方式不容许
缘由:请求方式和 Servlet 中的方式不匹配所形成
解决:尽可能使用 service() 方法进行请求处理,尽可能不要在 service() 方法中调用父类 service() 方法( super.service(arg0, arg1);)
* 4. 500 Internal Server Error:内部服务错误,服务器遇到了一个意外的状况
缘由a:java.lang.ClassNotFoundException
解决:在 web.xml 中检验 Servlet 配置 <servlet-class>com.myServlet.Servlet类名</servlet-class> 中的路径是否拼写错误
缘由b:service() 方法体的代码执行错误致使
解决:根据错误提示对 service() 方法中的代码进行错误更改
* Request 对象学习: * 1. 做用:Request 对象中的封存了当前请求的全部请求信息 * 2. 使用: 获取请求头数据 req.getMethod();// 获取请求方式 req.getRequestURL();// 获取 URL req.getRequestURI();// 获取 URI req.getScheme();// 获取协议
获取请求行数据 req.getHeader(String name);// 获取指定的请求行信息
req.getHeaders(String name);// 获取指定请求头的全部信息的枚举集合 req.getHeaderNames();// 返回全部请求行的键名的枚举集合
获取用户数据(重点) req.getParameter(String name);// 获取指定的用户数据 req.getParameterValues(String name);// 返回同键不一样值的请求数据(复选框),返回 String 类型的数组 req.getParameterNames();// 返回全部用户请求数据的枚举集合 注意:若是要获取的数据不存在,不会报错,返回 null * 3. Request 对象由 Tomcat 服务器建立,并做为实参传递给处理请求的 Servlet 的 service() 方法
* 4. 解决请求乱码问题:
a.在 service() 方法中对获取的请求数据进行从新编码,如:
String uname = req.getParameter(“uname”);
uname = String(uname.getBytes("iso8859-1"), "utf-8");
b.Get 方式请求步骤(缺一不可):
1)在 service() 方法中使用:req.setCharacterEncoding("utf-8");
2)在 Tomcat 安装目录中的 conf 目录下找到 server.xml 文件,进行以下配置:
<Connector port="8888" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" useBodyEncodingForURI="true"/>
c.Post 方式请求:
只须要在 service() 方法中获取请求前使用:req.setCharacterEncoding("utf-8");
import java.io.IOException; import java.util.Enumeration; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class RequestServlet extends HttpServlet{ @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ //获取请求头数据 //获取请求方式 String method = req.getMethod(); System.out.println(method); //获取请求URL StringBuffer url = req.getRequestURL(); System.out.println(url); //获取URI String uri = req.getRequestURI(); System.out.println(uri); //获取协议 String h = req.getScheme(); System.out.println(h); //获取请求行数据 //获取指定的请求行信息 String value = req.getHeader("User-Agent"); System.out.print(value); //获取全部的请求行的键的枚举 Enumeration e = req.getHeaderNames(); while(e.hasMoreElements()){ String name = (String)e.nextElement(); String value02 = req.getHeader(name); System.out.println(name + ":" + value02); } //获取用户信息(重要) String name = req.getParameter("uname"); String password = req.getParameter("pwd"); System.out.println(name + ":" + password); //获取同键不一样值的请求数据(复选框),返回数组 String[] favs = req.getParameterValues("fav"); if(favs!=null){ for(String f : favs) System.out.println(f); } } }
* Response 对象学习:
* 1. 做用:Response 对象是用来响应数据到浏览器
* 2. 使用:
设置响应头
resp.setHeader(String name, String Value);// 在响应头中添加或更新信息,同键会覆盖
resp.addHeader(String name, String Value);// 在响应头中添加信息,不会同键覆盖
设置响应状态
resp.sendError(int num, String msg);
设置响应编码格式
resp.setContentType("text/html;charset=utf-8");
或者 resp.setHeader("content-type", "text/plain;charset=utf-8");
设置响应实体
resp.getWriter().write(String str);
* 3. service()方法中的通常编写流程:
1) 设置请求编码格式
req.setCharacterEncoding("utf-8");
2) 设置响应编码格式
resp.setContentType("text/html;charset=utf-8");
3) 获取请求信息
uname = req.getParameter("uname");
pwd = req.getParameter("pwd");
4) 处理请求信息
a.建立业务层对象
b.调用业务层对象的方法
5) 响应处理结果
resp.getWriter().write("....");
* 请求转发的学习:
* 1. 使用:
req.getRequestDispatcher("URL/URI").forward(req, resp);
如:req.getRequestDispatcher("/index.jsp").forward(req, resp);
* 2. 做用:
实现了多个 Servlet 联动处理请求,这样就能避免代码冗余,让不一样 Servlet 的职责更加明确
* 3. 特色:
a.一次请求,一个 Request 对象
b.浏览器地址信息不改变
* 4. 请求转发后直接用 return; 结束便可
* 5. 使用 Request 对象实现不一样 Servlet 的数据流转:
req.setAttribute(String name, Object value);
req.getAttribute(String name);
做用:在一次请求中实现不一样 Servlet 间的数据共享
* 重定向的学习:
* 1. 使用:
resp.sendRedirect("URL/URI");
如:resp.sendRedirect(req.getContextPath() + "/index.jsp");
* 2. 做用:
a.解决了 Servlet 当前没法进行处理请求的问题
b.解决了表单数据重复提交的问题
* 3. 特色:
a.两次请求,两个 Request 对象
b.浏览器地址栏信息改变
* 4. 时机:
a.若是请求中有表单数据,而数据比较重要,不宜重复提交,建议使用重定向
b.若是请求被 Servlet 接收后没法进行处理,建议使用重定向定位到能够处理的资源
* Cookie 学习:
* 1. Cookie 本质上是由服务器端生成并保存在用户浏览器(客户端)上的小文本文件
* 2. 做用:实现了一个用户发送不一样请求时的数据共享
* 3. 工做原理:用户第一次访问服务器时,服务器端会在响应中利用 Set-Cookie header 来建立一个 Cookie,发送给 User-Agent(通常是浏览器),浏览器会将 Cookie 的 key/value 保存到某个目录下的文本文件内,在下一次请求中经过 Cookie header 包含该 Cookie,而且把它返回至服务器,从而完成用户身份等信息的校验
* 4. Cookie 的两种储存方式:
a.临时存储:存储在浏览器的运行内存中,关闭浏览器就失效 b.定时存储:设置了 Cookie 的有效期,存储在了客户端的硬盘中,在有效期内符合路径要求的请求都会附带该 Cookie 里的信息 * 5. 使用: 1)建立 Cookie 对象 Cookie c = new Cookie(String name, String value); 2)设置和获取有效期限 c.setMaxAge(int seconds);// 单位是:秒
c.getMaxAge(); 3)设置和获取有效路径 c.setPath("URL/URI");
c.getPath(); 4)响应 Cookie 信息给客户端 resp.addCookie(c); 5)获取 Cookie 信息 Cookie[] cks = req.getCookies(); if(cks != null){ // 避免出现空指针异常 for(Cookie c : cks){ String name = c.getName(); String value = c.getValue(); } }
* 6. 注意:一个 Cookie 对象存储一条数据;多条数据,能够建立多个 Cookie 对象进行存储
/** * 模拟三天免登录 * * Cookie 信息校验 * a.判断请求中是否带 Cookie 信息 * b.若是没有则请求转发给登陆页面 * c.若是有则校验 Cookie 信息是否正确 * d.若是校验正确则直接响应主页面给用户 * e.若是不正确则请求转发给登陆页面 */ import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.pojo.User; import com.service.LoginService; import com.service.impl.LoginServiceImpl; public class CookieServlet extends HttpServlet { @Override protected void service(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{ //设置请求编码 req.setCharacterEncoding("utf-8"); //设置响应编码格式 resp.setContentType("text/html;charset=utf-8"); //获取请求信息,获取 Cookie 信息 Cookie[] cks = req.getCookies(); //处理请求信息 //遍历Coolie信息 if(cks!=null){//避免出现空指针异常 System.out.println("have cookies"); String uid = ""; for(Cookie c:cks){ if("uid".equals(c.getName())){ uid = c.getValue(); System.out.println(uid); } } //校验 UID 是否存在 if("".equals(uid)){ //请求转发 req.getRequestDispatcher("/login.jsp").forward(req,resp); return; }else{ //校验 UID 用户信息 //获取业务层对象 LoginService ls = new LoginServiceImpl(); User u = ls.checkUidService(uid); if(u!=null){ //登陆成功,响应主页面 resp.sendRedirect("/index.jsp"); }else{ //请求转发 req.getRequestDispatcher("/login.jsp").forward(req,resp); return; } } }else{ System.out.println("have no cookies"); //请求转发 req.getRequestDispatcher("/login.jsp").forward(req,resp); return; } } } import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.pojo.User; import com.service.LoginService; import com.service.impl.LoginServiceImpl; public class LoginServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 设置响应编码格式 resp.setContentType("text/html;charset=utf-8"); // 获取请求信息 String uname = req.getParameter("uname"); // 使用 String 进行从新编码,避免出现乱码 uname = new String(uname.getBytes("iso8859-1"), "utf-8"); String pwd = req.getParameter("pwd"); System.out.println(uname + ":" + pwd); // 处理请求信息 // 建立和获取业务层对象 LoginService impls = new LoginServiceImpl(); User u = impls.checkLoginService(uname,pwd); // 响应处理结果 if(u!=null){ // 建立 Cookie 信息实现三天免登录,注意:不要直接用 Cookie 存放用户密码 Cookie c = new Cookie("uid", u.getUid()+""); // 设置 Cookie 的有效期和有效路径 c.setMaxAge(3*24*3600); c.setPath("/login/ck"); // 添加 Cookie 信息 resp.addCookie(c); resp.getWriter().write("登陆成功!"); }else{ // resp.getWriter().write("登陆失败!"); // 请求转发: req.getRequestDispatcher("/login.jsp").forward(req,resp); return; } } }
* Session 对象学习: * 1. 做用:实现了一个用户发送不一样请求时的数据共享 * 2. 工做原理:用户第一次访问服务器时,服务器会建立一个 Session 对象,并将该 Session 对象的 JSESSIONID 使用 Cookie 技术存储到浏览器内存中,保证用户的其余请求都可以获取到同一个 Session 对象,也就实现了用户的不一样请求时的数据共享 * 3. 特色: a.由服务器建立 b.存储在服务器端 c.依赖 Cookie 技术
d.注意:JSESSIONID 存储在了 Cookie 的临时存储空间中,即浏览器运行内存中,浏览器关闭则失效 e.做用域为:一次会话,只要在 JSESSIONID 不失效和 Session 对象不失效的状况下为整个项目内
f.Session 对象的默认有效时间为30分钟,可经过 Tomcat 目录下 web.xml 中的 <session-timeout>30</session-timeout> 来修改默认时间 * 4. 使用: 1)建立/获取 Session 对象 HttpSession session = req.getSession(); a.若是请求中拥有 Session 的标识符(JSESSIONID),则返回其对应的 Session 对象 b.若是请求中没有 Session 的标识符(JSESSIONID),则建立新的 Session 对象,并将其 JSESSIONID 做为 Cookie 数据存储到浏览器内存中 c.若是 Session 对象失效了,也会从新建立一个 Session 对象,并将其 JSESSIONID 存储在浏览器内存中 2)设置和获取 Session 会话的有效时间 session.setMaxInactiveInterval(int seconds);// 单位为:秒
session.getMaxInactiveInterval(); a.注意:在指定的时间内 Session 对象没有被使用则失效,若是使用了则从新计时
b.可经过 Tomcat 目录下 web.xml 中的 <session-timeout>30</session-timeout> 来修改 Session 对象的默认时间 3)强制 Session 会话失效 session.invalidate(); 4)存储和获取 Session 数据 session.setAttribute(String name, Object value); session.getAttribute(String name);// 返回 Object 类型 a.注意:存储的动做和获取的动做能够发生在不一样的请求中,可是存储动做必定要先于获取动做
* 5. 使用时机:通常用户在登陆 Web 项目时会将我的信息存储到 Session 对象中,供该用户的其余请求使用 * 6. 如何判断 Session 是否失效? a.将用户请求中的 JSESSIONID 和后台获取到的 Session 对象的 JSESSIONID 进行比对 b.若是一致,则 Session 没有失效 c.若是不一致,则 Session 失效了,重定向到登陆界面,让用户从新登陆
* ServletContext 对象学习:
* 1. ServletContext 是一个全局的储存信息的空间,服务器开始就存在,服务器关闭才释放
* 2. 做用:实现了不一样的用户共享数据
* 3. 特色:
a.由服务器建立
b.存储在服务器端
c.全部用户共享
d.做用域为:整个项目内
e.生命周期为:服务器启动到服务器关闭
f.使用时机:涉及到不一样用户共享数据,而这些数据量不大,同时又不但愿写入数据库中,咱们就能够考虑使用 ServletContext
g.使用建议:由于 ServletContext 中的数据会长时间存储在服务器中,这样就会占用不少内存,所以在使用 ServletContext 时,建议不要往里面添加过大的数据!
* 4. 使用:
1)获取 ServletContext 对象
//第一种方式:
ServletContext sc = this.getServletContext();
//第二种方式:
ServletContext sc = this.getServletConfig().getServletContext();
//第三种方式:
ServletContext sc = req.getSession().getServletContext();
2)存储和获取 ServletContext 数据
sc.setAttribute(String name, Object value);
sc.getAttribute(String name);// 返回类型是 Object
a.注意:不一样的用户可使用 ServletContext 对象进行数据的存取,若是获取的数据不存在则返回 null
3)使用 ServletContext 对象获取全局的、整个 Web 应用的初始化参数
sc.getInitParameter(String name); // 根据键名返回 web.xml 中配置的全局初始化参数的 String 类型的值,若是数据不存在返回 null
sc.getInitParameterNames();// 返回键名的枚举(Enumeration)
* 5. 在 web.xml 配置全局的初始化参数
<context-param>
<param-name>name</param-name>
<param-value>value</param-value>
</context-param>
a.注意:一组 <context-param> 标签只能存储一组键值对,多组键值对能够配置多个 <context-param> 进行存储
b.做用:将静态数据和代码进行解耦
* 6. 获取 WebContent 目录下的资源的绝对路径
String path = sc.getRealPath("/index.jsp");// 参数为 Web 根目录下的路径
a.注意:ServletContext 只能获取在 Web 根目录下的文件的全路径
* 7. 获取 WebContent 目录下资源的流对象
InputStream is = sc.getResourceAsStream("/index.jsp")// 参数为 Web 根目录下的路径
a.注意:ServletContext 只能获取在 Web 根目录下的资源流对象
b.若是资源放在了 src 目录下,这时就不能用 ServletContext 来获取流对象了,必须使用类加载器获取():
InputStream is = this.class.getClassLoader().getResourceAsStream("database.properties");
c.若是资源尚未直接在 src 目录下,而是在 src 目录下的某个包下,此时类加载器要加上包的路径:
InputStream is = this.class.getClassLoader().getResourceAsStream("com/ncdx/database.properties");
* 8. 因为一个 Web 应用中的全部 Servlet 共享同一个 ServletContext 对象,所以 Servlet 对象之间能够经过 ServletContext 对象来实现通信,即多个 Servlet 能够经过 ServletContext 对象来实现数据间的共享
* 9. 为了方便你们理解,咱们将 ServletContext 和 Cookie、Session 作一个简单对比,以下图:
类加载器的默认读取路径是 src 根目录
* ServletConfig 对象学习: * 1. 问题:如何获取在 web.xml 中给每一个 Servlet 单独配置的初始化参数呢? * 2. 解决:使用 ServletConfig 对象 * 3. 使用: 1)获取 ServletConfig 对象
ServletConfig sc = this.getServletConfig(); 2)获取 web.xml 中的配置的初始化参数
sc.getInitParameter(String name);// 根据键名返回 web.xml 中配置的初始化参数的 String 类型的值,若是数据不存在返回 null
sc.getInitParameterNames();// 返回键名的枚举(Enumeration)
* 4. 在 web.xml 中为某个 Servlet 单独配置的初始化参数,如:
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
* 什么是 MVC 架构模式?
* 1. MVC 模式是 Model-View-Controller 的简称,是软件工程中的一种软件架构模式,分为三个基本部分,分别是:模型(Model)、视图(View)和控制器(Controller)
1)Controller:负责转发请求,对请求进行处理 2)View:负责界面显示 3)Model:业务功能编写,例如算法实现、数据库设计以及数据存取操做实现
* 2. MVC 设计理念是实现动做控制、数据处理、结果显示三者分离
* 3. MVC 模式在 Web 开发中有很大的优点,它完美规避了 JSP 与 Servlet 各自的缺点,让 Servlet 只负责业务逻辑部分,而不会生成 HTML 代码;同时 JSP 中也不会充斥着大量的业务代码,这样极大提升了代码的可读性和可维护性
* 4. MVC 模式的工做原理以下图所示
1)Web 浏览器发送 HTTP 请求到服务端,而后被 Controller(Servlet) 获取并进行处理(例如参数解析、请求转发)
2)Controller(Servlet) 调用核心业务逻辑——Model 部分,得到结果
3)Controller(Servlet) 将逻辑处理结果交给 View(JSP),动态输出 HTML 内容
4)动态生成的 HTML 内容返回到浏览器中显示