JSP初始

说明:以下内容如有侵权,请联系删除

经验分享



DAY02

回顾

复制代码
1.软件的架构有哪两种
      B/S架构
      C/S架构
2.WEB资源分成哪两种
     静态资源
     动态资源
3. Tomcat项目发布的三种方式
     将资源文件放入webapps目录
     在server .xm1文件中配置【不推荐】
     配置独立的xm1文件
4. Idea配置Tomcat,创建web项目,部署web项目
     稍后会再次操作
5.浏览器开发工具查看HTTP协议请求和响应内容
     快捷键F12
6.请求内容
     请求首行:请求路径(携带参数)、请求方式、协议和版本
     请求头:都是一些key value的键值对【Referer User-Agent】
      请求体:就是你向服务器发起请求携带的数据【Get请求没有请求体、Post请求有请求体】
7.响应内容
     响应首行:响应状态码
     响应头:都是---些key value的键值对
     响应体:根据你的请求,服务器处理的---些结果数据

今日核心内容

复制代码
1.能够使用浏览器开发工具查看HTTP协议响应内容
2.能够理解HTTP协议响应内容
3.能够使用idea编写servlet
4.能够使用注解开发servlet
5.能够说出servlet生命周期方法执行流程
6.能够说出servlet运行原理

第一章 Servlet入门

1.1 Servlet概述

Servlet它是一个接口,它的本质也是java程序,这个java程序是运行在服务器端的!【Javase阶段的程序都是从main方法开始执行的】

作用

★接收用户发起请求携带的数据

★处理请求(看需求)【程序员编写代码】

★将处理的结果响应到客户端浏览器

第二章 Servlet快速入门

目标:编写一个普通的java类,通过浏览器可以访问

2.1 代码编写

(1)创建web项目

(2)编写普通java类,实现servlet接口

复制代码
编写servlet的步骤:
1.编写一个类去实现servlet接口
2.重写servlet接口中所有的抽象方法【在服务方法service中编写代码】
3.在web.xm1文件中配置(浏览器访问路径与servlet处理类的对应关系)
java 复制代码
package com.itheima.web.servlet;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

public class HelloServlet 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("HelloServlet~~~");
    }

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

    @Override
    public void destroy() {

    }
}

(3)配置web.xml

配置servlet网络访问路径

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

    <!--Servlet入门案例的配置-->
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.itheima.web.servlet.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/HelloServlet</url-pattern>
    </servlet-mapping>
</web-app>

(4)部署web项目

(5)启动测试

2.2 执行原理

第三章 Servlet相关API

3.1 声明周期相关

思想介绍

生命周期:指的是一个对象从生(创建)到死(销毁)的一个过程

本身我们使用面向对象的思想,应该先创建类的对象,然后拿着对象去调用方法来完成某些功能~====>>>现在的程序个在main方法中作为起点运行,而是放在Tomcat服务器中。====>>>类的对象由服务器容器Tomcat帮我们创建!

Tips:但凡与Servlet相关的所有类的对象的创建都是由服务器容器负责创建的!

java 复制代码
    /*
        下面3个方法就是与servlet生命周期相关的方法
     */

    //初始化方法,创建完对象后就会执行!
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    //服务方法:接收用户发起请求携带的数据、处理请求(看需求)【程序员编写代码】、将处理的结果响应到客户端浏览器
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    //销毁方法
    @Override
    public void destroy() {

    }

代码演示

(1)LifeServlet

java 复制代码
public class LifeServlet implements Servlet {

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("LifeServlet正在处理用户请求。。。");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("LifeServlet正在进行初始化。。。");
    }

    public LifeServlet(){
        System.out.println("LifeServlet对象创建了。。。");
    }

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

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

}

(2)配置web.xml

java 复制代码
    <servlet>
        <servlet-name>LifeServlet</servlet-name>
        <servlet-class>com.itheima.web.servlet.LifeServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LifeServlet</servlet-name>
        <url-pattern>/LifeServlet</url-pattern>
    </servlet-mapping>
复制代码
servlet生命周期:
默认情况,用户第一次发起请求,由服务器容器Tomcat创建Servlet实例对象,对象在整个Servlet生命周期中只会创建一次,然后紧接着调用init(Servletconfig config)方法来完成初始化操作,此方法在整个Servlet生命周期中只会执行1次!然后调用serivce(ServletRequest req, ServletResponse resp)服务方法来处理用户请求,这个方法在整个Servlet生命周期中会被执行多次(每访问一次Servlet就执行1次)。当关闭服务器的时候,会调用destroy(方法完成Servlet的销毁!

3.2 扩展:load-on-startup配置

3.3 拓展:ServletConfig

(1)EncodeServlet

java 复制代码
public class EncodeServlet implements Servlet {

    @Override
    public void init(ServletConfig config) throws ServletException {
        // 获得当前Servlet名称
        System.out.println(config.getServletName()); // EncodeServlet

        // 获得ServletContext对象 【重点】
        ServletContext context = config.getServletContext();
        System.out.println(context.getContextPath()); // /day02_code

        // 获得所有配置信息的初始化的名称
        Enumeration<String> parameterNames = config.getInitParameterNames();
        while (parameterNames.hasMoreElements()){
            System.out.println(parameterNames.nextElement());
        }

        // 获得配置的指定初始化名称对应的值
        System.out.println(config.getInitParameter("username")); // EncodeServlet
    }

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

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


    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }

    @Override
    public void destroy() {

    }
}

(2)配置web.xml

第四章 Servlet体系结构

实现Servlet除了实现Servlet接口方式以外,还有2种方式:

4.1 GenericServlet


4.2 HttpServlet[开发常用!]


4.3 Servlet体系结构

第五章 Servlet路径

5.1 url-pattern

作用:将一个请求网络地址和servlet类建立一个映射关系

Servlet映射多个url


url映射模式

5.2 相对/绝对路径






第六章 Servlet3.0

通过注解配置Servlet,简化web.xml配置Servlet复杂性,提高开发效率,几乎所有的框架都在使用注解



DAY03

回顾

复制代码
1. servlet概述
Servlet它其实是一套规范(接口),我们需要实现这个接口里面的方法,就能完成一些功能(接收用户的请求数据<请求首行、请求头、请求体>、处理请求<根据用户的需求来决定>、响应处理的结果到客户端)【Servlet程序都是在服务器中运行!】

2. xml配置servlet【掌握】
编写一个类去实现servlet接口(实现servlet接口中所有的抽象方法)【麻烦~】
编写一个类去继承GenericServlet抽象类(只需要重写抽象方法service(ServletRequestreq, ServletResponse resp))【它无法处理与Http协议相关的内容】
编写一个类去继承HttpServlet抽象类(根据用户的请求方式来重写对应的doXxx方法)。
HttpServlet是一个抽象类,但是里面没有抽象方法,java为什么这么设计呢?只要是一个抽象类,必须通过继承使用,java将HttpServlet设计成一个抽象类,说明不想让程序员自己去创建它的实例对象。因为HttpServlet的实例对象都必须是由服务器容器创建。

在web.xml文件中去配置:在浏览器地址栏访问的路径与servlet处理类的对应关系!
<servlet>
	<servlet-name>Servlet处理类的类名</servlet-name>
	<servlet-class>servlet处理类的全限定类名</servlet-c1ass></servlet>
<servlet-mapping>
	<servlet-name>Servlet处理类的类名</servlet-name>
	<url-pattern>/abc</url-pattern>
</ servlet-mapping>

3. servlet生命周期
默认情况,在用户第一次访问的时候,由服务器容器Tomcat负责创建Servlet实例对象!调用init(Servletconfig config)方法完成初始化(在整个servlet生命周期中只会执行一次! ),然后会调用服务法service(ServletRequest req,ServletResponse resp)来处理用户请求(在整个servlet生命周期中会执行多次!),当我们停止服务器,此时会调用destroy()方法完成销毁操作。通过配置1oad-on-stratup,让servlet在服务器启动的时候就创建~

4. serv1et体系结构
servlet接口
Genericservlet抽象类
Httpservlet抽象类

5. Servlet3.o
在Servlet处理类的上面加上下面的注解!
@WebServlet(urlPatterns=" /abc" , name="")

今日核心内容

复制代码
1.Request概述

2. reuqest获取请求消息内容
	请求行
	请求头
	请求参数(体)【重点】
	
3. request其他功能
	请求转发
	域对象
	
4.案例:用户登录

第一章 Request概述

用户通过浏览器访问服务器时,Tomcat将HTTP请求中所有的信息都封装在Request对象中

作用:开发人员可以通过request对象方法,来获取浏览器发送的所有信息

所有请求相关的数据都封装在这个对象中,我们可以通过这个对象相关的方法来获得对应的数据!

第二章 Request获取Http请求信息

2.1 获取请求首行信息

复制代码
例如:【Http请求协议:请求首行的内容】
	GET  /day09_request/requestDemo1 HTTP/1.1

相关API:
	1.获取请求方式 GET【掌握】
			String getMethod()
	2.获取项目虚拟路径(项目名)/day-9_request【掌握】
			String getContextPath()
	3.获取URI/day09_request/requestDemo1
			统一资源标识符(范围广)共和国
			String getRequestURI()
	4.获取URL http://localhost:8080/day09_request/requestDemo1
			统一资源定位符(确定某一个地址)中华人名共和国
			StringBuffer getRequestURL()
	5.获取协议和版本号 HTTP/1.1
			String getProtocol()
	6.获取客户端IP
			String getRemoteAddr()
java 复制代码
/*
    HttpServletRequest对象 与请求首行相关的方法!
 */
