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生命周期

  1. 首先当servlet第一次被调用的时候,会调用servlet的init方法,把servlet实例装载到内存中。
  2. 然后会调用service方法,当第二次servlet被访问的时候就会直接调用service函数,并创建一个新的线程,故Servlet是单实例多线程
  3. 只有当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项目名称。
界面如下:

  • 点击上面的链接:

get

  • 点击下面的链接:

post

3.5 运行步骤

  1. 用户点击超链接向Servlet发送请求。
  2. 服务器在web.xml中的servlet-mapping寻找与该URL地址相对应的Servlet的名字。
  3. 根据Servlet的名字找到和该Servlet相关的处理类。
  4. 若该Servlet还不存在,则先装载一个servlet类并创建实例,调用init方法初始化然后再根据请求的方式不同确定是调用doGet还是doPost方法;若存在,则直接根据请求的方式不同确定是调用doGet还是doPost方法。
  5. 最后通过Response对象返回给客户端浏览器。

4、Servlet加载的几种方式

  1. 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命令行操作

  1. 建立数据库:
    建立数据库
  2. 建立数据表
    建立数据表
  3. 查看初始状态:
     查看初始状态

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. 进行处理的类

  1. 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");}
  1. 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.setCharacterEncodingresponse.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后,以该编码方式编码进行传输,也就是requestUTF-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请求乱码问题。

阅读全文
0 0