Servlet相关知识点

本文详细介绍了Servlet的相关知识点,从C/S和B/S架构对比开始,讲解了Web服务器的概念,重点剖析了Tomcat的安装、目录结构、启动与停止。接着,深入探讨了Servlet的作用、开发步骤、配置方式以及常见错误。文章还涵盖了IDEA创建Web项目的过程,HTTP协议的基本概念、通信流程和状态码,以及Servlet的生命周期、线程安全问题。此外,还讨论了状态管理(Cookie与Session)的使用,最后通过实际案例展示了Servlet在权限验证和数据管理中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Servlet相关知识点

一、引言

1.1C/S架构和B/S架构

C/S和B/S是软件发展过程中出现的两种软件架构方式。

1.2C/S架构(Client/Server客户端/服务器)
  • 特点:必须在客户端安装特定软件
  • 优点:图形效果显示较好(如:3D游戏)
  • 缺点:服务器软件和功能进行升级,客户端也必须升级、不利于维护
  • 常见的C/S程序:QQ、微信等

CS架构

1.3B/S架构(Browser/Server浏览器/服务器)
  • 特点:无需安装客户端,任何浏览器都可直接访问
  • 优点:涉及到功能的升级,只需要升级服务器端
  • 缺点:图形显示效果不如C/S架构
  • 需要通过HTTP协议访问

DAO流程

二、服务器

2.1概念
2.1.1什么是Web

Web(World Wide Web)称为万维网,简单理解就是网站,它用来表示Internet主机上供外界访问的资源。

Internet上供外界访问的额资源分为两大类

  • 静态资源:指Web页面中供人们浏览的数据始终是不变的。(HTML、CSS)
  • 动态资源:指Web页面中供人们浏览的数据是由程序产生的,不同时间点,甚至不同设备访问Web页面看到的内容各不相同。(JSP/Servlet)
  • 在Java中,动态Web资源开发技术我们统称为Java Web。
2.1.2什么是Web服务器

Web服务器是运行及发布Web应用的容器,只有将开发的Web项目放置到该容器中,才能使网络中的所有用户通过浏览器进行访问。

2.2常见服务器
  • 开源:OpenSource(1、开放源代码 2、免费)
    • Tomcat(主流Web服务器之一,适合初学者 )
    • jetty(淘宝,运行效率比Tomcat高)
    • resin(新浪,所有开源服务器软件中,运行效率最高的)
    • 三者的用法从代码角度完全相同,只有在开启、关闭服务器软件时对应的命令稍有区别。掌握一个即掌握所有
  • 收费
    • WebLogic(Oracle)
    • WebSphere(IBM)
    • 提供相应的服务与支持,软件大,耗资源
2.3Tomcat服务器

Tomcat时Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,免费开源、并支持Servlet和JSP规范。目前Tomcat最新版本为9.0。

Tomcat技术先进、性能稳定,深受Java爱好者喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web应用服务器。

2.4Tomcat安装
2.4.1下载