@WebServlet(name = "AServlet", urlPatterns = "/AServlet")
public class AServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        // 获得用户的请求方式
        String method = request.getMethod();
        System.out.println("用户请求方式:" + method);

        // 获得项目的虚拟路径(项目名称的路径)
        String contextPath = request.getContextPath();
        System.out.println("项目虚拟路径是:" + contextPath);

        // 获得uri 【端口号之后,参数之前】
        String uri = request.getRequestURI();
        System.out.println("uri: " + uri);

        // 获得url 【一整个长串,也不包含参数】
        StringBuffer url = request.getRequestURL();
        System.out.println("url: " + url);

        // 获得客户端ip地址
        String addr = request.getRemoteAddr();
        System.out.println("发起请求客户端ip地址是:" + addr);

        // 协议版本
        String protocol = request.getProtocol();
        System.out.println("协议:" + protocol);

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        doGet(request, response);
    }

}

2.2 获取请求头信息



案例:视频防盗链


案例:浏览器兼容性

2.3 获取请求参数(体)

xml 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>form</title>
    
    </head>
    <body>
        <h3>get方式:</h3>
        <form action="/day03_code/EServlet" method="get">
            用户:<input type="text" name="username"> <br>
            密码:<input type="password" name="password"> <br>
            爱好:
            <input type="checkbox" name="hobby" value="somke"/>抽烟
            <input type="checkbox" name="hobby" value="drink"/>喝酒
            <input type="checkbox" name="hobby" value="perm"/>烫头
            <input type="submit" value="get提交...">
        </form>
        <h3>post方式:</h3>
        <form action="/day03_code/EServlet" method="post">
            用户:<input type="text" name="username"> <br>
            密码:<input type="password" name="password"> <br>
            爱好:
            <input type="checkbox" name="hobby" value="somke"/>抽烟
            <input type="checkbox" name="hobby" value="drink"/>喝酒
            <input type="checkbox" name="hobby" value="perm"/>烫头
            <input type="submit" value="post提交...">
        </form>
    </body>
</html>
java 复制代码
/*
    HttpServletRequest与请求参数相关的方法
 */
@WebServlet(name = "EServlet", urlPatterns = "/EServlet")
public class EServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {

        // 获得请求参数:用户名
        String username = request.getParameter("username");// 参数是页面表单name属性的值
        System.out.println("用户在表单中输入的用户名是:" + username);

        // 获得请求参数:密码
        String password = request.getParameter("password");
        System.out.println("用户在表单中输入的密码是:"+password);

        // 获得请求参数:爱好  【getParameter方法适合一个参数一个值的情形!】
        /*String hobby = request.getParameter("hobby");
        System.out.println("爱好:" + hobby); // 丢失后面的数据*/

        // 一个参数名对应多个参数值: getParameterValues方法!
        String[] hobbies = request.getParameterValues("hobby");
        for (String hobby : hobbies) {
            System.out.println("爱好:" + hobby);
        }

        System.out.println("===========================================");
        // 一次性获得提交请求携带的所有参数数据
        Map<String, String[]> map = request.getParameterMap();
        for(String key:map.keySet()){
            String[] values = map.get(key);
            for (String value : values) {
                System.out.println("key:" + key +"======>>>" + "value:" + value);
            }
        }

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        doGet(request, response);
    }

}
java 复制代码
/*
    HttpServletRequest与请求参数相关的方法
 */
@WebServlet(name = "EServlet", urlPatterns = "/EServlet")
public class EServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {

        // 告诉服务器使用指定的码表来解码 【这行代码需要放在方法的第一行】
        request.setCharacterEncoding("utf-8"); // 此方法只对请求体有效!

        // 获得请求参数:用户名
        String username = request.getParameter("username");// 参数是页面表单name属性的值
        System.out.println("用户在表单中输入的用户名是:" + username);

        // 获得请求参数:密码
        String password = request.getParameter("password");
        System.out.println("用户在表单中输入的密码是:"+password);

        // 获得请求参数:爱好  【getParameter方法适合一个参数一个值的情形!】
        /*String hobby = request.getParameter("hobby");
        System.out.println("爱好:" + hobby); // 丢失后面的数据*/

        // 一个参数名对应多个参数值: getParameterValues方法!
        String[] hobbies = request.getParameterValues("hobby");
        for (String hobby : hobbies) {
            System.out.println("爱好:" + hobby);
        }

        System.out.println("===========================================");
        // 一次性获得提交请求携带的所有参数数据
        Map<String, String[]> map = request.getParameterMap();
        for(String key:map.keySet()){
            String[] values = map.get(key);
            for (String value : values) {
                System.out.println("key:" + key +"======>>>" + "value:" + value);
            }
        }

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        doGet(request, response);
    }

}

2.4 BeanUtils

(1)JavaBean

java 复制代码
/*
    普通Java类:用于封装页面表单提交的数据

    Serializable:标记接口(里面什么也没有,保证JavaBean能够顺利的完成序列化)
 */
public class User implements Serializable {

    /*
        类中的属性来自于页面表单的属性!【建议属性与页面表单的name属性值保持一致!】
     */
    private String username;// 用户名

    private String password; // 密码

    private String[] hobby; // 爱好

    public User() {

    }

    public User(String username, String password, String[] hobby) {
        this.username = username;
        this.password = password;
        this.hobby = hobby;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String[] getHobby() {
        return hobby;
    }

    public void setHobby(String[] hobby) {
        this.hobby = hobby;
    }
}

(2)页面表单

(3)FServlet

java 复制代码
/*
    BeanUtils工具类的使用
 */
@WebServlet(name = "FServlet", urlPatterns = "/FServlet")
public class FServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        request.setCharacterEncoding("utf-8");

        // 一次性获得所有的请求参数数据
        Map<String, String[]> map = request.getParameterMap();

        // 创建对象 【将页面表单用户输入的数据封装到这个user对象中】
        User user = new User();

        // 使用BeanUtils工具类将map中的数据封装到user对象中去
        try {
            BeanUtils.populate(user,map);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 测试
        System.out.println(user.getUsername());
        System.out.println(user.getPassword());
        System.out.println(Arrays.toString(user.getHobby()));

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        doGet(request, response);
    }

}

第三章 Request其它功能

3.1 请求转发




3.2 域对象(共享数据)







第四章 案例:用户登录


代码实现

(1)编写login.html

(2)User实体类

说明:直接使用BeanUtils知识点的User类即可

(3)LoginServlet

java 复制代码
/*
    用户登录Servlet
 */
@WebServlet(name = "LoginServlet", urlPatterns = "/LoginServlet")
public class LoginServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charset=utf-8");
        request.setCharacterEncoding("utf-8");

        // 一次性获得用户在页面表单输入的用户名和密码数据
        Map<String, String[]> map = request.getParameterMap();

        // 创建JavaBean的示例对象
        User user = new User();

        // 使用BeanUtils封装数据到user对象
        try {
            BeanUtils.populate(user, map);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 只有用户名为jack,密码为123的用户才能登录成功~   【作业:文件存储一些事先准备好的数据(用户名和密码)】
        if("jack".equals(user.getUsername()) && "123".equals(user.getPassword())){
            // 登录成功~ 将提示信息保存到request域中
            request.setAttribute("msg","<h3 style='color:green'>恭喜您,登录成功~</h3>");
            // 转发到登录成功的Servlet
            request.getRequestDispatcher("SuccessServlet").forward(request,response);
        }else{
            // 登陆失败~将提示信息保存到request域中
            request.setAttribute("msg","<h3 style='color:red'>用户名或密码错误~</h3>");
            // 转发到登录成功的Servlet
            request.getRequestDispatcher("FailServlet").forward(request,response);
        }

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        doGet(request, response);
    }

}

(4)SuccessServlet

(5)FailServlet

附录

Servlet模板设置

java 复制代码
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")
@javax.servlet.annotation.WebServlet("/${Class_Name}")
public class ${Class_Name} extends javax.servlet.http.HttpServlet {

    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {
        this.doPost(request,response);
    }

    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException {

    }
 
}

DAY04

回顾

复制代码
1. request作用
HttpServletRequest子接口(具备处理与Http请求协议相关的能力),主要用于处理所有与请求相关的内容(请求首行、请求头、请求参数<体>),作为域对象(存放数据),请求转发(服务器内部资源的一个跳转)。

2. request获取Http请求信息
   请求行
     string getMethod(;//获得用户的请求方式
     string getRemoteAddr() ;//获得客户端的ip地址请求头
     string getHeader(string headerName);//获得指定名称请求头的值
   Referer :进入当前资源的上一个历史地址―【防盗链】
   User-Agent:客户端浏览器与操作系统的版本信息[浏览器兼容问题]

  请求参数(体)
     string getParameter(string name);//获得指定参数名称的值【一个参数名称对应一个参数值】
     string[] getParametervalues(String name);//获得一个参数名称对应多个参数值
     Map<String,string[]> getPar ameterMap();/一次性获得所有的参数和值,构成一个map集合

3.请求转发
    服务器内部资源的一个跳转~一次请求,浏览器地址栏不会发生改变~
    request.getRequestDispatcher("服务器内部资源的一个路径").forward(request , response);

4.域对象(共享数据)
    何时创建?
    当用户发起请求的时候何时销毁?
    当得到服务器响应的时候作用范围?
    一次请求~【请求转发是一次请求,超过一次请求,那么之前向r equest域中存放的数据就获取不到。】

5.案例:用户登录【书写3次~】
从登录页面(表单),点击登录按钮,指向服务器端的Loginservlet在LoginServlet中,获得用户在表单中输入的用户名和密码数据,借助BeanUtils封装到User对象中去,用指定的用户名与用户输入的用户名密码数据进行匹配,匹配成功,说明登录成功,将提示信息保存到request域中,转发到一个SuccessServlet,获取request域中的数据,显示到浏览器;匹配失败,说明登录失败,将提示信息保存到r equest域中,转发到一个Fai1servlet,获取request域中的数据,显示到浏览器。

今日目标

复制代码
1. servletcontext:应用上下文对象
2. response【重点】
3.综合案例

第一章 ServletContext

1.1 概述

web容器(tomcat)在启动时,它会为每个web项目创建一个对应的ServletContext对象

它代表:当前web项目

1.2 域对象(共享数据)




1.3 获取资源在服务器的真实地址


1.4 获取全局的配置参数


1.5 获取文件MIME类型


1.6 案例:统计网站的访问次数


java 复制代码
/*
    统计访问网站次数
 */
@WebServlet(urlPatterns = "/EServlet")
public class EServlet extends HttpServlet {

    // 这个初始化方法,在执行init(ServletConfig config)的时候,会调用无参的init()方法
    @Override
    public void init() throws ServletException {
        // 定义一个变量充当计数器
        int count = 0;
        // 将计数器放入ServletContext域中
        getServletContext().setAttribute("count", count);
    }

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获得ServletContext
        ServletContext context = getServletContext();

        // 从ServletContext域中获取计数器变量
        int count = (int) context.getAttribute("count");

        // 将访问的次数输出到控制台
        System.out.println("本网站已被访问:" + ++count + "次!");

        // 将更新后的计数器的值重新放入ServletContext域中
        context.setAttribute("count",count);

    }

    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 处理POST请求中文乱码
        req.setCharacterEncoding("utf-8");
        // 处理响应中文乱码[目前照抄]
        resp.setContentType("text/html;charset=utf-8");
        // 调用doGet
        doGet(req, resp);
    }
}

