JSP核心基础——Servlet应用

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请求乱码问题。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值