官网下载(http://tomcat.apache.org)Tomcat8.5解压缩版本

2.4.2解压安装

将Tomcat解压到一个没有特殊符号的目录中(一般纯英文即可)

注意

  • 不建议将服务器软件放在磁盘层次很多的文件夹
  • 不建议放在中文路径下
2.4.3Tomcat目录结构
文件夹说明备注
bin该目录下存放的是二进制可执行文件startup.bat启动Tomcat、shutdown.bat停止Tomcat
conf这是一个非常重要的目录,这个目录下有两个最为重要的文件server.xml和web.xmlserver.xml:配置整个服务器信息。例如修改端口号,编码格式等。
web.xml:项目部署描述符文件,这个文件中注册了很多MIME类型,即文档类型。
libTomcat的类库,里面存放Tomcat运行所需要的jar文件。
logs存放日志文件,记录了Tomcat启动和关闭的信息,如果启动Tomcat时有错误,异常也会记录在日志文件中。
tempTomcat的临时文件,这个目录下的东西在停止Tomcat后删除。
webapps存放web项目的目录,其中每个文件夹都是一个项目;其中ROOT是一个特殊的项目,在地址栏中没有给出项目目录时,对应的就是ROOT项目。
work运行时生成的文件,最终运行的文件都在这里。当客户端用户访问一个JSP文件时,Tomcat会通过JSP生成Java文件,然后再编译Java文件生成class文件,生成的java和class文件都会存放到这个目录下。
2.5Tomcat启动和停止
2.5.1启动

进入tomcat安装目录bin下,双击startup.bat启动程序,出现如下界面

Tomcat启动控制台

2.5.2验证

打开浏览器,输入http://localhost:8080

如果出现以下界面证明Tomcat启动成功。

Tomcat访问页面

2.5.3停止

Tomcat默认端口号为8080,可以通过conf/server.xml文件修改

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />
  • 注意:修改端口号需要重新启动Tomcat才能生效
2.6项目部署及访问静态资源

Tomcat是Web服务器,我们的项目应用是部署在webapps下,然后通过特定的URL访问。

2.6.1创建项目
  • 在webapps中建立文件夹(项目应用),比如:myweb
    • 创建WEB-INF文件夹,用于存放项目的核心内容
      • 创建classes,用于存放.class文件
      • 创建lib,用于存放jar文件
      • 创建web.xml,项目配置文件(到ROOT项目下的WEB-INF复制即可)
    • 把网页hello.html复制到myweb文件夹中,与WEB-INF在同级目录
2.6.2URL访问资源

浏览器地址中输入URL:http://localhost:8080/myweb/hello.html

  • 经验:URL主要有4部分组成:协议、主机、端口、资源路径

URL组成

2.6.3Tomcat响应流程图

请求响应流程图

2.7常见错误
2.7.1Tomcat控制台闪退

闪退问题是由于JAVA_HOME配置导致的,检查JAVA_HOME配置是否正确

2.7.2 404

访问资源不存在,出现404错误

404错误

三、Servlet

3.1概念
  • Servlet:Server Applet的简称,是服务器端的程序(代码、功能实现),可交互式的处理客户端发送到服务端的请求,并完成操作响应。
  • 动态网页技术
  • JavaWeb程序开发的基础,JavaEE规范(一套接口)的一个组成部分。
3.1.1Servlet作用
  • 接收客户端请求,完成操作。
  • 动态生成网页(页面数据可变)。
  • 将包含操作结果的动态网页响应给客户端。
3.2Servlet开发步骤
3.2.1搭建开发环境

将Servlet相关jar包(lib\servlet-api.jar)配置到classpath中

3.2.2编写Servlet
  • 实现javax.servlet.Servlet
  • 重写5个主要方法
  • 在核心的servlet()方法中编写输出语句,打印访问结果
package com.zjl.servlet;

import javax.servlet.*;
import java.io.IOException;

public class MyServlet implements Servlet {

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("My First Servlet");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}
3.2.3部署Servlet

编译MyServlet后,将生成的.class文件放在WEB-INF/classes文件夹中。

3.2.4配置Servlet

编写WEB-INF下项目配置文件web.xml

<?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">

    <!--1、添加servlet节点-->
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>com.zjl.servlet.MyServlet</servlet-class>
    </servlet>

    <!--2、添加servlet-mapping节点-->
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/myservlet</url-pattern>
    </servlet-mapping>

</web-app>
  • 注意:url-pattern配置的内容就是浏览器地址栏输入的URL中项目名称后的资源的内容
3.3运行测试

启动Tomcat,在浏览器地址栏中输入http://localhost:8080/myweb/myservlet访问,在Tomcat中打印时间表示成功。

3.4创建错误
3.4.1 500错误

服务端出现异常

500错误

四、IDEA创建Web项目

4.1IDEA创建Web项目

创建项目窗口,选择JavaEE7,并勾选Web Application

创建web项目

输入项目名称和项目保存位置,点击Finish,完成项目创建

项目目录设置

Web项目目录介绍

Servlet项目目录结构

4.2IDEA开发Servlet

使用开发工具编写Servlet,仍要手工导入servlet-api.jar文件,并与项目关联

4.2.1编写Servlet

创建MyServlet,实现Servlet接口,覆盖5个方法

4.2.2配置web.xml
<?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">

    <!--1、添加servlet节点-->
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>com.zjl.servlet.MyServlet</servlet-class>
    </servlet>

    <!--2、添加servlet-mapping节点-->
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/myservlet</url-pattern>
    </servlet-mapping>

</web-app>
4.2.3部署Web项目
  • 在Tomcat的webapps目录下,新建WebProject项目文件夹
    • 创建WEB-INF,存放核心文件
    • 在WEB-INF下,创建classes文件夹,将编译后的MyServlet.class文件复制至此。
  • 问题:每当我们编写了新的Servlet或者重新编译,都需要手工将新的.class部署到Tomcat中,较为麻烦。如何实现自动部署?
4.3IDEA部署Web项目

前面我们是在Tomcat的webapps目录新建应用程序目录myweb,然后把静态资源和Servlet复制到相关目录下。使用IDEA不需要我们复制了。可以通过IDEA集成Tomcat服务器,实现自动部署。

4.3.1 IDEA集成Tomcat

点击File选项,选择Settings

\Servlet项目Settings设置

选择Build,Execution,Deployment下的Application Servers。

Servlet项目应用服务器

点击+号,选择Tomcat Server

Servlet项目添加Tomcat服务

选择Tomcat安装目录,点击OK即可

Servlet项目选择Tomcat目录

最后,点击OK

Servlet项目完成目录选择

4.3.2项目部署Tomcat

点击Add Configuration

Servlet项目添加项目配置

点击+号,选择Tomcat Server,选择Local

Servlet项目选择Tomcat服务器

点击+号,选择Artifact,添加当前项目

Servlet项目添加当前项目

点击运行按钮,即可运行项目

Servlet项目运行

4.4其他操作
4.4.1关联第三方jar包

在WEB-INF目录下新建lib目录

Servlet项目在WEB-INF下新建lib目录

输入lib目录

Servlet项目导包文件夹改名

复制jar包到lib目录中

Servlet项目复制jar文件

右击lib目录,选择Add as Library…

Servlet项目集成jar文件

选择Project Library完成。

  • Global Library表示所有工程都可以使用
  • Project Library表示当前工程中所有模块都可以使用。
  • Module Library表示当前模块可以使用

Servlet项目jar包关联项目环境

4.4.2如何导出war包

项目完成后,有时候需要打成war方便部署。war包可以直接放入Tomcat的webapps目录中,启动Tomcat后自动解压,即可访问。

点击项目结构

Servlet项目结构配置

选择Artifacts,点击+号

Servlet项目添加Artifacts

选择Archive---->For…

Servlet项目选择项目对应格式

构建项目

Servlet项目构建项目

在out\artifacts\目录中,查看生产的war包,把war放入Tomcat的webapps目录,启动Tomcat自动解压即可访问。

Servlet项目War包目录

五、HTTP协议

5.1什么是HTTP

超文本传输协议(HTP,HyperText Transfer Protocol)式互联网上应用最为广泛的一种网络协议,是一个基于请求与响应模式的、无状态的、运行于TCP协议基础之上。

5.2HTTP协议特点
  • 支持客户端(浏览器)/服务器模式。
  • 简单快速:客户端只向服务器发送请求方法和路径,服务器即可响应数据,因而通信速度很快。请求方法常用的有GET、POST等。
  • 灵活:HTTP允许传输任意类型的数据,传输的数据类型由Content-Type标识。
  • 无连接:无连接指的是每次TCP连接只处理一个或多个请求,服务器处理完客户的请求后,即断开连接。采用之中方式可以节省传输时间。
    • HTTP1.0版本是一个请求响应之后,直接就断开了。称为短连接。
    • HTTP1.1版本不是响应之后直接就断开了,而是等几秒钟,这几秒钟之内有新的请求,那么还是通过之前的连接通道来收发消息,如果过了几秒钟用户没有发送新的请求,就会断开连接。称为长连接。
  • 无状态:HTTP协议是无状态协议。
    • 无状态是指协议对于事务处理没有记忆能力。
5.3HTTP协议通信流程
  • 客户与服务器建立连接(三次握手)。
  • 客户向服务器发送请求。
  • 服务器接受请求,并根据请求返回相应的文件作为应答。
  • 客户与服务器关闭连接(四次挥手)。

HTTP原理

5.4请求报文和响应报文
5.4.1HTTP请求报文

当浏览器向Web服务器发出请求时,它向服务器传递了一个数据块,也就是请求信息(请求报文),HTTP请求信息由4部分组成:1、请求行 请求方法/地址 URL协议/版本 2、请求头(Request Header) 3、空行 4、请求正文

请求报文

5.4.2HTTP响应报文

HTTP响应报文与HTTP请求报文相似,HTTP响应也由4个部分组成:1、状态行 2、响应头(Response Header) 3、空行 4、响应正文

响应报文

5.4.3常见状态码
状态代码状态描述说明
200OK客户端请求成功
302Found临时重定向
403Forbidden服务器收到请求,但是拒绝提供服务。服务器通常会在响应正文中给出不提供服务的原因
404Not Found请求的资源不存在,例如,输入了错误的URL。
500Internal Server Error服务器发生不可预期的错误,导致无法完成客户端的请求。

六、Servlet详解

6.1Servlet核心接口和类

在Servlet体系结构中,除了实现Servlet接口,还可以通过集成GenericServlet或HttpServlet类,完成编写。

6.1.1Servlet接口

在Servlet API中最重要的是Servlet接口,所有Servlet都会直接或间接的与该接口发生联系,或是直接实现该接口,或间接继承自实现了该接口的类。该接口包括以下五个方法:

  • init(ServletConfig config)
  • ServletConfig getServletConfig()
  • service(ServletRequest req,ServletResponse resp)
  • String getServletInfo()
  • destroy()
6.1.3HttpServlet类

HttpServlet是继承GenericServlet的基础上进一步的扩展。提供将要被子类化以创建适用于Web站点的HTTP Servlet的抽象类。

HttpServlet的子类至少必须重写一个方法,该方法通常是以下这些方法之一:doGet,如果servlet支持HTTP GET请求 doPost,用于HTTP POST请求 doPut,用于HTTP PUT请求 doDelete,用于HTTP DELETE请求

6.2Servlet两种创建方式
6.2.1实现接口Servlet
package com.zjl.servlet;

import javax.servlet.*;
import java.io.IOException;

/**
 * Servlet创建的第一种方式:实现接口Servlet
 */
public class HelloServlet2 implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("OK");
        servletResponse.getWriter().println("welcome use servlet");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}
  • 该方式比较麻烦,需要实现几口中所有方法