第二章 Response

2.1 概述

2.2 设置Http响应消息




2.3 响应重定向





2.4 响应定时刷新


2.5 响应中文




第三章 综合案例

3.1 点击切换验证码(js实现)

验证码制作Servlet工具类

java 复制代码
/*
   跟我一起了解一下验证码的制作代码....
 */
@WebServlet(urlPatterns = "/CheckcodeServlet")
public class CheckcodeServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //  创建画布
        int width = 120;
        int height = 40;
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        //  获得画笔
        Graphics g = bufferedImage.getGraphics();
        //  填充背景颜色
        g.setColor(Color.white);
        g.fillRect(0, 0, width, height);
        //  绘制边框
        g.setColor(Color.red);
        g.drawRect(0, 0, width - 1, height - 1);
        //  生成随机字符
        //  准备数据
        String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
        //  准备随机对象
        Random r = new Random();
        //  声明一个变量 保存验证码
        String code = "";
        //  书写4个随机字符
        for (int i = 0; i < 4; i++) {
            //  设置字体
            g.setFont(new Font("宋体", Font.BOLD, 28));
            //  设置随机颜色
            g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));

            String str = data.charAt(r.nextInt(data.length())) + "";
            g.drawString(str, 10 + i * 28, 30);

            //  将新的字符 保存到验证码中
            code = code + str;
        }
        //  绘制干扰线
        for (int i = 0; i < 6; i++) {
            //  设置随机颜色
            g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));

            g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
        }

        //  将验证码 打印到控制台
        System.out.println(code);

        //  将验证码放到session中
        request.getSession().setAttribute("code_session", code);

        //  将画布显示在浏览器中
        ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

3.1 点击切换验证码(自己使用js实现)

xml 复制代码
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/day04_code/LoginServlet">
            用户名:<input type="text" name="username"><br>
            密码:<input type="password" name="password"><br>
            验证码:<img src="/day04_code/CheckcodeServlet" onclick="changeImage()"><br>
            <input type="submit" value="登录">
        </form>
        <script>
            function changeImage() {
                let imgs=document.querySelector("img")
                imgs.src="/day04_code/CheckcodeServlet?time="+new Date().getTime()
            }
        </script>
    </body>
</html>

3.1 点击切换验证码(自己使用jQuery实现)

xml 复制代码
3.1 点击切换验证码(自己使用jQuery实现)
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="../js/jquery-3.4.1.min.js"></script>
    </head>
    <body>
        <form action="/day04_code/LoginServlet">
            用户名:<input type="text" name="username"><br>
            密码:<input type="password" name="password"><br>
            验证码:<img src="/day04_code/CheckcodeServlet"><br>
            <input type="submit" value="登录">
        </form>
        <script>
            $("img").click(function () {
                //this是js对象,必须转化成jQuery对象
               $(this).attr("src","/day04_code/CheckcodeServlet?time="+new Date().getTime())
            })
        </script>
    </body>
</html>

3.2 文件下载


3.2.1 使用链接下载文件

3.2.2 使用Servlet下载文件【推荐】

(1)download.html

(2)DownLoadServlet

java 复制代码
@WebServlet(name = "DownLoadServlet", urlPatterns = "/DownLoadServlet")
public class DownLoadServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charset=utf-8");
        request.setCharacterEncoding("utf-8");

        // 获得filename参数的值 (资源文件名称)
        String filename = request.getParameter("filename");

        // 设置2个头
        response.setHeader("Content-Disposition","attachment;filename="+filename);

        // 此头可以省略
        String mimeType = getServletContext().getMimeType(filename);
        response.setHeader("Content-Type",mimeType);

        // 设置2个流
        String realPath = getServletContext().getRealPath("/download/" + filename);
        //System.out.println(realPath);

        FileInputStream is = new FileInputStream(realPath);

        ServletOutputStream os = response.getOutputStream();

        // 流拷贝
        IOUtils.copy(is,os);

        // 释放资源
        os.close();
        is.close();

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        doGet(request, response);
    }

}

问题:点击中文文件名称(禽兽.jpg)下载,发现下载框,文件名显示不正常,但是数据是没有问题的

(3)中文乱码

DAY05

回顾

复制代码
1. ServletContext对象--代表的是整个WEB应用(与项目共存)
    生命周期:
       在服务器启动的时候对象创建
       当服务器停止或者项目移除,对象销毁

    作为域对象相关的方法:【必须先设置值才能获取到值】
       设置值: void setAttribute(string name,object obj);
       获取值:object getAttribute(string name);
       删除值: void removeAttribute(string name);

2. Servletcontext功能方法
     获得资源文件的真实路径: string getRealPath(String path);//参数是一个虚拟的路径
     书写虚拟路径:/资源文件名称的路径︰【/代表的是项目,后面的路径就是相对于项目的路径,最终得到真实地址】

     可以获得项目路径: String getContextPath();//得到的结果是:/day04_codea

     获得指定资源文件的Mime类型: string getMimeType(String filename);

3. Response对象
    所有与响应相关的内容都封装到这个对象中去了~

Http响应协议:
   首行:状态码(200 302 304 404405 500)
       setstatus (int sc);
   头: Refr esh(定时刷新)、Location(结合302状态码完成重定向)
       setHeader (string name , string value);
   体:响应到客户端浏览器的内容
       getwriter ().write(;/l/字符流【纯文本数据】
       getoutputStream().write();//字节流【图片、视频、音频(文件下载)】

重定向:
  特点:
      它是两次请求
      浏览器地址栏会发生改变
      重定向的资源位置可以是服务器内部,也可以是服务器外部
      无法获取request域中的数据

4. Response响应中文
     一行代码搞定一切∶既规定了服务器响应中文数据的编码的码表(utf-8),又告诉了浏览器使用该码表来解析数据(utf-8)
    response.setContentType("text/htm1; charset=utf-8");//放在响应数据之前~
5.综合案例
    点击切换验证码
          回忆之前的javascript的知识(页面加载函数,事件绑定,元素数据获取,属性操作,Date对象)
    文件下载
         核心:2个头,2个流
            2个头:
                      Content-Type:文件的Mime类型
                      Content-Disposition:告诉浏览器无论如何都要弹出下载框
            2个流:文件通过2个流来传递数据
                     通过服务器指定文件的真实路径来创建一个输入流
                     通过response对象获得输出流getoutputstream

第一章 会话概述

1.1 什么是会话?

1.2 会话技术

2.1 概述

2.2 快速入门


java 复制代码
/*
    Cookie操作
        获取Cookie的数据
 */
@WebServlet(name = "BServlet", urlPatterns = "/BServlet")
public class BServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charset=utf-8");
        request.setCharacterEncoding("utf-8");

        // 获得所有的Cookie
        Cookie[] cookies = request.getCookies();

        // 非空判断
        if(cookies!=null){
            // 遍历
            for (Cookie cookie : cookies) {
                // 判断(拿指定名称的cookie)
                if("username".equals(cookie.getName())){
                    // 获取该cookie的值
                    System.out.println(cookie.getValue());
                }
            }
        }

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        doGet(request, response);
    }

}

2.3 工作原理

2.4 Cookie细节

服务器发送多个Cookie?

java 复制代码
/*
    服务器端向客户端响应多个Cookie
 */
@WebServlet(name = "CServlet", urlPatterns = "/CServlet")
public class CServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charset=utf-8");
        request.setCharacterEncoding("utf-8");

        // 创建Cookie对象,并设置数据
        Cookie cookie1 = new Cookie("username","jack");
        // 创建Cookie对象,并设置数据
        Cookie cookie2 = new Cookie("password","123");

        // 响应cookie
        response.addCookie(cookie1);
        response.addCookie(cookie2);

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        doGet(request, response);
    }

}


Cookie在浏览器保存时间?

java 复制代码
/*
    Cookie的生命周期:
 */
@WebServlet(name = "DServlet", urlPatterns = "/DServlet")
public class DServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charset=utf-8");
        request.setCharacterEncoding("utf-8");

        // 创建Cookie对象并设置值
        Cookie cookie = new Cookie("username","jack");

        // 设置Cookie的存活时间
        cookie.setMaxAge(60*60*24*7); // 一周

        // 响应cookie
        response.addCookie(cookie);

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        doGet(request, response);
    }

}




Cookie是否可以存储中文?



Cookie共享数据的范围?


此时,测试,我们发现在FServlet中设置的cookie数据,去访问Gservlet,并没有携带带服务器端




2.5 Cookie特点

第三章 综合案例

3.1 用户上次访问记录

需求

访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您的到来。

如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:XXXX。

需求分析

代码实现

LastVisitServlet

