JSP核心基础——Servlet应用
来源:互联网 发布:php hmacsha256 编辑:程序博客网 时间:2024/06/05 19:59
1、Servlet概述
Servlet(Server Applet)是Java Servlet的简称,是小服务程序或服务连接器,用Java编写的服务器端程序,主要功能在于交互式地浏览和修改数据,生成动态Web内容。
狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
2、Servlet生命周期
- 首先当servlet第一次被调用的时候,会调用servlet的
init
方法,把servlet实例装载到内存中。 - 然后会调用
service
方法,当第二次servlet被访问的时候就会直接调用service函数,并创建一个新的线程,故Servlet是单实例多线程。 - 只有当web应用关闭,或者容器关闭,或者电脑关闭时候,才会调用
destroy
方法销毁servlet。
3、简单实例
3.1 编写Servlet代码
package servletdemo;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@WebServlet("/Hello")public class Hello extends HttpServlet { private static final long serialVersionUID = 1L; private String message; public Hello() { super(); } public void init() throws ServletException{ message = "Hello World"; } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<h1>"+"get:"+message+"</h1>"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<h1>"+"post:"+message+"</h1>"); }}
3.2 在web.xml文件内注册该Servlet
<servlet> <servlet-name>Hello</servlet-name> <servlet-class>servletdemo.Hello</servlet-class> </servlet><servlet-mapping> <servlet-name>Hello</servlet-name> <url-pattern>/servletdemo/Hello</url-pattern> </servlet-mapping>
其中servlet-name表示Servlet的名字(上下两个须一致),servlet-class要写Servlet类的路径(包名.类名),url-pattern表示用于访问的URL链接,可以自己定义路径(虚拟的),但必须以“/”开头。
注:修改一次web.xml,需重启服务器。
3.3 创建交互界面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Hello world!</title></head><body><h1>Servlet例子</h1><hr> <a href="servletdemo/Hello">get方式请求Hello</a><br /><br /> <form action="servletdemo/Hello" method="post"> <input type="submit" value="post方式请求Hello" /> </form></body></html>
此处链接要和web.xml中的url-pattern一致。
这里在eclipse内创建了jsp文件,但对于这种简单的内容完全可以用html文件代替。
3.4 运行该文件
方案一:在eclipse外面,Tomcat的HTTP端口为8008(server.xml中配置的),在浏览器输入: http://localhost:8008/users/WebContent/index.jsp
方案二:在eclipse内配置好Tomcat后,用里面的浏览器,此处配置的server.xml文件中HTTP端口为8080,故可以输入: http://localhost:8080/myweb/index.jsp
,myweb为web项目名称。
界面如下:
- 点击上面的链接:
- 点击下面的链接:
3.5 运行步骤
- 用户点击超链接向Servlet发送请求。
- 服务器在web.xml中的servlet-mapping寻找与该URL地址相对应的Servlet的名字。
- 根据Servlet的名字找到和该Servlet相关的处理类。
- 若该Servlet还不存在,则先装载一个servlet类并创建实例,调用init方法初始化然后再根据请求的方式不同确定是调用doGet还是doPost方法;若存在,则直接根据请求的方式不同确定是调用doGet还是doPost方法。
- 最后通过Response对象返回给客户端浏览器。
4、Servlet加载的几种方式
- Servlet容器启动时自动装载某些Servlet,实现它只需要在web.xml文件中的
<servlet></servlet>
之间添加以下代码:
<load-on-startup>1</load-on-startup>
其中,数字越小表示优先级越高(先产生,同等条件下先销毁)。
2. 客户端首次向某个Servlet发送请求。
3. Servlet类被修改后,Tomcat容器会自动重新装载Servlet。
5、Servlet表单处理
5.1 表单处理提交的类
package servletdemo;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@WebServlet("/LoginServlet")public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; public LoginServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().append("Served at: ").append(request.getContextPath()); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); String userid = request.getParameter("userid"); //获取name="userid"标签的值,没有则为null String passwd = request.getParameter("passwd"); //获取name="passwd"标签的值,没有则为null response.setContentType("text/html;charset=GBK"); //回复response对象的编码字符集为GBK if (passwd.equals("12345")) { out.println("<HTML>"); out.println("<title>Login Servlet</title>"); out.println("<body>"); out.println("Welcome,"+userid); out.println("</body>"); out.println("</HTML>"); }else { out.println("<HTML>"); out.println("<title>Login Servlet</title>"); out.println("<body>"); out.println("Login failure!"); out.println("</body>"); out.println("</HTML>"); } }}
5.2 登录界面
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Login page</title></head><body><h2>Login page</h2><form action="test" method="post"><table> <tr> <td>Name:</td> <td><input type="text" name="userid"/></td> </tr> <tr> <td>Password:</td> <td><input type="password" name="passwd"/></td> </tr></table><input type="submit" value="submit"></form></body></html>
5.3 web.xml配置文件
<servlet> <servlet-name>LoginServlet</servlet-name> <servlet-class>servletdemo.LoginServlet</servlet-class></servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/test</url-pattern></servlet-mapping>
5.4 运行效果
当密码为12345
时,点击submit,在web.xml中查找“/test”对应的Servlet名字,再跟据名字找到对应的类,调用类里面的post方法(第一次还要调用init方法),最后通过Response对象返回给客户端浏览器。
6、数据库操作
6.1 mysql命令行操作
- 建立数据库:
- 建立数据表
- 查看初始状态:
6.2代码准备
1. 访问与添加数据页面
SelectServlet.html
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Select</title><style type="text/css">table { font-family: verdana,arial,sans-serif; font-size:15px; color:blue; border-width: 1px; border-color: purple; border-collapse: collapse;}table td { border-width: 1px; padding: 8px; border-style: dashed;}</style></head><body><form action="SelectServlet" method="get"><table> <tr> <td>姓名:</td> <td><input type="text" name="name"/></td> </tr> <tr> <td>班级:</td> <td><input type="text" name="grent"/></td> </tr> <tr> <td>成绩:</td> <td><input type="number" name="result"/></td> </tr><tr> <td colspan="2" align="center"> <input type="submit" value="submit"> <input type="reset" value="reset"> </td></tr></table></form></body></html>
2. web.xml配置
注册两个Servlet
<servlet> <servlet-name>SelectServlet</servlet-name> <servlet-class>servletdemo.SelectServlet</servlet-class></servlet> <servlet-mapping> <servlet-name>SelectServlet</servlet-name> <url-pattern>/SelectServlet</url-pattern></servlet-mapping><servlet> <servlet-name>UpdateServlet</servlet-name> <servlet-class>servletdemo.Update</servlet-class></servlet><servlet-mapping> <servlet-name>UpdateServlet</servlet-name> <url-pattern>/UpdateServlet</url-pattern></servlet-mapping>
3. css表格修饰
css_table
@CHARSET "UTF-8";table { font-family: verdana,arial,sans-serif; font-size:11px; color:#333333; border-width: 1px; border-color: #666666; border-collapse: collapse;}table th { border-width: 1px; padding: 8px; border-style: solid; border-color: #666666; background-color: #dedede;}table td { border-width: 1px; padding: 8px; border-style: solid; border-color: #666666; background-color: #ffffff;}
4. 进行处理的类
SelectServlet.java
用于显示数据库中的数据到表格中
package servletdemo;import java.io.IOException;import java.io.PrintWriter;import java.net.URL;import java.net.URLEncoder;import java.sql.*;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@WebServlet("/SelectServlet")public class SelectServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final String CONTENT_TYPE = "text/html;charset=GBK"; public SelectServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(CONTENT_TYPE); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); String name = request.getParameter("name"); String grent = request.getParameter("grent"); String result = request.getParameter("result"); out.println(name+"---"+grent+"---"+result); try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/DB_student?useUnicode=true&characterEncoding=GBK"; String user = "root"; String password = "admin"; Connection con = DriverManager.getConnection(url,user,password); Statement stat = con.createStatement(); int length=0; if(name!=null&&grent!=null&&result!=null) length= stat.executeUpdate("insert into student values('"+name+"','"+grent+"',"+result+")"); if (length!=0) { out.println("添加成功!"); }else{ out.print("<p>input data not correct!</p>"); } ResultSet rs = stat.executeQuery("select * from student"); out.println("<html>"); out.println("<head><title>selectservlet</title>"); out.println("<script type=\"text/javascript\" src=\"JS.js\"></script>"); out.println("<link rel=\"stylesheet\" type=\"text/css\" href=\"css_table.css\" /></head>"); out.println("<body bgcolor=\"#ffffff\">"); out.println("<table align='center' border='1'><caption>学生信息</caption><thead><tr><th scope=\"col\">姓名</th><th scope=\"col\">班级</th><th scope=\"col\">成绩</th><th>修改</th><th scope=\"col\">删除</th></tr></thead>"); while(rs.next()){ out.println("<tr><td>"+rs.getString("name")+"</td><td>" +rs.getString("grent")+"</td><td>" +rs.getString("result") +"</td><td><a href=\"JavaScript:change()\">修改</a></td><td><a href=\"UpdateServlet?name=" +URLEncoder.encode(rs.getString("name"),"utf-8")+"&delete=true\">删除</a></td></tr>"); } out.println("</table>"); out.println("</body>"); out.println("</html>"); } catch (Exception e) { out.print("<p> error:</p>"+e.getMessage()); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
当用户点击修改时,先产生一个提示框,用于输入修改后的数据,然后在当前页面加载文档,链接指向UpdateServlet,delete参数用于让UpdateServlet识别出是采取修改操作还是删除操作。Js代码如下:
function change() { var str = prompt("输入格式为'姓名-班级-成绩'"); var words = str.split('-',3); window.location.assign("UpdateServlet?name="+encodeURI(words[0])+"&result="+encodeURI(words[2])+"&delete=false");}
UpdateServlet
执行删除和修改操作的类
package servletdemo;import java.io.IOException;import java.io.PrintWriter;import java.net.URLDecoder;import java.net.URLEncoder;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.Statement;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@WebServlet("/Update")public class Update extends HttpServlet { private static final long serialVersionUID = 1L; private static final String CONTENT_TYPE = "text/html;charset=GBK"; public Update() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(CONTENT_TYPE); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); String name = URLDecoder.decode(request.getParameter("name"),"utf-8"); //将name参数以utf-8编码方式解码为unicode编码 String result = request.getParameter("result"); boolean isdelete = request.getParameter("delete").equals("true")?true:false; try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/DB_student?useUnicode=true&characterEncoding=GBK"; String user = "root"; String password = "admin"; Connection con = DriverManager.getConnection(url,user,password); Statement stat = con.createStatement(); System.out.println(name); if(isdelete) stat.executeUpdate("delete from student where name='"+name+"'"); else stat.execute("update student set result="+Integer.parseInt(result)+" where name='"+name+"'"); out.print("<p>update success!</p>"); ResultSet rs = stat.executeQuery("select * from student"); out.println("<html>"); out.println("<head><title>selectservlet</title>"); out.println("<meta charset=\"gbk\">"); out.println("<script type=\"text/javascript\" src=\"JS.js\"></script>"); out.println("<link rel=\"stylesheet\" type=\"text/css\" href=\"css_table.css\" /></head>"); out.println("<body bgcolor=\"#ffffff\">"); out.println("<table align='center' border='1'><caption>学生信息</caption><thead><tr><th scope=\"col\">姓名</th><th scope=\"col\">班级</th><th scope=\"col\">成绩</th><th>修改</th><th scope=\"col\">删除</th></tr></thead>"); while(rs.next()){ out.println("<tr><td>"+rs.getString("name")+"</td><td>" +rs.getString("grent")+"</td><td>" +rs.getString("result") +"</td><td><a href=\"JavaScript:change()\">修改</a></td><td><a href=\"UpdateServlet?name=" +URLEncoder.encode(rs.getString("name"),"utf-8")+"&delete=true\">删除</a></td></tr>"); //将rs.getString("name")得到的unicode码编码为utf-8码,中文不能作为url链接的参数值。 } out.println("</table>"); out.println("</body>"); out.println("</html>"); } catch (Exception e) { out.print("<p> error:</p>"+e.getMessage()); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
6.3 运行效果
新增数据:‘李四-12-96’
修改:
6.4 遇到的几个问题
1. js提示框的中文显示乱码
原因:response默认用本地计算机编码方式编码中文,而客户端使用浏览器默认的编码方式解码,两者需统一。
解决:response.setCharacterEncoding("utf-8");
或者在<script></script>
内指定回复的JS文档编码格式为charset="utf-8"
此外,response.setCharacterEncoding
和response.setContentType
有区别。
response.setCharacterEncoding
:
在服务器端定义response内数据编码格式,即数据以哪种编码方式存储在response中。
response.setContentType("text/html;charset=GBK")
:
对返回的静态HTML文档设置编码格式,使客户端浏览器能正确显示HTML上的中文。等价于: response.getOutputStream().write("<meta http-equiv='content-type' content='text/html;charset=GBK'>".getBytes());
前者是设置动态文字(参数,数据库),后者设置页面静态文字
2. decode与encode
首先,上面的HTML文档用<meta charset="UTF-8">
来告诉浏览器是以UTF-8
编码传输的,要用UTF-8
来解码,即初始response
的HTML的编码是UTF-8
。
然后,form
标签有个属性是accept-charset=""
,不写则默认编码方式是UTF-8
,当用户输入姓名等信息点击submit
后,以该编码方式编码进行传输,也就是request
以UTF-8
编码,但是服务器是不知道的。那么服务器使用request.getParameter
如何知道这个编码方式来进行解码呢?
在getParameter()
源码中,有这么一段:
说明服务器会先获得request
的编码,为null
则默认以ISO-8859-1
进行解码。若要使服务器能使用·Content-type
中定义的编码,则要在connector
标签加上useBodyEncodingForURI=true
在上面并没有特意设置accept-charset=""
的值,但服务器仍然正确解码了。那么,现在有两个问题:
1. 为什么ISO-8859-1
可以正确解码UTF-8
编码的request
?
2. 如果设置accept-charset=""
的值为GBK
,服务器那里该怎么解码?
第二个问题,我尝试使用了 request.setCharacterEncoding("gbk");
发现没有用,但将 form
标签的提交方式改为post
,则可以。
总结:request.setCharacterEncoding
是设置从request
中取得的值或从数据库中取出的值。指定后可以通过getParameter()
直接获得正确的字符串,如果不指定,则默认使用iso8859-1
编码。值得注意的是在执行setCharacterEncoding()
之前,不能执行任何getParameter()
。而且,该指定只对POST
方法有效,对GET
方法无效。分析原因,应该是在执行第一个getParameter()
的时候,Java将会按照编码分析所有的提交内容,而后续的getParameter()
不再进行分析,所以setCharacterEncoding()
无效;而对于GET
方法提交表单时,提交的内容在URL中,一开始就已经按照编码分析提交内容,setCharacterEncoding()
自然就无效。
(注:post
提交的form
表单参数采用meta
编码方式)
get需在Tomcat的server.xml中的:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"URIEncoding="GBK" />
加入URIEncoding="GBK"
,解决get
请求乱码问题。
- JSP核心基础——Servlet应用
- JSP&Servlet核心介绍
- jsp/servlet核心知识点
- JSP核心基础-Servlet一个简单的例子
- JSP基础(二十一)——JSTL核心标签
- Servlet 与 JSP 核心编程
- Servlet 与 JSP 核心编程
- 【Java.Web】JSP —— HTML, Servlet,JSP比较, JSP基础
- JSP/Servlet基础——ServletMVC小例子
- JSP/Servlet基础——自定义标签库
- J2EE基础总结(2)——Servlet/JSP
- Servlet & JSP 基础6(Web应用部署)
- Servlet & JSP 基础7(Web应用安全)
- 2009-04-15读书记录:《Servlet与JSP核心编程》第四章——表单处理
- 2009-04-19读书记录:《Servlet与JSP核心编程》第八章——cookie管理
- 2009-04-20读书记录:《Servlet与JSP核心编程》第九章——会话跟踪
- servlet / jsp 学习——java,关系,区别,核心概念,代码例子
- 【JSP学习笔记(1)】——JSP基础应用
- 【纯吐槽】
- [占坑,暂时只写了大纲!] 凸优化笔记----2017 HIT 暑期学校学到的一点儿东西
- hdu2594(KMP水题)
- linux编译安装软件 ./configure命令enable和with有什么区别
- C++设计模式——装饰者模式
- JSP核心基础——Servlet应用
- Floyd算法,求两点之间的最短路
- loj1048Conquering Keokradong 二分
- hdu 6034 2017 Multi-University Training Contest
- 04.安装eclipse及汉化
- 线段树,区间开方(Rikka with Sequence,HDU 5828)
- 10129
- [GNU/Linux] Linux系统调用-线程相关(二):线程同步
- 1068. Find More Coins (30)