6.2.2继承HttpServlet(推荐)
package com.zjl.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Servlet implementation class HelloServlet
 * Servlet的第二种创建方式,继承HttpServlet,也是开发中推荐的
 */
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println("welcome use servlet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
6.2.3常见错误
  • HTTP Status 404资源找不到
    • 第一种情况:地址书写错误。
    • 第二种情况:地址没有问题,把IDEA项目中out目录删除,然后重新运行。
  • Servlet地址配置重复。both mapped to the url-pattern [/helloservlet] which is not permitted。
  • Servlet地址配置错误。比如没有写/Invalid [helloservlet2] in servlet mapping。
6.3Servlet两种配置方式
6.3.1使用web.xml(Servlet2.5之前使用)
<?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">

    <display-name>Web_Test01</display-name>
    <!--Servlet的第二种配置-->
    <!--Servlet配置-->
    <servlet>
        <!--名称-->
        <servlet-name>hello2</servlet-name>
        <!--Servlet的全称类名-->
        <servlet-class>com.zjl.servlet.HelloServlet</servlet-class>
        <!--启动的优先级,数字越小越先起作用-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--映射配置-->
    <servlet-mapping>
        <!--名称-->
        <servlet-name>hello2</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>login.html</welcome-file>
    </welcome-file-list>
</web-app>
6.3.2配置属性
url-pattern定义匹配规则,取值说明:
精确匹配  /具体的名称  只有url路径是具体的名称的时候才会触发Servlet
后缀匹配  `*`.xxx  只要是以xxx结尾的就匹配触发Servlet
通配符匹配  /`*`  匹配所有请求,包含服务器的所有资源
通配符匹配  /  匹配所有请求,包含服务器的所有资源,不包括.jsp

load-on-startup
1.元素标记容器是否应该在web应用程序启动的时候就加载这个servlet。
2.它的值必须是一个整数,表示servlet被加载的先后顺序。
3.如果该元素的值为负数或者没有设置,则容器会当Servlet被请求时再加载。
4.如果值为正整数或者0时,表示容器在应用启动时就夹在并初始化这个servlet,值越小,servlet的优先级越高,就越先被加载。值相同时,容器就会自己选择顺序来加载。
6.3.3使用注解(Servlet3.0后支持,推荐)
package com.zjl.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Servlet implementation class HelloServlet
 * 演示Servlet注解式配置
 */
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println("welcome use servlet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
6.3.4@WebServlet注解常用属性
  • name:Servlet名字(可选)
  • value:配置url路径,可以配置多个
  • urlPatterns:配置url路径,和value作用一样,不能同时使用
  • loadOnStartup:配置Servlet的创建的时机,如果是0或者正数,启动程序时创建,如果是负数,则访问时创建。数字越小优先级越高。

七、Servlet应用

7.1request对象

在Servlet中用来处理客户端请求需要使用doGet或doPost方法的request对象

request

7.1.1get和post区别

get请求

  • get提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连
  • get方式明文传递,数据量小,不安全
  • 效率高,浏览器默认请求方式为GET请求
  • 对应的Servlet的方法时doGet

post请求

  • post方法是把提交的数据放在HTTP包的Body中
  • 密文传递数据,数据量大,安全
  • 效率相对没有GET高
  • 对应的Servlet的方法时doPost
7.1.2request主要方法
方法名说明
String getParameter(String name)根据表单组件名称获取提交数据
void setCharacterEncoding(String charset)指定每个请求的编码
7.1.3request应用

HTML页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>欢迎页面</title>
</head>
<body>
    <h1>欢迎你</h1>
    <div>
        <form action="HelloServlet" method="post">
            <label>姓名:</label><input type="text" name="name"><br>
            <label>年龄:</label><input type="text" name="age"><br>
            <input type="submit" value="提交">
        </form>
    </div>
</body>
</html>

Servlet代码

package com.zjl.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取表单提交的姓名
        String name = req.getParameter("name");
        //获取年龄
        String age = req.getParameter("ago");
        //服务端输出打印
        System.out.println(req.getRemoteAdd()+"发来信息:姓名"+name+"---->年龄:"+age);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
7.1.4get请求参数问题

产生乱码是因为服务器和客户端沟通的编码不一致造成的,因此解决办法是:在客户端和服务器之间设置一个统一的编码,之后就按照此编码进行数据的传输和接收

7.1.5get中文乱码

在Tomcat7及以下版本,客户端以UTF-8的编码传输数据到服务器端,而服务器短的request对象使用的是ISO8859-1这个字符编码来接收数据,服务器和客户端沟通的编码不一致因此才会产生中文乱码的。

  • 解决办法:在接收到数据后,先获取request对象以ISO8859-1字符编码接收到的原始数据的字节数组,然后通过字节数组以指定的编码构建字符串,解决乱码问题。
  • Tomcat8的版本中get方式不会出现乱码了,因为服务器对url的编码格式可以进行自动转换。
package com.zjl.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * Servlet implementation class HelloServlet
 * 演示Servlet的GET请求,中文乱码的问题
 *
 */
@WebServlet("/GETServlet")
public class GetServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取表单提交的姓名
        String name = req.getParameter("name");
        name=new String(name.getBytes("ISO8859-1"),"UTF-8");
        //获取年龄
        String age = req.getParameter("ago");
        //服务端输出打印
        System.out.println(req.getRemoteAdd()+"发来信息:姓名"+name+"---->年龄:"+age);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
7.1.6post中文乱码

由于客户端是以UTF-8字符编码将表单数据传输到服务器端的,因此服务器也需要设置以UTF-8字符编码进行接收。

  • 解决方案:使用ServletRequest接口继承而来的setCharacterEncoding(charset)方法进行统一的编码设置。
package com.zjl.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * Servlet implementation class HelloServlet
 * 演示Servlet的POST请求,中文乱码的问题
 *
 */
@WebServlet("/POSTServlet")
public class PostServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置请求参数的编码格式--对GET无效
        req.setCharacterEncoding("UTF-8");
        //获取表单提交的信息
        String name=req.getParameter("msg");
        //服务端输出打印
        System.out.println(req.getRemoteAddr()+"发来信息"+msg);
    }
}
7.2response对象

response对象用于响应客户请求并向客户端输出信息。

response

7.2.1response主要方法
方法名称作用
setHeader(name,value)设置响应信息头
setContentType(String)设置响应文件类型,响应式的编码格式
setCharacterEncoding(String)设置服务端响应内容编码格式
getWriter()获取字符输出流
7.2.2response应用
//获取请求参数代码省略
//获取输出流
PrintWriter out=resp.getWriter();
out.println("<html>");
out.println("<head><title>login</title><head>");
out.println("<body>");
out.println("<h1>Login Success!!!</h1>");
//out.println("<h1>登录成功!!!</h1>");
out.println("</body>");
out.println("</html>");
  • 如果输出内容包含中文,则出现乱码,因为服务器默认采用ISO8859-1编码响应内容
7.2.3解决输出中文乱码
  • 设置服务器端响应的编码格式
  • 设置客户端响应内容的头内容的文件类型及编码格式
resp.setCharacterEncoding("utf-8");//设置响应编码格式为utf-8
resp.setHeader("Content-type","text/html;charset=UTF-8");
  • 不推荐

同时设置服务端的编码格式和客户端响应的文件类型及响应时的编码格式

resp.setContentType("text/html;charset=UTF-8");
  • 推荐
7.3综合案例(Servlet+JDBC)

要求:实现登录功能、展示所有用户功能

7.3.1数据库
create table admin(
	username varchar(20) primary key,
	password varchar(20) not null,
	phone varchar(11) not null,
	address varchar(20) not null
)charset=utf8;