java 复制代码
@WebServlet(name = "LastVisitServlet", urlPatterns = "/LastVisitServlet")
public class LastVisitServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charset=utf-8");

        // 获得指定名称的Cookie  (last_time)
        Cookie[] cookies = request.getCookies();
        Cookie last_time = CookieUtils.findCookieByName(cookies, "last_time");

        // 判断
        if(last_time!=null){
            // 说明不是第一次
            String value = last_time.getValue();
            // 显示在浏览器
            response.getWriter().write("<h3 style='color:red'>客官,您上一次访问本店的时间是:"+value+"</h3>");

        }else{
            // 说明是第一次
            response.getWriter().write("<h3 style='color:green'>客官,你是第一次光临本店,欢迎光临~</h3>");
        }

        // 不管是不是第一次,我们都需要更新当前时间到cookie中去
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日-HH:mm:ss");
        String date = simpleDateFormat.format(new Date());

        Cookie cookie = new Cookie("last_time",date);

        // 设置cookie
        cookie.setMaxAge(60*60*24*365);

        // 响应
        response.addCookie(cookie);

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        request.setCharacterEncoding("utf-8");
        doGet(request, response);
    }

}

3.2 jsp初体验



3.3 商品浏览记录【第一遍根据画图找这抄】

需求

做一个商品页面,当我们访问后,在页面上点击查看商品浏览记录后,可以查看到以前浏览过的商品信息

需求分析

代码实现

(1)goods.html

(2)GoodslnfoServlet

java 复制代码
/*
    商品浏览记录Servlet
 */
@WebServlet(name = "GoodsInfoServlet", urlPatterns = "/GoodsInfoServlet")
public class GoodsInfoServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charset=utf-8");

        // 1.获得请求参数name的值
        String product = request.getParameter("name");

        // 2.展示当前浏览的商品信息
        response.getWriter().write("您当前正在浏览的商品为:" + product);

        // 3.获得指定名称的cookie
        Cookie cookie = CookieUtils.findCookieByName(request.getCookies(), "goods_name");

        // 4.判断
        if(cookie ==null){
            // 5.之前没有浏览记录,将当前正在浏览的商品添加到cookie
            cookie = new Cookie("goods_name",product);
        }else{
            // 6.之前有浏览记录,取出 【浏览记录可能有很多的】 统一格式: 小米10-华为p40
            String value = cookie.getValue();
            // 7.判断当前商品是否在cookie中
            String[] split = value.split("-");
            List<String> list = Arrays.asList(split);
            if(!list.contains(product)) {
                // 8.不包含,追加,不做其他操作
                value = value + "-" + product; // 小米10-华为P40
            }

            // 9. 将value,重置到cookie中
            cookie = new Cookie("goods_name",value);
        }

        // 10.设置cookie的存活时间
        cookie.setMaxAge(60*60*24*365);
        // 11.响应
        response.addCookie(cookie);

        // 12.制作链接
        response.getWriter().write("<br><a href='/day05_code/html/goods.html'>继续浏览</a>");
        response.getWriter().write("<br><a href='/day05_code/jsp/history.jsp'>浏览记录</a>");

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        request.setCharacterEncoding("utf-8");
        doGet(request, response);
    }

}

(3)history.jsp

xml 复制代码
<%@ page import="com.itheima.web.servlet.utils.CookieUtils" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>浏览记录页面</title>
    </head>
    <body>
        <%
            // 编写Java代码
            // 获得指定名称的cookie
            Cookie cookie = CookieUtils.findCookieByName(request.getCookies(), "goods_name");
        
            // 非空判断
            if(cookie == null){
                // 没有记录
                out.write("暂无浏览记录...");
            }else{
                // 有记录,遍历显示
                out.write("浏览记录如下:<br>");
                String value = cookie.getValue(); // 格式:小米10-华为P40
                // 遍历
                for (String product : value.split("-")) {
                    // 显示
                    out.write("<span sytle='color:red'>"+product+"</span><br>");
                }
            }
        %>
    </body>
</html>

DAY06

回顾

复制代码
1.会话技术
http是无状态协议,多次请求之间相互独立,不能共享数据会话技术为了解决多次请求之间,共享数据问题
cookie将数据存储到客户端【当用户发起请求,在服务器端创建cookie,然后将Cookie响应到客户端浏览器保存】

2. cookie快速入门
设置cookie 【cookie只能存放字符串数据】
   //创建Cookie对象并设置数据
   Cookie cookie = new cookie(string name , string value);
   //将Cookie响应到客户端浏览器
   response.addcookie(cookie);
接收cookie【用户发起第二次请求,到达服务器端,服务器去获取之前存储在客户端的数据】
  //获得所有的Cookie
  Cookie[]cookies = request.getCookies();
  /从这些Cookie中获取指定名称的cookie
  for (Cookie cookie:cookies){
     //判断
     if("goods_name ".equals(cookie.getName()){
        //获得指定名称cookie的值
        string value = cookie.getvalue();
     }
  }

3. cookie使用细节
服务器一次可以发送多个cookie

tomcat8及以上版本支持中文,但不支持特殊符号(空格、逗号、分号、加号)
URLEncoder编码
URLDecoder解码

cookie.setPath(String path);设置cookie的携带路径
一旦设置cookie的路径,以后想要访问服务器将cookie成功携带过去,那么访问的路径必须包含cookie设置
的路径

cookie.setMaxAge(int second);// cookie默认是一个会话级别【关闭浏览器,cookie就没了】
正数:持久的cookie
负数:会话级别的cookie
零:直接杀死cookie[自动登录(复选框),将cookie杀死,或者不携带cookie]

4. cookie特点
数据存储在客户端,可以存中文,单个大小不能超过4KB,数量不能超过20个,浏览器存储所有服务器的cookie总个数不超过300个,数据不太安全..

5.综合案例
上次访问时间--> jsp
     <%
       放入Servlet中的代码
     %>
商品浏览记录

第一章 Session

1.1 概述

1.2 快速入门





1.3 工作原理

1.4 Session细节

客户端关闭,服务器不关闭

java 复制代码
@WebServlet(name = "AServlet", urlPatterns = "/AServlet")
public class AServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charset=utf-8");

        // 获得HttpSession对象
        HttpSession session = request.getSession();
        System.out.println(session);

        // 向session域中设置值
        session.setAttribute("msg","session域中的数据");

        // 不用响应(session是存在服务器端的)

        ///////////////////////////////////////////////////
        // 手动修改cookie,关闭保留JSESSION
        String id = session.getId();
        Cookie cookie = new Cookie("JSESSIONID",id);

        // 设置路径
        cookie.setPath("/day06_code");
        // 设置存活时间
        cookie.setMaxAge(60*60*24);

        // 响应
        response.addCookie(cookie);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        request.setCharacterEncoding("utf-8");
        doGet(request, response);
    }

}

客户端不关闭,服务器关闭



生命周期

URL重写

1.5 Session特点

第二章 三大域对象总结

request、session、ServletContext

2.1 API

2.2 生命周期

ServletContext域对象

HttpSession域对象

HttpServletRequest域对象

第三章 综合案例

3.1 用户登陆(验证码)

需求

用户访问带有验证码的登录页面,输入用户名,密码以及验证码实现登录功能。

需求分析

代码实现

(1)创建web项目

(2)导入验证码Servlet

(3)login.jsp

java 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>Insert title here</title>
      <%--引入jQuery核心js文件--%>
      <script src="../js/jquery-1.11.0.js"></script>
      <script>
         /*window.onload = function () {
            // alert("xxx");
            // 为图片绑定一个鼠标单击事件
            document.getElementsByTagName("img")[0].onclick = function () {
               // alert("xxx");
               this.src="/day04_code/CheckcodeServlet?time="+ new Date().getTime();
            }
         }*/
   
         // 页面加载函数
         $(function () {
            // 为图片标签绑定一个鼠标单击事件
            $("img").click(function () {
               $(this).prop("src","/day06_code/CheckcodeServlet?time="+ new Date().getTime());
            });
         });
   
      </script>
   </head>
   <body>
      <form action="/day06_code/LoginServlet">
         用户名:<input type="text" name="username" />
         <br/>
         密码:<input type="password" name="password" /><br/>
         验证码:<input type="text" name="code">
         <img src="/day06_code/CheckcodeServlet" />
         <br>
         <input type="submit" value="登录"/>
      </form>
   </body>
</html>

(4)LoginServlet

java 复制代码
/**
        *
        *  用户登录的Servlet
        *
        */
@WebServlet(name = "LoginServlet", urlPatterns = "/LoginServlet")
public class LoginServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charset=utf-8");

        //////////////////////////////// 验证码校验成功才行!
        // 1.获得用户在表单中输入的验证码
        String code = request.getParameter("code");

        // 2.获得服务器生成的验证码数据
        String verifyCode = (String) request.getSession().getAttribute("code_session");

        // 3.校验
        if(!verifyCode.equalsIgnoreCase(code)){
            // 校验失败,将错误的提示信息保存到request域
            request.setAttribute("vcodemsg","验证码校验失败");
            // 转发
            request.getRequestDispatcher("/jsp/login.jsp").forward(request,response);
            // 不让后面的代码执行
            return;
        }

        /////////////////////////////// 程序能执行到这里,说明验证码校验成功,要校验用户名和密码数据了
        // 4. 获得用户名和密码数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        // 5. 判断
        if(!("jack".equals(username) && "123".equals(password))){
            // 用户名或密码错误
            request.setAttribute("umsg","用户名或密码错误");
            // 转发
            request.getRequestDispatcher("/jsp/login.jsp").forward(request,response);
            // 不让后面的代码执行
            return;
        }

        /////////////////////////////// 程序能执行到这里,说明验证码校验成功,用户名和密码也校验成功了
        // 6. 将用户信息(用户名)保存到session域中
        request.getSession().setAttribute("username",username);
        // 7. 重定向到 success.jsp
        response.sendRedirect("/day06_code/jsp/success.jsp");

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        request.setCharacterEncoding("utf-8");
        doGet(request, response);
    }

}

(5)login.jsp

