系列文章目录
目录
前言
JSP的根基是Java Servlet技术,该技术的核心就是在Tomcat服务器端创建响应用户请求的对象,被创建的对象习惯上被称为一个servlet。
一、servlet的部署、创建与运行
Java Servlet的核心思想是在Tomcat服务器端创建响应用户请求的servlet对象,简称servlet。
1.源文件及字节码文件
①servlet类
写一个创建servlet的类就是编写一个特殊类的子类,这个特殊类就是javax.servlet.http包中的HttpServlet类。HttpServlt实现了Servlet接口,实现了响应用户的方法。HttpServlet的子类被习惯称作一个Servlet类,这样的类创建的对象习惯地被称作一个servlet。
②字节码文件的保存
保存java源文件时,保存文件类型选择为所有文件,将编码选择为ANSI。
2.编写部署文件web.xml
Servlet类的字节码文件保存到指定的目录后,必须为Tomcat服务器编写一个部署文件,只有这样,Tomcat服务器才会用Servlet类创建servlet对象。该部署文件是个XML文件,名字必须是web.xml。
①根标记
xml文件必须有一个根标记,web.xml文件的根标记是web-app,跟标记web-app的开始标签是<web-app>,结束标签是</web-app>,开始标签和结束标签之间的内容称作根标记的内容。
②servlet标记及子标记
servlet标记需要有两个子标记:servlet-name和servlet-class,其中servlet-name标记的内容是Tomcat服务器创建的servlet名字,servlet-class标记的内容告知Tomcat服务器用哪个Servlet类来创建servlet。
③servlet-mapping标记及子标记
servlet-mapping标记需要有两个子标记:servlet-name和url-pattern,其中,servlet-name标记的内容是Tomcat服务器创建的servlet的名字。url-pattern标记用来指定用户用怎样的URL格式来请求servlet。
3.servlet的创建与运行
当用户请求Tomcat服务器运行一个servlet时,必须根据web.xml文件中标记url-pattern指定的格式输入请求。
4.向servlet传递参数的值
在请求一个servlet时,可以在请求的url-pattern中额外加入参数及其值,格式是: url-pattern?参数1=值&参数2=值 那么被请求的servlet就可以使用reques对象获取参数的值,格式是: request.getParameter(参数n)
package ch4_Person; import javax.imageio.ImageIO; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.awt.geom.Ellipse2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; public class Example extends HttpServlet { @Override public void init(ServletConfig config) throws ServletException { super.init(config); } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); double width = Double.parseDouble(req.getParameter("width")); double height = Double.parseDouble(req.getParameter("height")); resp.setContentType("image/jpeg"); Ellipse2D ellipse = new Ellipse2D.Double(400 - width / 2, 300 - height / 2,width,height); BufferedImage image = getImage(ellipse); try{ OutputStream outClient = resp.getOutputStream(); boolean boo = ImageIO.write(image,"jpeg",outClient); } catch(Exception exp){} } BufferedImage getImage(Shape shape){ int width = 800, height = 600; BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); g.fillRect(0,0,width,height); Graphics2D g_2d = (Graphics2D)g; g_2d.setColor(Color.blue); g_2d.fill(shape); return image; } }<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>lookPic</servlet-name> <servlet-class>ch4_Person.Example</servlet-class> </servlet> <servlet-mapping> <servlet-name>lookPic</servlet-name> <url-pattern>/lookPic</url-pattern> </servlet-mapping> </web-app>
二、servlet工作原理
servlet由Tomcat服务器负责管理,Tomcat服务器通过读取web.xml,然后创建并运行servlet。
1.servlet对象的生命周期
一个servlet的生命周期主要由下列三个过程组成: ①初始化servlet。servlet第一次被请求加载时,服务器初始化这个servlet,即创建一个servlet,这个servlet调用init方法完成必要的初始化工作。 ②新诞生的servlet再调用service方法响应用户的请求。 ③当服务器关闭时,调用destroy方法销毁servlet。
2.init方法
该方法是HttpServlet类中的方法,可以在子类中重写这个方法。 public void init(ServletConfig config) throws ServletException 该方法在执行时,服务器会把一个ServletConfig类型的对象传递给init方法,这个对象就被保存在servlet中,直到servlet被销毁。
3.service方法
该方法是HttpServlet类中的方法,可以在子类中直接继承该方法或重写这个方法。 public void service(HttpServletRequest request, HttpServletResponse response) throw ServletException, IOException 当servlet成功创建和初始化之后,调用service方法处理用户的请求并返回响应。
4.destroy方法
该方法是HttpServlet类中的方法,子类可以直接继承这个方法,一般不需要重写。 public destroy() 当Tomcat服务器终止服务时,destroy方法会被执行,销毁servlet。
三、通过JSP页面访问servlet
按照部署文件web.xml给出的servlet的url-pattern,用户除了可以在浏览器输入url-pattern请求运行一个servlet歪,也可以通过JSP页面来请求一个servlet。
1.通过表单向servlet提交数据
Web服务目录下的JSP页面都可以通过form表单请求该Web服务目录下的某个servlet。 <form action="url-pattern中配置的值" ?参数1=值&参数2=值></form> 通过JSP页面访问servlet的好处是,JSP页面可以负责页面的信息显示,信息的有关处理交给servlet去完成。
2.通过超链接访问servlet
JSP页面可以使用超链接去请求某个servlet。 <a href="url-pattern中配置的值"></a>
<%@ page contentType="text/html" %> <%@ page pageEncoding="utf-8" %> <HTML> <bodgy bgcolor="#ffccff"> <style> #textStyle { font-family: 宋体; font-size: 36px; color: blue } </style> <%request.setCharacterEncoding("utf-8");%> <HTML> <body bgcolor="#ffccff"> <form action="computeBill?discount=6" id="textStyle" method="post"> 输入账单:<br> <textArea name="billMess" rows="5" cols="30"></textArea> <br><input type="sumbit" value="提交"> </form> </body> </HTML>package ch4_Person; import com.sun.corba.se.impl.ior.ObjectIdImpl; import javax.imageio.ImageIO; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.awt.geom.Ellipse2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Example extends HttpServlet { @Override public void init(ServletConfig config) throws ServletException { super.init(config); } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); out.println("<html><body bgcolor = yellow>"); String discountMess = req.getParameter("discount"); double discount = Double.parseDouble(discountMess); String billMess = req.getParameter("billMess"); if(billMess == null){ out.print("没有账单"); return; } double bill = getPriceSum(billMess); double billDiscount = bill * (discount / 10); out.print("<h2>" + billMess + "<br>消费:" + bill + "元"); out.print("优惠" + discount + "折<br>后的金额:" + billDiscount + "元"); out.print("</h2></body></html>"); } public double getPriceSum(String input){ Pattern pattern; Matcher matcher; String regex = "-?[0-9][0-9]*[.]?[0-9]*"; pattern = Pattern.compile(regex); matcher = pattern.matcher(input); double sum = 0; while(matcher.find()){ String str = matcher.group(); sum += Double.parseDouble(str); } return sum; } }<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>computeBill</servlet-name> <servlet-class>ch4_Person.Example</servlet-class> </servlet> <servlet-mapping> <servlet-name>computeBill</servlet-name> <url-pattern>/computeBill</url-pattern> </servlet-mapping> </web-app>
四、共享变量
Servlet类是HttpServlet的一个子类,在编写子类时就可以声明某些成员变量,那么,请求servlet的用户将共享该servlet的成员变量。
<%@ page contentType="text/html" %> <%@ page pageEncoding="utf-8" %> <HTML> <bodgy bgcolor="#ffccff"> <style> #textStyle { font-family: 宋体; font-size: 36px; color: blue } </style> <%request.setCharacterEncoding("utf-8");%> <HTML> <body bgcolor="#ffccff"> <a href="computePI" id="textStyle">参与计算PI的值</a> </body> </HTML>package ch4_Person; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class Example extends HttpServlet { double sum = 0, i = 1, j = 1; int number = 0; @Override public void init(ServletConfig config) throws ServletException { super.init(config); } @Override protected synchronized void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); out.println("<html><body bgcolor=cyan>"); number++; sum = sum + i / j; j = j + 2; i = - i; out.println("<h1>servlet:" + getServletName() + "已经被请求了" + number + "次"); out.println("<br>现在PI的值是:"); out.println(4 * sum); out.println("</h1></body></html>"); } }<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>computePI</servlet-name> <servlet-class>ch4_Person.Example</servlet-class> </servlet> <servlet-mapping> <servlet-name>computePI</servlet-name> <url-pattern>/computePI</url-pattern> </servlet-mapping> </web-app>
五、doGet方法和doPost方法
实际上HttpServlet类所给出的service方法的功能是检查HTTP请求类型,并在service方法中更具用户的请求方式,在service方法中对应地调用doGet或doPost方法。如果不重写service方法,就需要在Servlet类中重写doGet或doPost方法来响应用户的请求。
<%@ page contentType="text/html" %> <%@ page pageEncoding="utf-8" %> <HTML> <bodgy bgcolor="#ffccff"> <style> #textStyle { font-family: 宋体; font-size: 36px; color: blue } </style> <%request.setCharacterEncoding("utf-8");%> <HTML> <body bgcolor="#ffccff"> <form action="sumORproduct" id="textStyle" method="post"> 输入数字,用逗号分隔提交给servlet(post方式): <br><input type="text" name="number"/> <input type="submit" value="提交"/> </form> <form action="sumORproduct" id="textStyle" method="get"> 输入数字,用逗号分隔提交给servlet(get方式): <br><input type="text" name="number"/> <input type="submit" value="提交"/> </form> </body> </HTML>package ch4_Person; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class Example extends HttpServlet { double sum = 0, i = 1, j = 1; int number = 0; @Override public void init(ServletConfig config) throws ServletException { super.init(config); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); req.setCharacterEncoding("utf-8"); PrintWriter out = resp.getWriter(); out.println("<html><body bgcolor=cyan>"); String s = req.getParameter("number"); String []a = s.split("[,,]+"); double sum = 0; for(String item : a){ if(item.length() >= 1){ sum += Double.parseDouble(item); } } out.print("<h2>用户的请求方式是" + req.getMethod() + "<br>"); for(String item : a){ if(item.length() >= 1){ out.print(item + " "); } } out.print("<br>的和是" + sum); out.println("</h2></body></html>"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); req.setCharacterEncoding("utf-8"); PrintWriter out = resp.getWriter(); out.println("<html><body bgcolor=cyan>"); String s = req.getParameter("number"); String []a = s.split("[,,]+"); double product = 1; for(String item : a){ if(item.length() >= 1){ sum += Double.parseDouble(item); } } out.print("<h2>用户的请求方式是" + req.getMethod() + "<br>"); for(String item : a){ if(item.length() >= 1){ out.print(item + " "); } } out.print("<br>的乘积是" + sum); out.println("</h2></body></html>"); } }<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>sumORproduct</servlet-name> <servlet-class>ch4_Person.Example</servlet-class> </servlet> <servlet-mapping> <servlet-name>sumORproduct</servlet-name> <url-pattern>/sumORproduct</url-pattern> </servlet-mapping> </web-app>
六、重定向与转发
重定向的功能是将用户从当前页面或servlet定向到另一个JSP页面或servlet。转发的功能是将用户对当前JSP页面或servlet的请求转发给另一个JSP页面或servlet。
1.sendRedirect方法
当用户请求一个servlet时,该servlet在处理数据后,可以使用重定向方法将用户重新定向到另一个JSP页面或servlet。重定向方法仅仅是将用户从当前页面或servlet定向到另一个JSP页面或servlet,但不能将用户对当前页面或servlet的请求转发给所定向的资源。
2.forward方法
RequestDispatcher对象可以把用户对当前JSP页面或servlet的请求转发给另一个JSP页面或servlet,而且将用户对当前JSP页面或servlet的请求传递给转发到JSP页面或servlet。 ①得到RequestDispatcher对象。 public RequestDispatcher getRequestDispatcher(String path) ②转发 void forward(Servlet request, ServletResponse response) throws ServletException, ava.io.IOException
3.二者的区别
转发和重定向方法不同的是,用户可以看到转发到JSP页面或servlet的运行效果,但是,在浏览器的地址栏中不能看到forward方法转发到JSP页面的地址或servlet的地址,用户在浏览器的地址栏中所看到的人让是当前JSP页面的URL或servlet的url-pattern。如果此时刷新浏览器,那么请求将是当前的JSP页面或servlet。
4.使用转发的好处
使用转发技术可以让JSP页面和处理数据的servlet解耦,JSP页面只需和处理转发的servlet打交道。
七、使用session
用户在访问一个Web服务目录期间,Tomcat服务器为该用户分配一个session对象,Tomcat服务器可以在各个页面以及servlet中使用这个session记录用户的相关信息,而且Tomcat服务器保证不同用户的session对象互不相同。访问某个Web服务目录的用户,在不同的servlet中获取的session对象是完全相同的,不同的用户的session对象互不相同。
<%@ page contentType="text/html" %> <%@ page pageEncoding="utf-8" %> <style>#textStyle { font-family: 宋体; font-size: 36px; color: blue } </style> <HTML> <body bgcolor=#ffccff> <% session.setAttribute("message","请您猜字母"); session.setAttribute("count",0); char a[] = new char[26]; int m = 0; for(char c = 'a'; c <= 'z'; c++){ a[m] = c; m++; } int randomIndex = (int)(Math.random() * a.length); char ch = a[randomIndex]; session.setAttribute("savedLetter",new Character(ch)); %> <h3>访问或刷新该页面可以随机得到一个英文字母。 <br>单击超链接去猜出这个字母:<br> <a href="test1.jsp">去猜字母</a> </h3> </body> </HTML><%@ page contentType="text/html" %> <%@ page pageEncoding="utf-8" %> <HTML> <bodgy bgcolor="#ffccff"> <style> #textStyle { font-family: 宋体; font-size: 36px; color: blue } </style> <% String message = (String)session.getAttribute("message"); %> <HTML> <body bgcolor="#ffccff"> <table border="1"> <form action="guess" method="post"> <tr><td id="textStyle">输入您的猜测(a-z之间的字母):</td> <td><input type="text" name="clientGuessLetter" size="10"/></td> <td><input type="submit" value="提交"/></td> </tr><td>提示信息:</td> <td><%= message %></td> </form> <form action="test.jsp" method="post"> <tr><td>单击按钮重新开始:</td></tr> <td><input type="submit" value="随机得到一个字母"/></td> </form> </table> </body> </HTML>package ch4_Person; import javax.servlet.GenericServlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; public class Example extends HttpServlet { @Override public void init(ServletConfig config) throws ServletException { super.init(config); } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); req.setCharacterEncoding("utf-8"); HttpSession session = req.getSession(true); String str = req.getParameter("clientGuessLetter"); Character guessLetter = str.trim().charAt(0); String count = (String)session.getAttribute("count"); int n = Integer.parseInt(count); Character savedLetter = (Character)session.getAttribute("savedLetter"); char realLetter = savedLetter.charValue(); if(Character.isUpperCase(guessLetter)){ guessLetter = Character.toLowerCase(guessLetter); } if(guessLetter < realLetter){ n++; session.setAttribute("message","第" + n + "次,猜小了"); session.setAttribute("count","" + n); resp.sendRedirect("test1.jsp"); } else if(guessLetter > realLetter){ n++; session.setAttribute("message","第" + n + "次,猜大了"); session.setAttribute("count","" + n); resp.sendRedirect("test1.jsp"); } else if(guessLetter == realLetter){ n++; session.setAttribute("message","猜对了,猜的次数:" + n); session.setAttribute("count","" + n); resp.sendRedirect("test1.jsp"); } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } }<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>guess</servlet-name> <servlet-class>ch4_Person.Example</servlet-class> </servlet> <servlet-mapping> <servlet-name>guess</servlet-name> <url-pattern>/guess</url-pattern> </servlet-mapping> </web-app>
总结
以上就是今天要讲的内容,本文仅仅简单介绍了Java Servlet基础的使用,要想更加深入的学习可以参考其他人的博客。