insert into admin(username,password,phone,address) values('zhangsan','123456','12345678901','北京市昌平区');
insert into admin(username,password,phone,address) values('lisi','123456','12345678901','北京市昌平区');
7.3.2DBUtils
package com.zjl.servletProject.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class DbUtils {
    private static DruidDataSource ds;
    private static final ThreadLocal<Connection> THREAD_LOCAL = new ThreadLocal<>();

    static {
        Properties properties = new Properties();
        InputStream is = DbUtils.class.getResourceAsStream("database.properties");
        try {
            properties.load(is);
            ds = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection(){
        Connection connection = THREAD_LOCAL.get();
        try {
            if (connection == null){
                connection = ds.getConnection();
                THREAD_LOCAL.set(connection);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    public static void begin(){
        Connection connection = null;
        try {
            connection = getConnection();
            connection.setAutoCommit(false);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void commit(){
        Connection connection = null;
        try {
            connection = getConnection();
            connection.commit();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeAll(connection,null,null);
        }
    }

    public static void rollback(){
        Connection connection = null;
        try {
            connection = getConnection();
            connection.rollback();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeAll(connection,null,null);
        }
    }

    public static void closeAll(Connection connection, Statement statement,ResultSet resultSet){
        try {
            if (resultSet != null){
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
                THREAD_LOCAL.remove();
            }
        }catch (SQLException e){
            e.printStackTrace();
        }

    }
}
7.3.3AdminDaoImpl
package com.zjl.servletProject.dao.impl;

import com.zjl.servletProject.dao.AdminDao;
import com.zjl.servletProject.entity.Admin;
import com.zjl.servletProject.utils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.sql.SQLException;
import java.util.List;

public class AdminDaoImpl implements AdminDao {
    private QueryRunner queryRunner = new QueryRunner();
    @Override
    public int insert(Admin admin) {
        return 0;
    }

    @Override
    public int delete(String username) {
        return 0;
    }

    @Override
    public int update(Admin admin) {
        return 0;
    }

    @Override
    public Admin select(String username) {
        try {
            Admin admin = queryRunner.query(DbUtils.getConnection(),"select * from admin where username=?;",new BeanHandler<Admin>(Admin.class),username);
            return admin;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<Admin> selectAll() {
        try {
            List<Admin> admins = queryRunner.query(DbUtils.getConnection(),"select * from admin;",new BeanListHandler<Admin>(Admin.class));
            return admins;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}
7.3.4AdminServiceImpl
package com.zjl.servletProject.service.impl;

import com.zjl.servletProject.dao.AdminDao;
import com.zjl.servletProject.dao.impl.AdminDaoImpl;
import com.zjl.servletProject.entity.Admin;
import com.zjl.servletProject.service.AdminService;
import com.zjl.servletProject.utils.DbUtils;

import java.util.List;

public class AdminServiceImpl implements AdminService {
    private AdminDao adminDao = new AdminDaoImpl();
    @Override
    public Admin login(String username, String password) {
        Admin result = null;
        try {
            DbUtils.begin();
            Admin admin = adminDao.select(username);
            if (admin != null){
                if (admin.getPassword().equals(password)){
                    result = admin;
                }
            }
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public List<Admin> showAllAdmin() {
        List<Admin> admins = null;
        try {
            DbUtils.begin();
            admins = adminDao.selectAll();
            DbUtils.commit();
        } catch (Exception e) {
            DbUtils.rollback();
            e.printStackTrace();
        }
        return admins;
    }
}
7.3.5HTML页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
    <form action="/login" method="post">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        <input type="submit" value="登录">
    </form>
</body>
</html>
7.3.6LoginServlet
package com.zjl.servletProject.servlet;

import com.zjl.servletProject.entity.Admin;
import com.zjl.servletProject.service.AdminService;
import com.zjl.servletProject.service.impl.AdminServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //处理乱码
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //收参
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        //调用业务逻辑
        AdminServiceImpl adminService = new AdminServiceImpl();
        Admin admin = adminService.login(username, password);
        //处理结果
        PrintWriter printWriter = resp.getWriter();
        if (admin != null) {
            //响应给客户端一个结果页面,显示登录成功
            printWriter.println("<html>");
            printWriter.println("   <head>");
            printWriter.println("       <meta>");
            printWriter.println("       <title></title>");
            printWriter.println("   </head>");
            printWriter.println("   <body>");
            printWriter.println("       <h1>登录成功</h1>");
            printWriter.println("   </body>");
            printWriter.println("</html>");
        } else {
            //响应给客户端一个结果页面,显示登录失败
            printWriter.println("<html>");
            printWriter.println("   <head>");
            printWriter.println("       <meta>");
            printWriter.println("       <title></title>");
            printWriter.println("   </head>");
            printWriter.println("   <body>");
            printWriter.println("       <h1>登录失败</h1>");
            printWriter.println("   </body>");
            printWriter.println("</html>");
        }

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}
7.3.7ShowAllAdminServlet
package com.zjl.servletProject.servlet;

import com.zjl.servletProject.entity.Admin;
import com.zjl.servletProject.service.AdminService;
import com.zjl.servletProject.service.impl.AdminServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

@WebServlet("/showAll")
public class ShowAllAdminServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //处理乱码
        resp.setContentType("text/html;charset=utf-8");
        
        //调用业务逻辑
        AdminService adminService = new AdminServiceImpl();
        List<Admin> admins = adminService.showAllAdmin();

        //处理结果
        PrintWriter printWriter = resp.getWriter();
        if (admins != null) {
            //展示用户列表
            printWriter.println("<html>");
            printWriter.println("   <head>");
            printWriter.println("       <meta charset='utf-8'>");
            printWriter.println("       <title>展示用户</title>");
            printWriter.println("   </head>");
            printWriter.println("   <body>");
            printWriter.println("       <table border='1'>");
            printWriter.println("           <tr>");
            printWriter.println("               <td>username</td>");
            printWriter.println("               <td>password</td>");
            printWriter.println("               <td>phone</td>");
            printWriter.println("               <td>address</td>");
            printWriter.println("           </tr>");
            for (Admin admin : admins) {
                printWriter.println("           <tr>");
                printWriter.println("               <td>"+admin.getUsername()+"</td>");
                printWriter.println("               <td>"+admin.getPassword()+"</td>");
                printWriter.println("               <td>"+admin.getPhone()+"</td>");
                printWriter.println("               <td>"+admin.getAddress()+"</td>");
                printWriter.println("           </tr>");
            }
            printWriter.println("       </table>");
            printWriter.println("   </body>");
            printWriter.println("</html>");
        } else {
            //提示当前没有用户
            printWriter.println("<html>");
            printWriter.println("   <head>");
            printWriter.println("       <meta charset='utf-8'>");
            printWriter.println("       <title>展示用户</title>");
            printWriter.println("   </head>");
            printWriter.println("   <body>");
            printWriter.println("       <h1>当前没有用户</h1>");
            printWriter.println("   </body>");
            printWriter.println("</html>");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

八、转发与重定向

8.1现有问题

在之前案例中,调用业务逻辑和显示结果页面都在同一个Servlet里,就会产生设计问题

  • 不符合单一只能原则、各司其职的思想
  • 不利于后续的维护

应该将业务逻辑和显示结果分离开

Servlet项目现阶段问题

8.1.1业务、显示分离

Servlet项目业务与显示分离

  • 问题:业务逻辑和现实结果分离后,如何跳转到显示结果的Servlet?
  • 业务逻辑得到的数据结果如何传递给显示结果的Servlet?
8.2转发

转发的作用在服务器端,将请求发送给服务器上的其他资源,以共同完成一次请求的处理。

8.2.1页面跳转

在调用业务逻辑的Servlet中,编写以下代码

  • request.getRequestDispatcher("/目标URL-pattern").forward(request,response);

forward

  • 使用forward跳转时,是在服务器内部跳转,地址栏不发生变化,属于同一次请求
8.2.2数据传递

forward表示一次请求,是在服务器内部跳转 ,可以共享同一次request作用域中的数据

  • request作用域:拥有存储数据的空间,作用范围是一次请求有效(一次请求可以经过多次转发)
    • 可以将数据存入request后,在一次请求过程中的任何位置进行获取
    • 可传递任何数据(基本数据类型、对象、数组、集合等)
  • 存数据:request.setAttribute(key,value);
    • 以键值对形式存储在request作用域中。key为String类型,value为Object类型
  • 取数据:request.getAttribute(key);
    • 通过String类型的key访问Object类型的value
8.2.3转发的特点
  • 转发是服务器行为
  • 转发是浏览器只做了一次访问请求
  • 转发浏览器地址不变
  • 转发两次跳转之间传输的信息不会丢失,所以可通过request进行数据的传递
  • 转发只能将请求转发给同一个Web应用中的组件
8.3重定向

重定向作用在客户端,客户端将请求发送给服务器后,服务器响应给客户端一个新的请求地址,客户端重新发送新的请求。

8.3.1页面跳转

在调用业务逻辑的Servlet中,编写以下代码

  • response.sendRedirect(“目标URI”);
  • URI:统一资源标识符(Uniform Resource Identifier),用来表示服务器中定位一个资源,资源在web项目中的路径(/project/source)

redirect

  • 使用redirect跳转时,是在客户端跳转,地址栏发生变化,属于多次请求

8.3.2数据传递

sendRedirect跳转时,地址栏改变,代表客户端重新发送的请求。属于两次请求

  • response没有作用域,两次request请求中的数据无法共享
  • 传递数据:通过URI的拼接进行数据传递("/WebProject/b?username=tom");
  • 获取数据:request.getParameteer(“username”);
8.3.3重定向特点
  • 重定向是客户端行为。
  • 重定向是浏览器做了至少两次的访问请求。
  • 重定向浏览器地址改变。
  • 重定向两次跳转之间传输的信息会丢失(request范围)。
  • 重定向可以指向任何的资源,包括当前应用程序中的其他资源、同一个站点上的其他应用程序中的资源、其他站点的资源。
8.4转发、重定向总结

当两个Servlet需要传递数据时,选择forward转发。不建议使用sendRedirect进行传递

九、Servlet生命周期

9.1声明周期的四个阶段
9.1.1实例化

当用户第一次访问Servlet时,由容器调用Servlet的构造器创建具体的Servlet对象。也可以在容器启动之后立刻创建实例。使用如下代码可以设置Servlet是否在服务器启动时就创建。

  • 注意:只执行一次
9.1.2初始化

在初始化阶段,init()方法会被调用。这个方法在javax.servlet.Servlet接口中定义。其中,方法以一个ServletConfig类型的对象作为参数。

  • 注意:init方法只被执行一次
9.1.3服务

当客户端有一个请求时,容器就会将请求ServletRequest与响应ServletResponse对象转给Servlet,以参数的形式传给service方法。

  • 此方法会执行多次
9.1.4销毁

当Servlet容器停止或者重新启动都会引起销毁Servlet对象并调用destroy方法。

  • destroy方法执行一次
9.1.5Servlet执行流程

Servlet执行流程

/**
 * Servlet implementation class LifeServlet
 * 演示Servlet的生命周期:
 * 1.实例化
 * 2.init:初始化
 * 3.service:服务
 * 4.destory: 销毁
 */
@WebServlet("/lifeservlet")
public class LifeServlet extends HttpServlet {
    public LifeServlet() {
        System.out.println("1.完成实例化");
    }

    @Override
    public void init() throws ServletException {
        super.init();
        System.out.println("2.完成初始化");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("3.就绪中");
        resp.getWriter().append("served at:").append(req.getContextPath());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    public void destroy() {
        super.destroy();
        System.out.println("4.销毁了");
    }
}

十、Servlet特性

10.1线程安全问题

Servlet在访问之后,会执行实例化操作,创建一个Servlet对象。而我们Tomcat容器可以同时多个线程并发访问统一个Servlet,如果在方法中对成员变量做修改操作,就会有线程安全的问题。

10.2如何保证线程安全
  • synchronized
    • 将存在线程安全问题的代码放到同步代码块中
  • 实现SingleThreadModel接口
    • servlet实现SingleThreadModel接口后,每个线程都会创建servlet实例,这样每个客户端请求就不存在共享资源的问题,当时servlet响应客户端请求的效率太低,所以已经淘汰。
  • 尽可能使用局部变量
package com.zjl.servlet;

import javax.servlet.ServletException;
import javax.servlet.SingleThreadModel;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/safeservlet")
public class SafeServlet extends HttpServlet implements SingleThreadModel {
//    private String message = "";

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String message = "";
        //假设1.接收数据
        //2.调用业务逻辑,得到登录结果
        message = "登录成功";//登录失败
        PrintWriter printWriter = resp.getWriter();
        printWriter.write(message);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

十一、状态管理

11.1现有问题
  • HTTP协议是无状态的,不能保存每次提交的信息
  • 如果用户发来一个新的请求,服务器无法知道它是否与上次的请求有联系。
  • 对于那些需要多次提交数据才能完成的Web操作,比如登录来说,就成问题了。
11.2概念

将浏览器与web服务器之间多次交互当作一个整体来处理,并且将多次交互所涉及的数据(即状态)保存下来。

11.3状态管理分类
  • 客户端状态管理技术:将状态保存在客户端。代表性的是Cookie技术。
  • 服务器状态管理技术:将状态保存在服务器端。代表性的是session技术(服务器传递sessionID时需要使用Cookie的方式)

十二、Cookie的使用

12.1什么时Cookie
  • Cookie是在浏览器访问Web服务器的某个资源时,由Web服务器咋HTTP响应消息头中附带传送给浏览器的一小段数据。
  • 一旦Web浏览器保存了某个Cookie,那么它在以后每次访问该Web服务器时,都应在HTTP请求头中将这个Cookie回传给Web服务器。
  • 一个Cookie主要由标识该信息的名称(name)和值(value)组成。

Cookie原理

12.2创建Cookie
//创建Cookie
Cookie cookie = new Cookie("code",code);
cookie.setPath("/webs");//设置Cookie的路径
cookie.setMaxAge(-1);//内存存储,取值有三种:>0有效期,单位秒;=0浏览器关闭;<0内存存储,默认-1
response.addCookie(cookie);//添加到response对象中,响应式发送给客户端
//注意:有效路径:当前访问资源的上一级目录,不带主机名
  • chrome浏览器查看cookie信息:chrome://settings/content/cookies
12.3获取Cookie
//获取所有的Cookie
Cookie[] cookies = request.getCookies();
//遍历Cookie
for(Cookie cookie : cookies){
    //检索出自己的Cookie
    if("code".equals(cookie.getName())){
        //记录Cookie的值
        code = cookie.getValue();
        break;
    }
}
12.4修改Cookie

只要保证Cookie的名和路径一致即可修改

//修改Cookie
Cookie cookie = new Cookie("code",code);
cookie.setPath("/webs");//设置Cookie的路径
cookie.setMaxAge(-1);//内存存储,取值有三种:>0有效期,单位秒;=0浏览器关闭;<0内存存储,默认-1
response.addCookie(cookie);//让浏览器添加Cookie
  • 注意:如果改变cookie的name和有效路径会新建cookie,而改变cookie值、有效期会覆盖原有cookie
12.5Cookie编码与解码

Cookie默认不支持中文,只能包含ASCII字符,所以Cookie需要对Unicode字符进行编码,否则会出现乱码。

  • 编码可以使用java.net.URLEncoder类的encode(String str,String encoding)方法
  • 解码使用java.net.URLDecoder类的decode(String str,String encoding)方法
12.5.1创建带中文Cookie
//使用中文的Cookie,name与value都使用UTF-8编码
Cookie cookie = new Cookie(
	URLEncoder.encode("姓名","UTF-8")
	URLEncoder.encode("老邢","UTF-8"));
//发送到客户端
response.addCookie(cookie);
12.5.2读取带中文Cookie
if(request.getCookies() != null){
    for(Cookie cookie : request.getCookies()){
        String cookieName = URLDecoder.decode(cookie.getName(),"UTF-8");
        String cookieValue = URLDecoder.decode(cookie.getValue(),"UTF-8");
        out.println(cookieName+"=");
        out.println(cookieValue+";<br/>");
    }
}else{
    out.println("Cookie已经写入客户端,请刷新页面。");
}
12.6Cookie优点和缺点
12.6.1优点
  • 可配置到期规则。
  • 简单性:Cookie是一种基于文本的轻量结构,包含简单的键值对。
  • 数据持久性:Cookie默认在过期之前是可以一直存在客户端浏览器上的。
12.6.2缺点
  • 大小受到限制:大多数浏览器对Cookie的大小有4K、8K字节的限制。
  • 用户配置为禁用:有些用户禁用了浏览器或客户端设备接收Cookie的能力,因此限制了这一功能。
  • 潜在的安全风险:Cookie可能会被篡改。会对安全性造成潜在风险或者导致依赖于Cookie的应用程序失败。

十三、Session对象

13.1Session概述
  • Session用于记录用户的状态。Session指的是在一段时间内,单个客户端与Web服务器的一连串相关的交互过程。
  • 在一个Session中,客户可能会多次请求访问同一个资源,也有可能请求访问各种不同的服务器资源。
13.2Session原理
  • 服务器会为每一次会话分配一个Session对象
  • 同一个浏览器发起的多次请求,同属于一次会话(Session)
  • 首次使用到Session时,服务器会自动创建Session,并创建Cookie存储SessionId发送回客户端
  • 注意:session是由服务端创建的。
13.3Session使用
  • Session作用域:拥有存储数据的空间,作用范围是一次会话有效
    • 一次会话是使用同一浏览器发送的多次请求。一旦浏览器关闭,则结束会话
    • 可以将数据存入Session中,在一次会话的任意位置进行获取
    • 可传递任何数据(基本数据类型、对象、集合、数组)
13.3.1获取Session

session是服务器端自动创建的,通过request对象获取

//获取Session对象
HttpSession session = request.getSession();
System.out.println("Id:"+session.getId());//唯一标记
13.3.2Session保存数据

setAttribute(属性名,Object)保存数据到session中

session.setAttribute("key",value);//以键值对形式存储在session作用域中。
13.3.4Session移除数据

removeAttribute(属性名);从session中删除数据

session.removeAttribute("key");//通过键移除session作用域中的值
13.4Session与Request应用区别
  • request是一次请求有效,请求改变,则request改变
  • session是一次会话有效,浏览器改变,则session改变
package com.zjl.sessions;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet(name = "SessionServlet",value = "/ss")
public class SessionServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.通过request对象获取Session对象
        HttpSession session = req.getSession();
        
        //2.使用session保存数据
        session.setAttribute("name","zhangsan");
        req.setAttribute("password","123456");
        
        resp.sendRedirect(req.getContextPath()+"/getValue");
        System.out.println(session.getId());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
13.4.2GetValueServlet.java
package com.zjl.sessions;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet(name = "GetValueServlet",value = "/getValue")
public class GetValueServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.通过request获取session对象
        HttpSession session = req.getSession();

        String username = (String) session.getAttribute("name");
        String password = (String) req.getAttribute("password");

        System.out.println("从session中获得了:"+username);
        System.out.println("从request中获得了:"+password);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
13.5Session的生命周期
  • 开始:第一次使用到Session的请求产生,则创建Session
  • 结束:
    • 浏览器关闭,则失败
    • Session超时,则失效
      • session.setMaxInactiveInterval(seconds);//设置最大有效时间(单位:秒)
    • 手工销毁,则失效
      • session.invalidate();//登录退出、注销
15.5.1Session失效
session.setMaxInactiveInterval(60*60);//设置session最大有效期为一小时
session.invalidate();//手工销毁
13.4浏览器禁用Cookie解决方案
13.4.1浏览器禁用Cookie的后果

服务器在默认情况下,会使用Cookie的方式将sessionID发送给浏览器,如果用户禁止Cookie,则sessionID不会被浏览器保存,此时,服务器可以使用如URL重写这样的方式来发送sessionID。

13.4.2URL重写

浏览器在访问服务器上的某个地址时,不再使用原来的那个地址,而是使用经过改写的地址(即在原来的地址后面加上了sessionID)。

13.4.3实现URL重写

response.encodeRedirectURL(String url)生成重写的URL。

HttpSession session = request.getSession();
//重写URL追加SessionId
String newUrl = response.encodeRedirectURL(req.getContextPath()+"/cs");
System.out.println(newUrl);

response.sendRedirect(newUrl);
13.5Session实战权限验证

Session记录登录状态

13.5.1创建管理员表
CREATE TABLE manager(
	username VARCHAR(20) PRIMARY KEY,
    password VARCHAR(20) NOT NULL
)charset=utf8;
13.5.2 登录页面
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>管理员登录</title>
	</head>
	<body>
		<form action="/loginMgr" method="post">
			用户名:<input type="text" name="username"/><br />
			密码:<input type="password" name="password" /><br />
			<input type="submit" value="登录" />
		</form>
	</body>
</html>
13.5.3LoginMgrController
package com.zjl.servletProject.servlet.controller;

import com.zjl.servletProject.entity.Manager;
import com.zjl.servletProject.service.ManagerService;
import com.zjl.servletProject.service.impl.ManagerServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet(name="LoginMgrController",value="/loginMgr")
public class LoginMgrController extends HttpServlet{
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        //1.处理乱码
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf-8");
        //2.收参
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //3.调用业务方法
        ManagerService managerService = new ManagerServiceImpl();
        Manager mgr = manageService.login(username,password);
        //4.处理结果,流程跳转
        if(mgr != null){
            //登录成功
            //将管理员信息存储在Session里
            HttpSession session = request.getSession();
            session.setAttribute("mgr",mgr);
            //跳转 目标、方式
            response.sendRedirect("/showallcontroller");
        }else{
            //登录失败
            response.sendRedirect(/loginMgr.html);
        }
    }
    
    protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        doPost(request,response);
    }
}
13.5.4ShowAllAdminController
package com.zjl.servletProject.servlet.controller;

import com.zjl.servletProject.entity.Admin;
import com.zjl.servletProject.entity.Manager;
import com.zjl.servletProject.service.ManagerService;
import com.zjl.servletProject.service.impl.ManagerServiceImpl;

import javax.servlet.RequestDispather;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;

@WebServlet(name="ShowAllAdminController",value="/showallcontroller")
public class ShowAllAdminController extends HttpServlet{
    protected void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
        //通过HttpSession完成权限控制
        HttpSession session = req.getSession();
        Manager mgr = (Manager)session.getAttribute("mgr");
        if(mgr != null){
            //只负责调用业务逻辑功能
            AdminService adminService = new AdminServiceImpl();
            
            List<Admin> adminList = adminService.showAllAdmin();
            
            //request作用域存储数据
           req.setAttribute("admins",adminList);
            //通过转发 跳转到显示结果servlet
            req.getRequestDispatcher("/showall.jap").forward(req,resp);
        }else{
            resp.sendRedirect("/loginMgr.html");
        }
    }
    
    protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
        doPost(req,resp);
    }
}
13.6Session实战保存验证码
13.6.1创建验证码
  • 导入ValidateCode.jar
  • 创建生成验证码的Servlet
/**
 * Servlet implementation class CreateCode
 * 验证码的生成
 */
@WebServlet("/createcode")
public class LoginMgrController extends HttpServlet{
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        ValidateCode vc = new ValidateCode(200,30,4,10);
        String code = vc.getCode();
        System.out.println(request.getRemoteAddr()+":生成:"+code);
        //使用Session存储的生成的验证码
        HttpSession session = request.getSession();
        session.setAttribute("code",code);
        //响应给客户端
        vc.write(response.getOutputStream());
    }
    
    protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        doPost(request,response);
    }
}
13.6.2登录页面
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>管理员登录</title>
	</head>
	<body>
		<form action="/loginMgr" method="post">
			用户名:<input type="text" name="username"/><br />
			密码:<input type="password" name="password" /><br />
            验证码:<input type="text" name="inputVcode" /><img src="/createcode"/><br/>
			<input type="submit" value="登录" />
		</form>
	</body>
</html>
13.6.3LoginMgrController
package com.zjl.servletProject.servlet.controller;

import com.zjl.servletProject.entity.Manager;
import com.zjl.servletProject.service.ManagerService;
import com.zjl.servletProject.service.impl.ManagerServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet(name="LoginMgrController",value="/loginMgr")
public class LoginMgrController extends HttpServlet{
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        //1.处理乱码
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf-8");
        //2.收参
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String inputVcode = request.getParameter("inputVcode");
        
        String codes = (String)request.getSession.getAttribute("codes");
        if(!inputVcode.isEmpty() && inputVcode.equalsIgnoreCase(codes)){
        //3.调用业务方法
            ManagerService managerService = new ManagerServiceImpl();
            Manager mgr = manageService.login(username,password);
            //4.处理结果,流程跳转
            if(mgr != null){
                //登录成功
                //将管理员信息存储在Session里
                HttpSession session = request.getSession();
                session.setAttribute("mgr",mgr);
                //跳转 目标、方式
                response.sendRedirect("/showallcontroller");
            }else{
                //登录失败
                response.sendRedirect(/loginMgr.html);
            }
        } else{
            response.sendRedirect("/loginMgr.html");
        }
    }
    
    protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        doPost(request,response);
    }
}

十四、ServletContext对象

14.1ServletContext概述
  • 全局对象,也拥有作用域,对应一个Tomcat中的Web对象
  • 当Web服务器启动时,会为每一个Web应用程序创建一块共享的存储区域(ServletContext)
  • ServletContext在Web服务器启动时创建,服务器关闭时销毁。
14.2获取ServletContext对象
  • GenericServlet提供了getServletContext()方法。(推荐)this.getServletContext();
  • HttpServletReques提供了getServletContext()方法。(推荐)
  • HttpSession提供了getServletContext()方法
14.3ServletContext作用
14.3.1获取项目真实路径

获取当前项目在服务器发布的真实路径

String realpath=servletContext.getRealPath("/");
14.3.2获取项目上下文路径

获取当前项目上下文路径(应用程序名称)

System.out.println(servletContext.getContextPath);//上下文路径(应用程序名称)
System.out.println(request.getContextPath);
14.3.3全局容器

ServletContext拥有作用域,可以存储数据到全局容器中

  • 存储数据:servletContext.setAttribute(“name”,value);
  • 获取数据:servletContext.getAttribute(“name”);
  • 移除数据:servletContext.removeAttribute(“name”);
14.4ServletContext特点
  • 唯一性:一个应用对应一个ServletContext
  • 生命周期:只要容器不关闭或者应用不卸载,ServletContext就一直存在。
14.5ServletContext应用场景

ServletContext统计当前项目访问次数

package com.zjl.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext
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("/servlet3")
public class Servlet3 extends HttpServlet{
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        //1.处理乱码
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf-8");
        
        ServletContext application = request.getServletContext();
        Integer count=(Integer)application.getAttribute("count");
        if(count==null){
            count=1;
            application.setAttribute("count",count);
        }else{
            PrintWriter out=response.getWriter();
            out.write("servlet共访问次数:"+count);
        }
    }
    
    protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        doPost(request,response);
    }
}
14.6作用域总结
  • HttpServletRequest:一次请求,请求响应之前有效
  • HttpSession:一次会话开始,浏览器不关闭或不超时之前有效
  • ServletContext:服务器启动开始,服务器停止之前有效

十五、过滤器

15.1现有问题

在以往的Servlet中,有没有冗余的代码,多个Servlet都要进行编写。

15.2概念

过滤器(Filter)时处于客户端与服务器目标资源之间的一道过滤技术。

Servlet项目过滤器

15.3过滤器作用
  • 执行地位在Servlet之前,客户端发送请求时,会先经过Filter,再到达目标Servlet中;响应时,会根据执行流程再次反向执行执行Filter
  • 可以解决多个Servlet共性代码的冗余问题(例如:乱码处理、登录验证)
15.4编写过滤器

Servlet API中提供了一个Filter接口,开发人员编写一个Java类实现了这个接口即可,这个Java类称之为过滤器(Filter)

15.4.1实现过程
  • 编写Java类实现Filter接口
  • 在doFilter方法中编写拦截逻辑
  • 设置拦截路径
package com.zjl.web.filter;

import javax.servlet.*
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/myfilter1")//过滤路径
public class MyFilter1 implement Filter{
    //初始化过滤器
    @Override
    public void init(FilterConfig filterConfig) throws ServletException{
        System.out.println("过滤器初始化了......init..."+filterConfig);
    }
    
    //执行过滤
    @Override
    public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws IOException,ServletException{
        System.out.println("过滤前......doFilter");
        //放行
        chain.doFilter(request,response);
        
        System.out.println("过滤后......destroy");
    }
    
    //销毁
    @Override
    public void destroy(){
        System.out.println("销毁了......destroy");
    }
}
15.5过滤器配置
15.5.1注解配置

在自定义的Filter类上使用注解@WebFilter(value="/过滤资源目标")

15.5.2xml配置
<!--过滤器的xml配置-->
<filter>
    <!--名称-->
    <filter-name>sf</filter-name>
    <!--过滤器类全称-->
    <filter-class>com.zjl.web.filter.SecondFilter</filter-class>
</filter>
<filter-mapping>
    <!--名称-->
    <filter-name>sf</filter-name>
    <!--过滤的url匹配规则和Servlet类似-->
    <url-pattern>/*</url-pattern>
</filter-mapping>
15.5.3过滤器路径
过滤器的过滤路径通常有三种形式:

精确过滤匹配,比如/index.jsp  /myservlet

后缀过滤匹配,比如*.jsp、*.html、*.jpg

通配符/*,表示拦截所有。注意过滤器不能使用/*匹配。
/aaa/bbb/*允许
15.6过滤器链和优先级
15.6.1过滤器链

客户端对服务器请求之后,服务器调用Servlet之前会执行一组过滤器(多个过滤器),那么这组过滤器就称为一条过滤器链。

每个过滤器实现某个特定的功能,当第一个Filter的doFilter方法被调用时,Web服务器会创建一个嗲表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则Web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

Servlet项目过滤器链

15.6.2过滤器优先级

在一个Web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。优先级:

  • 如果为注解的话,是按照类全名称的字符串顺序决定作用顺序
  • 如果web.xml,按照filter-mapping注册顺序,从上往下
  • web.xml配置高于注解方式
  • 如果注解和web.xml同时配置,会创建多个过滤器对象,造成过滤多次。
15.7过滤器典型应用
15.7.1过滤器解决编码
package com.zjl.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(value="/*")
public class EncodingFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException{
        
    }
    
    @Override
    public void doFilter(ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain) throws IOException,ServletException{
        //同一处理请求和响应的乱码
        servletRequest.setCharacterEncoding("UTF-8");
        servletResponse.setContentType("text/html;charset=utf-8");
        
        filterChain.doFilter(servletRequest,servletResponse);
    }
    
    @Override
    public void destory(){
        
    }
}
15.7.2权限验证

ShowAllAdminController

package com.zjl.servletProject.servlet.controller;

import com.zjl.servletProject.entity.Admin;
import com.zjl.servletProject.entity.Manager;
import com.zjl.servletProject.service.AdminService;
import com.zjl.servletProject.service.impl.AdminServiceImpl;

import javax.servlet.RequestDispather;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;

@WebServlet("/showallcontroller")
public class ShowAllAdminController extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
        //通过HttpSession完成权限控制
        //HttpSession session=req.Session();
        //Manager mgr=(Manager)session.getAttribute("mgr");
        //if(mgr != null){
            //只负责调用业务逻辑功能
            AdminService adminService = new AdminServiceImpl();
            
            List<Admin> adminList = adminService.showAllAdmin();
            
            //request作用域存储数据
            req.setAttribute("admins",adminList);
            //通过转发 跳转到显示结果servlet
            req.getRequestDispatcher("/showalljsp").forward(req,resp);
        //}else{
          //  resp.sendRedirect("/loginMgr.html");
        //}
    }
    
    @Override
    protected void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
        doGet(req,resp);
    }
}

CheckFilter

package com.zjl.servletProject.filter;

import com.zjl.servletProject.entity.Manager;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax servlet.http.HttpServletRequest;
import javax servlet.http.HttpServletResponse;
import javax servlet.http.HttpSession;
import java.io.IOException;
@WebFilter(value="/showallcontroller")
public class CheckFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException{
        
    }
    
    @Override
    public void doFilter(ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain) throws IOException,ServletException{
        //权限验证  验证管理员是否登录!
        //向下转型  拆箱
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        HttpSession session = request.getSession();
        if(mgr != null){//登录过
            filterChain.doFilter(request,response);
        }else{
            response.sendRedirect(request.getContextPath()+"/loginMgr.html");
        }
    }
    
    @Override
    public void destory(){
        
    }
}

十六、综合案例(EmpProject)

16.1数据库环境搭建

该案例是EmpProject员工管理系统。使用了两张表

  • EMP员工信息表
  • EmpManager管理员表
16.1.1创建数据库
create database emp;
16.1.2创建数据表
create table emp(
	id int primary key auto_increment,
    name varchar(20) not null,
    salary double not null,
    age int not null
)charset=utf8;

create table empmanager(
	username varchar(20) not null,
    password varchar(20) not null
)charset=utf8;
16.2创建Web项目

创建Web项目,导入相关jar包

  • commons-dbutils-1.7.jar
  • druid-1.1.5.jar
  • mysql-connector-java-5.1.25-bin.jar
  • ValidateCode.jar
16.3基础环境搭建

项目下创建包目录结构

  • com.zjl.emp.controller 调用业务逻辑Servlet
  • com.zjl.emp.dao 数据访问层
  • com.zjl.emp.impl 数据访问层实现类
  • com.zjl.emp.entity 实体类
  • com.zjl.emp.filter 过滤器
  • com.zjl.emp.jsp 打印显示页面Servlet
  • com.zjl.emp.service 业务逻辑层
  • com.zjl.emp.service.impl 业务逻辑层实现类
  • com.zjl.emp.utils 工具类
  • dadabase.properties 数据库连接及连接池配置文件
16.4管理员登录功能

仅展示Controller代码

package com.zjl.emp.controller;

import com.zjl.emp.entity.EmpManager;
import com.zjl.emp.service.EmpManagerService;
import com.zjl.emp.service.impl.EmpManagerServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet(name="EmpManagerLoginController",value="/manager/EmpManagerLoginController")
public class EmpManagerLoginController extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        //1.收参
        String username = request.getParameter("username");
        String password = request.getParameter("passwore");
        String inputVcode = request.getParameter("inputVcode");
        
        //2.校验验证码
        String codes = (String)request.getSession().getAttribute("codes");
        if(!inputVcode.isEmpty() && inputVcode.equalsIngoreCase(codes)){
            //调用业务逻辑实现登录
            EmpManagerService empMangerService = new EmpManagerServiceImpl();
            EmpManager empManager = empManagerService.login(username.password);
            if(empManager != null){
                //登录成功
                //存储在session作用域
                HttpSession session = request.getSession();
                session.setAttribute("empManager",empManager);
                //跳转到查询所有的controller
                response.sendRedirect(request.getContextPath()+"/manager/safe/showAllEmpController");
            }else{
                response.sendRedirect(request.getContextPath()+"/login.html");
            }
        }else{
            //验证码输入错误,跳转到登录页面
            response.sendRedirect(request.getContextPath()+"/login.html");
        }
    }
    
    @Override
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        doGet(request,response);
    }
}
16.5查询所有员工功能
16.5.1调用业务逻辑Controller
package com.zjl.emp.controller;

import com.zjl.emp.entity.Emp;
import com.zjl.emp.service.EmpService;
import com.zjl.emp.service.impl.EmpServiceImpl;
import sun.security.util.AuthResources_it;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@WebServlet(name="ShowAllEmpController",value="/manager/safe/showAllEmpController")
public class ShowAllEmpController extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        //权限验证存放在过滤器实现
        EmpService empService = new EmpServiceImpl();
        List<Emp> emps = empService.showAllEmp();
        
        request.setAttribute("emps",emps);
        
        request.getRequestDispatcher("/manager/safe/showAllEmp.jsp").forward(request,response);
    }
    
    @Override
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        doGet(request,response);
    }
}
16.5.2显示页面JSP
package com.zjl.emp.jsp;

import com.zjl.emp.entity.Emp;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

@WebServlet(name="ShowAllEmpJSP",value="/manager/safe/showAllEmpJSP")
public class ShowAllEmpJSP extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        //1.获取集合数据
        List<Emp> emps = (List<Emp>)request.getAttribute("emps");
        
        PrintWrite printWriter = response.getWriter();
        
        printWriter.println("<html>");
        printWriter.println("	<head>");
        printWriter.println("		<meta charset="UTF-8">");
        printWriter.println("		<title>查询所有员工页面</title>");
        printWriter.println("	<head>");
        printWriter.println("	<body>");
        printWriter.println("		<table boder='1'>");
        printWriter.println("			<tr>");
        printWriter.println("				<td>编号</td>");
        printWriter.println("				<td>姓名</td>");
        printWriter.println("				<td>工资</td>");
        printWriter.println("				<td>年龄</td>");
        printWriter.println("				<tdcolspan='2'>操作</td>");
        printWriter.println("			<、tr>");
        for(Emp emp : emps){
            printWriter.println("			<tr>");
            printWriter.println("				<td>"+emp.getId()+"</td>");
            printWriter.println("				<td>"+emp.getName()+"</td>");
            printWriter.println("				<td>"+emp.getSalary()+"</td>");
            printWriter.println("				<td>"+emp.getAge()+"</td>");
            printWriter.println("				<td><a href='"+request.getContextPath()+"/manager/safe/removeController?id="+emp.getId()+"'>删除</a></td>");
            printWriter.println("				<td><a href='"+request.getContextPath()+"/manager/safe/showController?id="+emp.getId()+"'>修改</a></td>");
            printWriter.println("			</tr>");
        }
        printWriter.println("		</table>");
        printWriter.println("	</body>");
        printWriter.println("</html>");
    }
    
    @Override
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        doGet(request,response);
    }
}
16.5.3权限验证过滤器
package com.zjl.emp.filter;

import com.zjl.emp.entity.EmpManager;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax servlet.http.HttpServletRequest;
import javax servlet.http.HttpServletResponse;
import javax servlet.http.HttpSession;
import java.io.IOException;
@WebFilter(value="/manager/safe/*")
public class CheckFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException{
        
    }
    
    @Override
    public void doFilter(ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain) throws IOException,ServletException{
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        
        HttpSession session = request.getSession();
        EmpManager empManager = (EmpManager)session.getAttribute("empManager");
        if(empManager != null){//登录过
            filterChain.doFilter(request,response);
        }else{
            response.sendRedirect(request.getContextPath()+"/loginMgr.html");
        }
    }
    
    @Override
    public void destory(){
        
    }
}
16.5.4字符编码过滤器
package com.zjl.emp.filter;

import javax.servlet.*;
import java.io.IOException;
@WebFilter(value="/manager/*")
public class CheckFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException{
        
    }
    
    @Override
    public void doFilter(ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain) throws IOException,ServletException{
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");
        filterChain.doFilter(servletRequest,servletResponse);
    }
    
    @Override
    public void destory(){
        
    }
}
16.6删除员工功能
16.6.1删除员工Controller
package com.zjl.emp.controller;

import com.zjl.emp.service.EmpService;
import com.zjl.emp.service.impl.EmpServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name="RemoveEmpController",value="/manager/safe/removeEmpController")
public class RemoveEmpController extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        Integer id = Integer.valueOf(request.getParameter("id"));
        
        EmpService empService = new EmpServiceImpl();
        empService.removeEmp(id);
        
        response.sendRedirect(request.getContextPath()+"/manager/safe/showAllEmpController");
    }
    
    @Override
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        doGet(request,response);
    }
}
16.7修改员工功能
16.7.1查询单个员工 Controller
package com.zjl.emp.controller;

import com.zjl.emp.entity.Emp;
import com.zjl.emp.service.EmpService;
import com.zjl.emp.service.impl.EmpServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name="ShowEmpController",value="/manager/safe/showEmpController")
public class ShowEmpController extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        Integer id = Integer.valueOf(request.getParameter("id"));
        
        EmpService empService = new EmpServiceImpl();
        empService.showEmp(id);
        
        request.setAttribute("emp",emp);
        
        request.getRequestDispatcher("/manager/safe/showUpdateEmpInfoJSP").forward(request,response);
    }
    
    @Override
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        doGet(request,response);
    }
}
16.7.2显示修改页面
package com.zjl.emp.jsp;

import com.zjl.emp.entity.Emp;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name="ShowUpdateEmpInfoController",value="/manager/safe/showUpdateEmpInfoJSP")
public class ShowUpdateEmpInfoJSP extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        Emp emp = (Emp)request.getAttribute("emp");
        
        PrintWrite printWriter = response.getWriter();
        
        printWriter.println("<html>");
        printWriter.println("	<head>");
        printWriter.println("		<meta charset="UTF-8">");
        printWriter.println("		<title>修改员工信息页面</title>");
        printWriter.println("	<head>");
        printWriter.println("	<body>");
        printWriter.println("		<form action='/empproject/manager/safe/updateEmpController' method='post'>");
        printWriter.println("			编号:<input type='text' name='id' value='"+emp.getId()+"' readonly/><br/>");
        printWriter.println("			姓名:<input type='text' name='name' value='"+emp.getName()+"'/><br/>");
        printWriter.println("			工资:<input type='text' name='salary' value='"+emp.getSalary()+"'/><br/>");
        printWriter.println("			年龄:<input type='text' name='age' value='"+emp.getAge()+"'/><br/>");
        printWriter.println("			<input type='submit' value='修改'/><br/>");
        printWriter.println("		</form>");
        printWriter.println("	</body>");
        printWriter.println("</html>");
    }
    
    @Override
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        doGet(request,response);
    }
}
16.7.3修改员工信息Controller
package com.zjl.emp.controller;

import com.zjl.emp.entity.Emp;
import com.zjl.emp.service.EmpService;
import com.zjl.emp.service.impl.EmpServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name="UpdateEmpController",value="/manager/safe/updateEmpController")
public class UpdateEmpController extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        //1.收参
        Integer id = Integer.valueOf(request.getParameter("id"));
        String name = request.getParameter("name");
        Double salary = Double.valueOf(request.getParameter("salary"));
        Integer age = Integer.valueOf(request.getParameter("age"));
        
        Emp emp = new Emp(id,name,salary,age);
        
        EmpService empService = new EmpServiceImpl();
        empService.modify(emp);
        
        response.sendRedirect(request.getContextPath+"/manager/safe/showAllEmpController");
    }
    
    @Override
    protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
        doGet(request,response);
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周景洛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值