(6)success.jsp

使用ajax实现用户登录(ajax实现的主要是验证码内容)

java 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Insert title here</title>
        <%--引入jQuery核心js文件--%>
        <script src="js/jquery-1.11.0.js"></script>
    </head>
    <body>
    <form action="/day06_code/LoginServlet">
        用户名:<input type="text" name="username" />
        <br/>
        密码:<input type="password" name="password" /><br/>
        验证码:<input type="text" id="check">
        <img src="/day06_code/CheckcodeServlet" /><span style="color: red"></span>
        <br>
        <input type="hidden" name="method" value="login">
        <input type="submit" value="登录"/>
        <script>
            $("img").click(function () {
                $(this).prop("src","/day06_code/CheckcodeServlet?time="+ new Date().getTime());
            })

            $("#check").blur(function () {
                $("span").html("")
                let code=$(this).val();
                $.ajax({
                    url:"/day06_code/LoginServlet",
                    data:{"code":code,"method":"checkCode"},
                    type:"post",
                    dataType:"text",
                    success:function (data) {
                        $("span").html(data)
                    }
                })
            })
        </script>
    </form>
    </body>
</html>
java 复制代码
@WebServlet(name = "LoginServlet", urlPatterns = "/LoginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        String method = request.getParameter("method");
        if ("checkCode".equals(method)) {
            checkCode(request,response);
        }else if("login".equals(method)){
            login(request,response);
        }
    }

    protected void checkCode(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String code_session = (String)request.getSession().getAttribute("code_session");
        String code = request.getParameter("code");
        if (!code_session.equals(code)) {
            response.getWriter().write("验证码错误");
        }
    }

    protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

}

3.2 商品购物车

需求

有一个商品页面,可以点击超链接将商品添加到购物车,还有一个超链接点击它的时候可以查看购物车中商品信息

需求分析

代码实现

(1)goods.jsp

(2)AddCartServlet

java 复制代码
/**
 商品添加到购物车
 */
@WebServlet(name = "AddCartServlet", urlPatterns = "/AddCartServlet")
public class AddCartServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charset=utf-8");

        // 1. 获取请求参数name的值
        String product = request.getParameter("name");

        // 2. 响应结果到浏览器
        response.getWriter().write(product+", 商品已成功加入购物车!<br><br>");

        // 3. 从session中获得购物车
        Map<String,Integer> cart = (Map<String, Integer>) request.getSession().getAttribute("cart");

        // 4. 判断购物车是否为空
        if(cart ==null){
            // 创建购车对象
            cart = new HashMap<>();
        }

        // 5. 判断购物车中是否有当前添加的商品
        if(cart.containsKey(product)){
            // 6. 购物车中存在当前添加的商品,不用添加商品到购物车,直接将数量+1
            Integer oldCount = cart.get(product);
            cart.put(product,oldCount+1);
        }else{
            // 7. 购物车中不存在当前添加的商品,添加到购物车
            cart.put(product,1);
        }

        // 8.重新将购物车添加到session
        request.getSession().setAttribute("cart",cart);

        // 9.记录浏览超链接
        response.getWriter().write("<a href='/day06_code/jsp/goods.jsp'>继续浏览</a><br><br>");

        // 10.查看购物超链接
        response.getWriter().write("<a href='/day06_code/jsp/cart.jsp'>查看购物车</a>");

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        request.setCharacterEncoding("utf-8");
        doGet(request, response);
    }

}

(3)cart.jsp

java 复制代码
<%@ page import="java.util.Map" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>cart</title>
    </head>
    <body>
        <h3>购物车页面</h3>
        
        <table border="1" width="200px" align="center">
            <tr>
                <th>商品</th>
                <th>数量</th>
            </tr>
            <%
                // 1. 从session域中获得购物车
                Map<String ,Integer> cart = (Map<String, Integer>) request.getSession().getAttribute("cart");
                // 2. 判断是否为空
                if(cart == null){
                    // 说明没有
                    out.write("购物车内部没有任何商品<br><br>");
                }else{
                    // 3. 遍历
                    for(String key:cart.keySet()){
                        out.write("<tr><td>"+key+"</td><td>"+cart.get(key)+"</td></tr>");
                    }
                }
            %>
        
        </table>
    </body>
</html>

DAY07

回顾

复制代码
1. session作用
在一次会话中,多次请求间,共享数据,在服务器中存储
谷歌:向服务器发起请求【只要没关闭浏览器,那么此时所有的操作都在一次会话中(都是同一个Session对象)】
IE:向服务器发起请求【只要没关闭浏览器,那么所有的操作都在一次会话中,与上面的不是同一个会话】
Httpsession session = request.getsession();

2. session快速入门
获得session对象--Httpsession session = request.getsession();
存数据--session.setAttribute(string name , 0bject value);
取数据--object object = session.getAttribute(string name);
工作原理--依赖cookie技术

3. session使用细节
(1)浏览器关闭,服务器不关闭,二次获取session数据是否一致?
Session对象以及里面的数据依旧保留在服务器端,只不过你关闭浏览器,cookie没了,里面保存的
JSESSIONID丢失了,下次访问的时候,获得session就是一个新的!【默认情况是拿不到数据】
其实,我们可以让第二次请求里面依旧获得第一次请求向session中设置的值~【手动维护JESESSIONID】

(2)浏览器不关闭,服务器关闭,二次获取session数据是否一致?
正常关闭: session对象以及里面的数据会进行序列化到磁盘,下次启动服务器将其加载到内存。【可以的】
正常关闭服务器后,会在磁盘的一个位置看到一个session持久化的文件,再次启动这个文件会消失
非正常关闭,session对象会销毁!

(3)生命周期
创建?
   request.getsessionO;【不够精确】
   浏览器携带jsessionid与服务器不匹配时创建
销毁?
  非正常关闭为活跃30分钟自杀
作用范围?
  在一次会话中,多次请求间

4.三大域对象
servletContex
tHttpsession
HttpservletRequest

第一章 JSP

1.1 概述

在很多动态网页中,绝大部分内容都是固定不变的,只有局部内容需要动态产生和改变。为了弥补Servlet的缺陷,SUN公司在Servlet的基础上推出了JSP (Java Server Pages)【它的本质就是一个Servlet】

JSP是简化Servlet编写的一种技术,它将Java代码和HTML标签混合在同一个文件中编写,页面动态资源使用java代码,页面静态资源使用html标签。

简单来说:可以在html页面中嵌套java代码

作用:简化书写,展示动态页面

1.2 快速入门

1.3 工作原理

1.4 脚本和注释

脚本

java 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>jsp脚本</title>
    </head>
    <body>
        <!--声明脚本:以前在类中方法外,能书写什么java代码,这个脚本中就可以写什么样的java代码-->
        <%!
            // 此处可以定义成员变量
            int number = 100;
            // 定义方法
            public static int getSum(int a,int b){
                return a + b;
            }
        %>
        
        <!--输出脚本:在service方法中进行数据的输出-->
        <%=number%>
        
        <!--java代码片段脚本:以前在java类里面的方法中能书写什么java代码,这个脚本中就可以书写什么样的java代码-->
        <%
            // 这里定义了一个局部变量
            int count = 10;
            // 调用方法
            int sum = getSum(10, 20);
        %>
        
        <!--输出脚本:在service方法中进行数据的输出-->
        <%=count%>
        
        <!--输出脚本:在service方法中进行数据的输出-->
        <%=sum%>
    </body>
</html>

注意: jsp一次编译可以多次运行(不需要重新编译,除非你修改了jsp源码)

注释

1.5 指令


page指令


include指令(静态包含)



taglib指令(铺垫明天的知识)


1.6 内置对象



pagecontext内置对象【注意全域查找方法】

java 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>pageContext域对象</title>
    </head>
    <body>
        <%--模拟Servlet向四个域对象中设置值--%>
        <%
            // 向page域中设置值
            //pageContext.setAttribute("book","西游记");
            // 向request域中设置值
            //request.setAttribute("book","红楼梦");
            pageContext.setAttribute("book","红楼梦",2);
            // 向session域中设置值
            session.setAttribute("book","三国演义");
            // 向servletContext域中设置值
            application.setAttribute("book","水浒传");
        %>
        
        <%--从四个域中获取数据--%>
        <%=pageContext.getAttribute("book")%><br>
        <%--<%=pageContext.getAttribute("book",1)%><br>
        <%=pageContext.getAttribute("book",2)%><br>
        <%=pageContext.getAttribute("book",3)%><br>
        <%=pageContext.getAttribute("book",4)%><br>--%>
        
        
        <%--全域查找方法:从小范围到大范围挨个找,知道找到就不继续找,没有找到就继续,所有域都没找到返回null--%>
        <%=pageContext.findAttribute("book")%>
    </body>
</html>

1.7 JSP动作标签


动态包含


请求转发

第二章 MVC模式

2.1 JSP发展史



2.2 MVC介绍


DAY08

回顾


第一章 EL表达式

1.1 从域中获取普通单值

java 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>EL表达式获取域中的数据</title>
    </head>
    <body>
        <h3>EL表达式获取域中的普通单值</h3>
        <%--这里嵌套java片段,模拟在Servlet中向域中设置值--%>
        <%
            // page域
            //pageContext.setAttribute("book","西游记");
            // request域
            pageContext.setAttribute("book","三国演义",2);
            // session域
            pageContext.setAttribute("book","红楼梦",3);
            // servletContext域
            pageContext.setAttribute("book","水浒传",4);
        %>

        <%--使用jsp脚本从域中获取值--%>
        <%=pageContext.getAttribute("book",1)%><br>
        <%=pageContext.getAttribute("book",2)%><br>
        <%=pageContext.getAttribute("book",3)%><br>
        <%=pageContext.getAttribute("book",4)%><br><br>
        <%--全域查找方法--%>
        <%=pageContext.findAttribute("book")%>

        <!--  使用jsp输出脚本获取到的数据没拿到显示的是null  -->

        <%--使用el表达式从域中获取数据--%>
        ${pageScope.book}<br>
        ${requestScope.book}<br>
        ${sessionScope.book}<br>
        ${applicationScope.book}<br><br>
        <!--全域查找-->
        ${book}
    </body>
</html>

1.2 从域中获取数组中的数据

1.3 从域中获取List集合中的数据

1.4 从域中获取Map集合中的数据

以后,我们在Servlet中,去查询数据库的数据,得到多一些数据,可能需要封装到map,此时,将map数据保存到域中,然后跳转到jsp页面

java 复制代码
<%@ page import="java.util.HashMap" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>EL表达式获取域中的数据</title>
    </head>
    <body>
        <h3>EL表达式获取域中的Map集合里面的数据</h3>
        <%--这里嵌套java片段,模拟在Servlet中向域中设置值--%>
        <%
            // 定义集合
            HashMap<String,String> map = new HashMap<>();
            // 添加数据
            map.put("username","健哥哥");
            map.put("age","18");
            map.put("address","东京");
            map.put("singleton","yes");
        
            // 将Map集合添加到域中
            pageContext.setAttribute("map",map);
        %>
        
        <!--获得Map集合中的居住人地: 东京-->
        ${map.address}<br>
        ${map['address']}<br>
        ${map["address"]}
    </body>
</html>

注意: map里面的数据是双列的,获得值有多种写法

1.5 从域中获取JavaBean里面的数据

以后我们经常在Servlet中处理的数据封装到一个对象中去!然后将这个对象保存域中,跳转到jsp页面

比如:用户登录

JavaBean

java 复制代码
public class Student implements Serializable {
    private String name;
    private String age;
    private String address;

    public Student() {
    }

    public Student(String name, String age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

获取域中JavaBean里面的数据

1.6 从域中获取多个对象构成的集合里面的数据

java 复制代码
<%@ page import="com.itheima.domain.Student" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>EL表达式获取域中的数据</title>
    </head>
    <body>
        <h3>EL表达式获取域中的JavaBean里面的数据</h3>
        <%--这里嵌套java片段,模拟在Servlet中向域中设置值--%>
        <%
            // 创建多个Student对象
            Student student1 = new Student("健哥哥1","18","东京1");
            Student student2 = new Student("健哥哥2","28","东京2");
            Student student3 = new Student("健哥哥3","38","东京3");
            Student student4 = new Student("健哥哥4","48","东京4");
            Student student5 = new Student("健哥哥5","58","东京5");

            // 创建集合
            ArrayList<Student> students = new ArrayList<>();

            // 将多个有数据的学生对象添加到集合中
            students.add(student1);
            students.add(student2);
            students.add(student3);
            students.add(student4);
            students.add(student5);

            // 将多个student对象构成的list集合添加到域中
            pageContext.setAttribute("students",students);
        %>

        <!--获得多个student对象中的名字: 健哥哥4-->
        ${students[3].name}<br>
        ${students[3]['name']}<br>
        ${students[3]["name"]}<br>
    </body>
</html>

1.7 EL表达式取值的小结

1.8 EL表达式进行运算




1.9 EL表达式操作WEB常用对象


第二章 jstl标签

前面我们知道,jsp2.0规范要求页面尽量少些java代码,el表达式能够取代输出脚本,奔着这个目标,也希望将java代码片段也使用标签(jstl给它取代了,但是,没有完全实现了!!!

jstl标签其底层依旧是java代码!只不过,我们使用标签就行(它会自动执行该标签对应的java代码),方便后期的维护!

2.1 jstl标签的基本使用步骤

2.2 jstl常用标签

jstl标签一般会配合el表达式使用【在Servlet中向域里面设置值,然后跳转jsp页面,在jsp页面使用el表达式从域中取出数据,然后使用jstl标签进行处理】

if标签

choose标签

java 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h3>choose标签</h3>
        <!-- 如果年龄超过18岁,那么允许进入网吧上网 -->
        
        <!-- 向域中设置数据: 保存用户年龄的数据 【下面的标签等价于:request.setAttribute("age","20"); 】 -->
        <c:set scope="request" var="age" value="8"></c:set>
        
        <c:choose>
            <%--这个when类似于java中的if--%>
            <c:when test="${age >=18}">
                哥们,你可以自行进入网吧上网了。。。
            </c:when>
            <%--这个when类似于Java中的else if--%>
            <c:when test="${age>=10}">
                哥们,你可以在父母的陪同下进入网吧上网。。。
            </c:when>
            <%--otherwise类似于java的else--%>
            <c:otherwise>
                小毛孩,赶紧回家,不要让大人担心。。。
            </c:otherwise>
        </c:choose>
    
    </body>
</html>

foreach标签

java 复制代码
<%@ page import="com.Student" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h3>forEach标签</h3>
        <!--模拟Servlet,向域中设置多个对象构成的集合-->

        <%
            // 创建多个Student对象
            Student student1 = new Student("健哥哥1","18","东京1");
            Student student2 = new Student("健哥哥2","28","东京2");
            Student student3 = new Student("健哥哥3","38","东京3");
            Student student4 = new Student("健哥哥4","48","东京4");
            Student student5 = new Student("健哥哥5","58","东京5");

            // 创建集合
            ArrayList<Student> students = new ArrayList<>();

            // 将多个有数据的学生对象添加到集合中
            students.add(student1);
            students.add(student2);
            students.add(student3);
            students.add(student4);
            students.add(student5);

            // 将多个student对象构成的list集合添加到域中
            pageContext.setAttribute("students",students);
        %>

        <!-- 使用jstl标签将域中的数据获取并遍历(多个学生对象构成的list集合) -->

        <table border="1px" align="center" width="600px" height = "230px">
            <tr>
                <th>用户名</th>
                <th>年龄</th>
                <th>居住地</th>
            </tr>
            <!-- 先判断-->
            <c:if test="${not empty students}">
                <c:forEach items="${students}" var="student" begin="0" end="4" step="2" varStatus="vs">
                    <tr align="center">
                        <td>${vs.count}</td>
                        <td>${student.name}</td>
                        <td>${student.age}</td>
                        <td>${student.address}</td>
                    </tr>
                </c:forEach>
            </c:if>

        </table>
    </body>
</html>

第三章 三层架构

DAY09

回顾


第一章 Filter概述

生活中的过滤器

净水器、空气净化器、地铁安检、山大王

web中的过滤器

当用户访问服务器资源时,过滤器将请求拦截下来,完成一些通用的操作

应用场景

如:登录验证、统一编码处理、敏感字符过滤

保安大叔对胸卡的检查就是一个过滤器~

第二章 Filter快速入门

需求:用户访问某个jsp页面,在访问到达目标资源jsp页面之前,我们添加一个过滤器

2.1 xml配置

(1)编写java类,实现filter接口

java 复制代码
import javax.servlet.*;
import java.io.IOException;

/*
    过滤器类: 对quick.jsp过滤
        1. 编写的一个类去实现Filter接口(需要重写接口中所有的抽象方法)
        2. 在web.xml文件中配置(配置你要过滤的访问资源路径与过滤器处理类的对应关系)
 */
public class QuickFilter implements Filter {

    // 空实现(没有方法体)
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    /*
        对目标资源进行过滤器的核心方法
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        // 是否放行
        chain.doFilter(servletRequest,servletResponse); // 不写这行代码,就是不放行
    }

    @Override
    public void destroy() {

    }
}

(2)配置web.xml

2.2 注解配置

注意:玩注解的话,需要把web.xml中filter标签注释

(1)编写java类,实现filter接口

java 复制代码
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/*
    过滤器类: 对quick.jsp过滤
        1. 编写的一个类去实现Filter接口(需要重写接口中所有的抽象方法)
        2. 在实现类上面添加一个注解 @WebFilter(urlPatterns = "/jsp/quick.jsp")
 */
@WebFilter(urlPatterns = "/jsp/quick.jsp")
public class QuickFilter implements Filter {

    // 空实现(没有方法体)
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    /*
        对目标资源进行过滤器的核心方法
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        System.out.println("已经进入过滤器了。。。");
        // 是否放行
        //chain.doFilter(servletRequest,servletResponse); // 不写这行代码,就是不放行
    }

    @Override
    public void destroy() {

    }
}

(2)配置@WebFilter

第三章 Filter工作原理

第四章 使用细节

4.1 生命周期

java 复制代码
import javax.servlet.*;
import java.io.IOException;

/*
    Filter的生命周期:一个对象从创建到销毁的过程

 */
public class AFilter implements Filter {

    // 构造方法
    public AFilter(){
        System.out.println("AFilter创建了。。。");
    }

    // 初始化方法
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("AFilter正在进行初始化。。。");
    }

    // 拦截过滤方法
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("AFilter正在对a.jsp目标资源进行过滤。。。");
        // 放行
        filterChain.doFilter(servletRequest,servletResponse);
    }

    // 销毁方法
    @Override
    public void destroy() {
        System.out.println("AFitler销毁了。。。");
    }
}


java 复制代码
import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;

/*
    FilterConfig
       重点关注获得ServletContext对象

 */
public class BFilter implements Filter {

    // 初始化方法
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 获得当前Filter的名字
        System.out.println(filterConfig.getFilterName());

        // 可以获得配置的所有参数名称
        Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
        while (initParameterNames.hasMoreElements()){
            String name = initParameterNames.nextElement();
            System.out.println(name);
            // 可以获得配置的指定参数的值
            System.out.println(filterConfig.getInitParameter(name));
        }

        // 获得ServletContext对象
        System.out.println(filterConfig.getServletContext().getContextPath());

    }

    // 拦截过滤方法
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    }

    // 销毁方法
    @Override
    public void destroy() {
    }
}

4.2 拦截路径



4.3 拦截方式


xml版本


注解版本

4.4 过滤器链





4.5 注解和xml使用

第五章 综合案例

5.1 用户评论留言

需求

用户访问某论坛网站,可以对文章比赛等内容进行留言

需求分析

代码实现

5.2 统一网站编码(请求和响应)

需求

tomcat8.5版本中已经将get请求的中文乱码解决了,但是post请求还存在中文乱码浏览器发出的任何请求,通过过滤器统一处理中文乱码

需求分析

代码实现

java 复制代码
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/*
    处理全站中文乱码的过滤器
 */
@WebFilter(filterName = "EncodingFilter",urlPatterns = "/*")
public class EncodingFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        System.out.println("进来了。。。");

        // 对req和resp进行强转
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        // 获得用户请求方式
        String method = request.getMethod();
        System.out.println(method);

        // 判断
        if("post".equalsIgnoreCase(method)){
            // 处理post请求中文乱码
            request.setCharacterEncoding("utf-8");
        }

        // 处理响应中文乱码
        response.setContentType("text/html;charset=utf-8");

        // 放行
        chain.doFilter(request, response);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

5.3 非法字符拦截

需求

当用户发出非法言论的时候,提示用户言论非法警告信息

需求分析

代码实现

(2)WordsFilter

java 复制代码
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

/*
    屏蔽非法字符
 */
@WebFilter(filterName = "WordFilter",urlPatterns = "/WordsServlet")
public class WordFilter implements Filter {

    // 定义集合
    private List<String> wordList = new ArrayList<>();

    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //System.out.println(wordList);
        // 强转
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        // 获得用户输入的内容
        String content = request.getParameter("content");

        //System.out.println(content);

        // 遍历集合
        for (String word : wordList) {
            // word: 一个一个的既定非法字符
            // 判断用户输入的内容是否包含了既定非法字符
            if(content.contains(word)){
                // 非法了
                response.getWriter().write("您的评论含有非法字符,网络警察已关注!");
                // 不放行
                return;
            }
        }

        chain.doFilter(req, resp);
    }

    /*
        读取配置文件,已经设定好的非法字符
     */
    public void init(FilterConfig config) throws ServletException {

        // 加载配置文件数据到对象
        ResourceBundle bundle = ResourceBundle.getBundle("data");

        // 读指定key的值
        String keywords = bundle.getString("keywords");

        try {
            // 本身文件是utf-8的,但是服务器拿数据,采用iso8859-1编码的,此时出现的乱码,解回来重新编码
            keywords = new String(keywords.getBytes("iso8859-1"),"utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        // 切割
        String[] words = keywords.split(",");

        // 遍历获得单个
        for (String word : words) {
            // 添加到集合
            wordList.add(word);
        }

    }
}

5.4 非法字符过滤

需求

当用户发出非法言论的时候,在servlet中输出的时候:用"*"替代

你是个笨蛋-->你是个**

我们希望,在获得用户输入的数据时候就已经拿到了处理好的数据(已经将非法字符屏蔽了)

用户在页面表单输入:孙子,你好!

调用request.getParameter("content")拿到的数据是**,你好!

技术分析

java 复制代码
/*
    回顾装饰(器)模式
 */
public class TestDecorator {

    public static void main(String[] args) {
        Phone phone = new Lvjing(new Meiyan(new HuaWei()));
        phone.take();
        phone.call();
    }

}

// 接口规范
interface Phone {
    void take();

    void call();
}

// 被包装类,一会对他增强
class HuaWei implements Phone {

    @Override
    public void take() {
        System.out.println("3200W像素拍照");
    }

    @Override
    public void call() {
        System.out.println("打电话");
    }
}

// 包装抽象类,做一个默认的实现,调用原有的功能
abstract class PhoneWrapper implements Phone {

    private Phone phone;

    public PhoneWrapper(Phone phone) {
        this.phone = phone;
    }

    @Override
    public void take() {
        phone.take();
    }

    @Override
    public void call() {
        phone.call();
    }
}

// 美颜增强
class Meiyan extends PhoneWrapper {

    public Meiyan(Phone phone) {
        super(phone);
    }

    @Override
    public void take() {
        // 调用拍照的原有功能
        super.take();
        System.out.println("美颜...");
    }
}

// 滤镜增强
class Lvjing extends PhoneWrapper {

    public Lvjing(Phone phone) {
        super(phone);
    }

    @Override
    public void take() {
        super.take();// 原有功能
        System.out.println("滤镜");

    }
}

需求分析

代码实现

注意:需要将WordsFilter过滤器的注解注释

(1)自定义MyHttpServletRequest

java 复制代码
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.List;

/*
    装饰者:
        1.装饰类要与被装饰类(HttpServletRequestWrapper:里面的getParameter方法只能获得用户输入的参数数据)一样,实现共同的父接口或者继承共同的父类
        2.装饰类中需要提供一个带参(默认实现类,其他我们需要的对象)构造!
        3.在装饰类中提供一个成员变量
        4.对需要增强的方法进行重写
        5.不需要重写的,继承(直接拥有了父类的功能),实现接口(重写额方法体内部,调用默认实现类的方法)
 */
public class MyHttpServletRequest extends HttpServletRequestWrapper {

    // 非法词库
    private List<String> wordList;

    public MyHttpServletRequest(HttpServletRequest request) {
        super(request);
    }

    @Override
    public String getParameter(String name) {
        // 调用原有的功能,获取用户输入的值
        String parameter = super.getParameter(name);

        // 对非法词库过滤...
        for (String word : wordList) {
            // word: 一个一个的既定非法字符
            // 判断用户输入的内容是否包含了既定非法字符
            if(parameter.contains(word)){
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < word.length(); i++) {
                    sb.append("*");
                }
                parameter=parameter.replace(word,sb);
            }
        }

        return parameter;
    }
}

(2)编写WordsProFilter

java 复制代码
package com.itheima.web.filter;

import com.itheima.web.servlet.MyHttpServletRequest;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;

@WebFilter("/WordsServlet")
public class WordsProFilter implements Filter {

    private List<String> wordList;


    public void init(FilterConfig config) throws ServletException {
        // 1.加载配置文件
        /*
            ResourceBundle这哥们 专门读取src目录下的properties配置文件,不需要写后缀名
         */
        ResourceBundle words = ResourceBundle.getBundle("words");
        // 2.读取keyword关键字内容
        String keyword = words.getString("keyword"); // 傻叉,大爷的,二大爷的
        // 3.split切割,转为list集合
        wordList = Arrays.asList(keyword.split(","));
        System.out.println("加载非法词库:"+wordList);

    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException {
        // 向下转型
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        // 对request对象进行包装 (过滤)
        MyHttpServletRequest requestPro = new MyHttpServletRequest(request, wordList);

        // 放行
        chain.doFilter(requestPro, response);
    }

    public void destroy() {

    }

}

附录

Filter模板设置
java 复制代码
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")
@javax.servlet.annotation.WebFilter("/${Entity_Name}")
public class ${Class_Name} implements javax.servlet.Filter {

    public void init(javax.servlet.FilterConfig config) throws javax.servlet.ServletException {

    }


    public void doFilter(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse, javax.servlet.FilterChain chain) throws javax.servlet.ServletException, java.io.IOException {
      
        // 放行
        chain.doFilter(servletRequest, servletResponse);
    }

    public void destroy() {
    
    }

}

DAY10 Listener&综合案例

回顾


第一章 综合案例

1.1 环境搭建

创建模块(项目)

省略

导入案例原型

加入操作需要的jar包

导入案例需要的数据

导入案例需要的JavaBean

1.2 用户查询功能

需求

使用三层架构和MVC模式开发代码,完成用户显示列表功能。

查询所有用户信息的执行流程

页面入口代码(index.html)

UserServlet

java 复制代码
/*
    用户模块web层
 */
@WebServlet(name = "UserServlet", urlPatterns = "/UserServlet")
public class UserServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charset=utf-8");
        // 获得请求参数action
        String action = request.getParameter("action");
        // 判断
        if("findAllUser".equals(action)){
            // 要进行查询所有用户信息的功能
            findAllUser(request,response);
        }
    }

    /*
        查询所有用户信息的方法
     */
    public void findAllUser(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        // 直接调用service层查询所有用户信息的方法
        UserService service = new UserService();
        List<User> users = service.findAllUser();
        System.out.println(users);

        // 将查询的集合结果数据保存到request域中
        request.setAttribute("users",users);

        // 转发到list.jsp页面
        request.getRequestDispatcher("/list.jsp").forward(request,response);

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        request.setCharacterEncoding("utf-8");
        doGet(request, response);
    }

}

UserService

UserDao

list.jsp页面

1.3 添加用户功能

需求

点击添加用户跳转添加用户页面,在添加用户页面,添加新的用户

添加用户信息执行流程

add.html入口页面

UserServlet

UserService

UserDao

1.4 删除用户功能

需求

点击删除按钮删除当前一整行数据,删除之后重新查询全部展示删除效果

删除指定用户信息的执行流程

list.jsp页面


UserServlet

UserService

UserDao

1.5 修改用户功能

用户回显【异步实现】

需求

点击"修改"按钮,跳转到更新页面(回显数据)

异步操作:请求在哪个页面发起,那么从服务器端得到的数据就先显示在哪个页面







修改用户

需求

重写输入用户信息,点击提交,更新系统





DAY11 AJAX&文件上传

回顾

第一章 JSON回顾

1.1 json知识点的核心

1.2 json格式数据的定义和获取



json数据的key都是字符串类型的,值可以是任意类型的

1.3 java对象转成json格式数据


将单个对象转成json格式数据


将多个对象构成的List集合转成json

java 复制代码
/*
   多个对象构成的List集合转成json格式的数据
*/
    @Test
    public void test2() throws JsonProcessingException {
        // 创建一个集合对象
        ArrayList<Person> persons = new ArrayList<>();
        // 创建多个Person对象
        Person p1 = new Person("p001","jack","北京顺义");
        Person p2 = new Person("p002","jerry","河北邯郸");
        Person p3 = new Person("p003","rose","湖南郴州");
        Person p4 = new Person("p004","tom","四川成都");
        Person p5 = new Person("p005","lucy","山东烟台");
        // 将多个对象添加到集合
        persons.add(p1);
        persons.add(p2);
        persons.add(p3);
        persons.add(p4);
        persons.add(p5);
        /////上面代码仅仅只是在模拟以后从数据库查询出来的结果数据////////

        // 将多个对象转成json格式的数据
        ObjectMapper om = new ObjectMapper();
        String str = om.writeValueAsString(persons);
        System.out.println(str);
        // [{"pid":"p001","pname":"jack","paddress":"北京顺义"},{"pid":"p002","pname":"jerry","paddress":"河北邯郸"},{"pid":"p003","pname":"rose","paddress":"湖南郴州"},{"pid":"p004","pname":"tom","paddress":"四川成都"},{"pid":"p005","pname":"lucy","paddress":"山东烟台"}]

    }

第二章 案例:检查用户名是否可用

需求

在用户注册页面,输入用户名,当用户名输入框失去焦点时,发送异步请求,将输入框的用户名传递给服务器进行是否存在的校验。

2.1 技术分析

2.2 功能的执行流程

2.3 代码实现




UserServlet

为了演示对象转json数据,这里强加了

java 复制代码
UserServlet
/*
    用户名异步校验web层
 */
@WebServlet(name = "UserServlet", urlPatterns = "/UserServlet")
public class UserServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charset=utf-8");
        // 获得请求参数username
        String username = request.getParameter("username");
        //System.out.println(username);
        // 调用service层根据用户名查询用户信息的方法
        UserService service = new UserService();
        User user = service.findUserByUsername(username);
        // 将查询结果转成json格式数据
        ObjectMapper om = new ObjectMapper();
        String json = om.writeValueAsString(user);
        //System.out.println(json);
        // 直接通过响应体响应
        response.getWriter().write(json);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        request.setCharacterEncoding("utf-8");
        doGet(request, response);
    }

}



register.jsp页面回调函数

java 复制代码
$.ajax({
          url:"${pageContext.request.contextPath}/UserServlet",
          type:"post",
          data:{"username":username},
          success:function(user){
              // 判断
              if(user==null){
                  // 说明该用户名可用
                  $("#usernameinfo").html('<span class="label label-success">用户名可用</span>');
                  // 将注册按钮的禁用状态取消
$("#sub").prop("disabled",false);
              }else{
                  // 说明该用户名不可用
                  $("#usernameinfo").html('<span class="label label-danger">用户名不可用</span>');
                  // 禁用注册提交按钮
                  $("#sub").prop("disabled",true);
              }
          },
          dataType:"json"
      });

第三章 案例:文件上传


3.1 技术分析

文件上传三要素

补充




文件上传技术

1.使用apache提供工具类commons-fileupload (今天讲,最麻烦的...)

2.使用servlet3.0版本,通过注解实现(黑马旅游网)

3.使用springMVC框架(最简单,底层使用commons-fileupload)

3.2 代码实现【抄一遍即可】





FileUploadServlet

java 复制代码
/*
    文件上传Servlet
 */
@WebServlet(name = "FileUploadServlet", urlPatterns = "/FileUploadServlet")
public class FileUploadServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        response.setContentType("text/html;charset=utf-8");

        // 1.创建磁盘文件项的工厂对象
        DiskFileItemFactory factory = new DiskFileItemFactory();

        // 2.通过磁盘文件项工厂对象创建文件上传核心对象
        ServletFileUpload fileUpload = new ServletFileUpload(factory);

        try {
            // 3. 解析请求(request),获得所有的表单项
            List<FileItem> fileItems = fileUpload.parseRequest(request);
            //System.out.println(fileItems.size()); // 2

            // 4. 遍历集合
            for (FileItem fileItem : fileItems) {
                // 5. 判断
                if(fileItem.isFormField()){ // fileItem.isFormField() 结果为true,说明是一个普通项
                    // 获得name属性值
                    String username = fileItem.getFieldName();
                    //System.out.println("普通项username的名字是:" + username); // 获得name属性的值
                    // 获得value属性值
                    String value = fileItem.getString();
                    //System.out.println("普通项username的值是:" + value); // 获得value属性的值

                    // 接下来,具体普通项代码如何编写,取决于需求
                }else{
                    // 6. 说明是文件上传项,获得文件上传项的名称
                    String filename = fileItem.getName();
                    //System.out.println(filename); // temp.jpg
                    // 7. 根据文件上传的名称和存储的位置,创建输出流
                    String realPath = getServletContext().getRealPath("/upload");
                    //System.out.println(realPath);
                    // 8. 判断upload目录在服务器中是否存在
                    File file = new File(realPath);
                    if(!file.exists()){
                        // 不存在,创建一个
                        file.mkdirs();
                    }

                    //System.out.println(realPath);
                    OutputStream os = new FileOutputStream(realPath + "/" + filename);

                    // 9. 获得输入流
                    InputStream is = fileItem.getInputStream();

                    // 10. 流拷贝
                    IOUtils.copy(is,os);

                    // 11. 释放资源
                    os.close();
                    is.close();

                    // 12. 给出友好提示
                    response.getWriter().write("success!");
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        request.setCharacterEncoding("utf-8");
        doGet(request, response);
    }

}

第四章 Listener

4.1 概述

生活中的监听器

我们很多商场有摄像头,监视着客户的一举一动。如果客户有违法行为,商场可以采取相应的措施。

javaweb中的监听器

在我们的java程序中,有时也需要监视某些事情,一旦被监视的对象发生相应的变化,我们应该采取相应的操作。监听web三大域对象:HttpServletRequest、HttpSession、ServletContext

4.2 快速入门

监听器在web开发中使用的比较少;见的机会就更少了,今天我们使用ServletContextListenner来带领大家学习下监听器,因为这个监听器是监听器中使用率最高的一个,且监听器的使用方式都差不多。

我们使用这个监听器可以在项目启动和销毁的时候做一些事情,例如,在项目启动的时候加载配置文件。

编写监听类实现对应的监听器接口

java 复制代码
/*
    域对象本身监听器,关注的是域对象的创建和销毁!
        ServeltContext:
            创建:服务器启动创建
            销毁:服务器停止销毁

     事件源:ServletContext对象
     事件:创建和销毁
     监听器: MyServletContextListener
     注册监听:在web.xml文件中配置
     事件对象:可以获得事件源对象!

     只要ServletContext创建了或者销毁了,那么就会被监听器MyServletContextListener捕获到,从而执行对应的方法!
 */
public class MyServletContextListener implements ServletContextListener {

    // 当ServletContext被创建的时候会执行
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("已监听到ServletContext创建了");
        System.out.println("去加载spring框架的配置文件");
        // 通过事件对象获得事件源对象
        ServletContext context = servletContextEvent.getServletContext();
    }

    // 当ServletContext对象销毁的时候被执行!
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("已监听到ServeltContext对象销毁了");
    }

}

xml配置

注解配置

4.3 案例:统计在线人数

需求

有用户使用网站,在线人数就+1;用户退出网站,在线人数就-1

监听器

java 复制代码
/*
    域对象属性监听器
        关注的是对域对象属性值的变更(添加、替换、删除)
 */

@WebListener()
public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener, HttpSessionListener {

    // 向session中添加新的值就执行这个方法
    @Override
    public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("向session域中设置值了");
    }

    // 将session域中的数据删除了,就执行这个方法
    @Override
    public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("将session域中值删除了");
    }

    // 将session域中的数据替换就会执行这个方法
    @Override
    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("将session域中值替换了");
    }

    ////////////////////上面三个方法是为了演示域对象属性监听器【与本案例无关】//////////////////////

    // session对象创建就执行这个方法
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        //System.out.println("session创建了");

        // 会话创建,有新的用户在访问网站
        HttpSession session = httpSessionEvent.getSession();

        // 获得项目环境
        ServletContext servletContext = session.getServletContext();

        // 获得会话的id
        System.out.println("session创建了。。。"+ session.getId());


        // 获取当前在线人数
        Integer number = (Integer) servletContext.getAttribute("NUMBER");

        // 判断
        if(number==null){
            // 第一个用户
            servletContext.setAttribute("NUMBER",1);
        }else{
            // 不是第一个
            servletContext.setAttribute("NUMBER", ++number);
        }
    }

    // session对象销毁执行这个方法
    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        // 会话结束,用户就不在线了
        HttpSession session = httpSessionEvent.getSession();
        // 获得ServletContext
        ServletContext context = session.getServletContext();

        System.out.println("session销毁了。。。"+ session.getId());

        // 获得当前在线人数
        Integer number = (Integer) context.getAttribute("NUMBER");

        // 人数少1个
        context.setAttribute("NUMBER",--number);
    }
}

number.jsp

LogoutServlet

相关推荐
软件开发-NETKF88881 个月前
JSP到Tomcat特详细教程
java·开发语言·tomcat·jsp·项目运行
衍生星球1 个月前
JSP程序设计之JSP指令
java·开发语言·jsp
衍生星球2 个月前
JSP 程序设计之 Web 技术基础
java·开发语言·jsp
衍生星球2 个月前
JSP 程序设计之 JSP 基础知识
java·web·jsp
鹦鹉0072 个月前
SpringMVC的基本使用
java·spring·html·jsp
飞翔的佩奇2 个月前
Java项目:基于SSM框架实现的小区物业管理系统【ssm+B/S架构+源码+数据库+毕业论文+开题报告+任务书+远程部署】
java·数据库·mysql·毕业设计·jsp·ssm框架·小区物业管理系统
程序猿小D2 个月前
Java项目:基于SSM框架实现的进销存管理系统【ssm+B/S架构+源码+数据库+毕业论文+远程部署】
java·数据库·mysql·ssm·jsp·毕业论文·进销存管理系统
Bella_chene3 个月前
IDEA 中使用 <jsp:useBean>动作指令时,class属性引用无效
java·intellij-idea·jsp·java web开发