JavaWeb详解

一、HTTP协议简介

1、什么是http协议

概述:

HTTP是Hyper Text Transfer Protocol的缩写,即超文本传输协议。它是一种请求/响应式的协议,客户端在与服务器端建立连接后就可以向服务器端发送请求,这种请求被称作HTTP请求,HTTP请求方法有8种:GET,POST,PUT,OPTIONS,HEAD,DELETE,TRACE,CONNECT,其中GET,POST是最为常用的两种;服务器端接收到请求后会做出相应的响应,这种响应被称为HTTP响应。
在这里插入图片描述
默认端口号:80。

HTTP协议是一种纯文本的无状态协议!

2、http协议的工作原理

HTTP协议工作于客户端-服务端架构之上。浏览器作为 HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。

Web服务器有:Apache服务器,Tomcat服务器,IIS服务器( Internet lnformation Services)等。

Web服务器根据接收到的请求后,向客户端发送响应信息。

3、使用程序获取网页内容示例

public class HttpRequest {
    public static void main(String[] args) throws IOException {
        //与服务器建立连接,并指定连接的端口号
        Socket socket = new Socket("14.215.177.39",80);
        PrintWriter out = new PrintWriter(socket.getOutputStream());
        //发送请求内容
        out.println("GET / HTTP/1.1");  //请求行。采用GET方式请求
        out.println("Host:edu-learn4fun.com");
        out.println("Content-Type:text/html");
        out.println();  //空行
        out.flush();
        //接受服务器响应内容
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String str = "";
        while((str = reader.readLine())!=null){
            System.out.println(new String(str.getBytes("GBK"),"utf-8"));
        }
        reader.close();
        out.close();
        socket.close();
    }
}

4、HTTP协议常见状态

200 一切正常(所有状态正常)

301 资源(网页等)被永久转移到其它URL

404 资源找不到。(首先去检查一下所写的路径是否正确)

500 服务器内部错误(程序出现异常,首先去查看异常信息以定位错误位置)

Web服务器

Web服务器主要用来接收客户端发送的请求和响应客户端请求。

1、Tomcat(Apache)( 我们主要撸这只猫 ):当前应用最广的JavaWeb服务器;

2、JBoss(Redhat红帽):支持JavaEE,应用比较广EJB容器 –> SSH轻量级的框架代替

3、GlassFish(Orcale):Oracle开发JavaWeb服务器,应用不是很广;

4、Resin(Caucho):支持JavaEE,应用越来越广;

5、Weblogic(Orcale):要钱的!支持JavaEE,适合大型项目;

6、Websphere(IBM):要钱的!支持JavaEE,适合大型项目

二、servlet介绍

1、我的第一个servlet

涉及的技术知识点

1、Servlet

2、Request请求对象

3、Response响应对象

Servlet开发规则

实际编码通过继承HttpServlet来完成Servlet的开发

public class TestServlet extends HttpServlet{
}

Servlet类的相关方法:

doGet Servlet中用于处理 get请求的方法

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

doPost Servlet中用于处理post请求的方法

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

service
①在Servlet的顶层实现中,在service方法中调用的具体的doGet或者是doPost
②在实际开发Servlet的过程中,可以选择重写doGet以及doPost 或者 直接重写service方法来处理请求。

java程序:

public class HelloWorld extends HttpServlet {

    public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //向客户端响应一个HelloWorld
        PrintWriter out = resp.getWriter();
        out.println("HelloWorld");  //向客户端写内容
        System.out.println("service.......");
    }
}

.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的名称,可以随便取,但是要注意servlet的名称不能重复-->
        <servlet-name>helloWorld</servlet-name>
        <!-- servlet对于的类的全名称。包名+类名-->
        <servlet-class>com.servlet.test01.HelloWorld</servlet-class>
    </servlet>

    <servlet-mapping>
        <!-- servlet name节点内容需要和servlet节点中的name属性一致-->
        <servlet-name>helloWorld</servlet-name>
<!--        配置访问路径。这里"/"表示项目的根目录-->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

</web-app>

web.xml文件。用于描述整个web应用的信息的。

2、什么是servlet

Servlet是运行在服务器上的java类。它可以接收客户端的请求,并向客户端做出响应。

servlet的体系结构:

在这里插入图片描述

说明:
1、开发中我们从 HttpServlet继承。

2、Servlet的组成部分:

 	- Servlet的主体部分: (servlet接口-->GenericServlet-->HttpServlet-->OurServlet)
 	- Servlet需要初始化,那么就需要有初始化参数。这时就有了一个配置对象:
 	- ServletConfigServlet要运行,需要一个运行的环境。这是就需要一个上下文对象:
 	- ServletContextServlet要获取客户端的请求,就需要有一个请求对象:ServletRequest
 	- Servlet需要向客户端响应消息,就需要有一个响应对象: ServletRespons

3、servlet的生命周期

public class HelloWorld extends HttpServlet {

    public HelloWorld() {
        System.out.println("构造方法.......");
    }
    @Override
    public void destroy() {
        System.out.println("destroy.......");

        super.destroy();
    }

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

    public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //向客户端响应一个HelloWorld
        PrintWriter out = resp.getWriter();
        out.println("HelloWorld");  //向客户端写内容
        System.out.println("service.......");
    }
}

.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的名称,可以随便取,但是要注意servlet的名称不能重复-->
        <servlet-name>helloWorld</servlet-name>
        <!-- servlet对于的类的全名称。包名+类名-->
        <servlet-class>com.servlet.test01.HelloWorld</servlet-class>
    </servlet>

    <servlet-mapping>
        <!-- servlet name节点内容需要和servlet节点中的name属性一致-->
        <servlet-name>helloWorld</servlet-name>
<!--        配置访问路径。这里"/"表示项目的根目录-->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

</web-app>

第一次运行结果:
在这里插入图片描述

刷新页面:

在这里插入图片描述

分析:

现象:构造方法和init方法只执行了一次(第一次运行的时候执行的),后面一次访问没有在执行构造方法和init方法。

说明:每次访问其实都是访问的是同一个servlet实例。

执行顺序:构造方法->init方法->servlet->doGet

说明:通过servlet的生命周期的说明,可以看出servlet是一个单例类。
在这里插入图片描述

4、get、post

get和post是HTTP请求的两种基本方法(请求方法一共有8种),他们本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。

GET和POST有一个重大的区别

  • 简单说:GET产生一个TCP数据包;POST产生两个TCP数据包。

  • 复杂说:对于GET方式的请求,浏览器会把header和data一起发送出去,服务器响应200(状态码);对于POST请求,浏览器先发送header,服务器响应100(已经收到请求的第一部分,正在等待其余部分),浏览器再次发送data,服务器返回200。

基本区别
在这里插入图片描述

get、post的选择

post:

若符合下列任一情况,则用POST方法(如果要修改服务上的数据,那么选择POST):

  • 请求的结果有持续性的副作用,例如,数据库内添加新的数据行。
  • 需要提交的数据量比较大时。
  • 要传送的数据不是采用7位的ASCl编码,例如二进制数据等。

get:

若符合下列任一情况,则用GET方法(查询服务器上的数据选择GET):

  • 请求是为了查找资源,HTML表单数据仅用来帮助搜索。

  • 请求结果无持续性的副作用。

  • 收集的数据及HTML表单内的输入字段名称的总长不超过2048个字符。

5、servlet中文乱码问题

在页面提交的时候,和 servlet进行获取的时候的编码格式不统一造成的。tomcat 默认的编码格式:ISO-8859-1,而这种编码方式是不支持中文的。所以会出现中文乱码。

解决方案:在接收和响应的时候设置固定的编码格式为utf-8。

解决post请求乱码问题

		//设置请求对象编码格式
        request.setCharacterEncoding("utf-8");
        //设置响应对象编码格式
        response.setCharacterEncoding("utf-8");
        //设置响应内容的类型,
		//为保证servlet向客户端响应的消息不会有乱码
        response.setContentType("text/html");

在这里插入图片描述

附注册表单源代码:

regist.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
</head>
<body>
<h1>用户注册</h1>
<form action="/WebStudy01/reg" method="post">
    <table>
        <tr>
            <th>用户名:</th>
            <td><input type="text" name="username"></td>
        </tr>
        <tr>
            <th>密码:</th>
            <td><input type="password" name="userpwd"></td>
        </tr>
        <tr>
            <th>性别:</th>
            <td>
                <select name="gender">
                    <option value=""></option>
                    <option value=""></option>
                </select>
            </td>
        </tr>

        <tr>
            <th>提交:</th>
            <td>
                <input type="submit">
            </td>
        </tr>
    </table>
</form>
</body>
</html>

java:

public class Regist extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置请求编码格式
        request.setCharacterEncoding("utf-8");
        //设置响应编码格式
        response.setCharacterEncoding("utf-8");
        //设置响应内容的类型,
        response.setContentType("text/html");

        /*
        获取表单数据
        调用request请求对象的getParameter方法,参数和表单控件中name属性保持一致
         */public class Regist extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置请求编码格式
        request.setCharacterEncoding("utf-8");
        //设置响应编码格式
        response.setCharacterEncoding("utf-8");
        //设置响应内容的类型,
        response.setContentType("text/html");

        //响应数据到客户端
        PrintWriter out = response.getWriter();

        /*
        获取表单数据
        调用request请求对象的getParameter方法,参数和表单控件中name属性保持一致
         */
        String username = request.getParameter("username");
        String userpwd = request.getParameter("userpwd");
        String gender = request.getParameter("gender");
        String[] singers = request.getParameterValues("singer");
		
        //使用枚举
        Enumeration<String> names = request.getParameterNames();
        while (names.hasMoreElements()){
            out.println(names.nextElement()+"<br>");
        }
		
        //使用map键值对
        Map<String, String[]> parameterMap = request.getParameterMap();
        Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
        Iterator<Map.Entry<String, String[]>> iterator = entries.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, String[]> next = iterator.next();
            out.println(next.getKey()+"=="+ Arrays.toString(next.getValue())+"<br>");
        }

        out.println("用户名:"+username+"<br>");
        out.println("密码:"+userpwd+"<br>");
        out.println("性别:"+gender+"<br>");

        for (String str: singers) {
            out.println(str+"\t");
        }
    }
}
        String username = request.getParameter("username");
        String userpwd = request.getParameter("userpwd");
        String gender = request.getParameter("gender");

        //响应数据到客户端
        PrintWriter out = response.getWriter();
        out.println("用户名:"+username+"<br>");
        out.println("密码:"+userpwd+"<br>");
        out.println("性别:"+gender+"<br>");
    }
}

先在URL地址栏后边加注册网页–>regist.html,添加注册信息后会跳转响应界面。

配置Servlet:

<!--    配置用户注册,表单提交Servlet-->
    <servlet>
        <servlet-name>reg</servlet-name>
        <servlet-class>com.servlet.study01.Regist</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>reg</servlet-name>
        <url-pattern>/reg</url-pattern>
    </servlet-mapping>

解决get请求乱码问题

String username = request.getParameter("username");
username = new String(username.getBytes("ISO-8859-1"),"utf-8");

6、请求转发和重定向:

需求:登录页面将登录信息提交到servlet中,如果登录成功则需要跳转到欢迎页面。

6.1 采用重定向方式:

1、登录界面代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
    <div>
        <form action="/WebStudy01/login" method="post">
            <div>
                用户名:<input type="text" name="username">
            </div>
            <div>
                密码:<input type="password" name="password">
            </div>
            <div>
                <input type="submit" value="登录">
            </div>
        </form>
    </div>
</body>
</html>

2、java代码:

public class Login extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置请求编码格式
        request.setCharacterEncoding("utf-8");
        //设置响应编码格式
        response.setCharacterEncoding("utf-8");
        //设置响应内容的类型,
        response.setContentType("text/html");

        //获取用户和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        //登录成功转到欢迎界面
        //重定向
        response.sendRedirect("/WebStudy01/Welcome.html");
    }
}

配置servlet:

<!--    配置用户登录Servlet-->
<servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>com.servlet.study01.Login</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>login</servlet-name>
    <url-pattern>/login</url-pattern>
</servlet-mapping>

重定向过程示意图:
在这里插入图片描述

说明:

  • 使用语句:response.sendRedirect("/WebStudy01/Welcome.html");
  • 重定向使用的是response响应对象,说明重定向是有服务器向客户端发送一个响应信息。
  • 重定向的本质是:由服务器告诉客户端,你在去请求另一个资源。
  • 重定向,客户端向服务器发送了两次请求。两次请求斌没有什么联系,也是说可以请求任意互联网资源(全路径)
  • 绝对路径中的"/"是服务器中的根路径

6.2 采用请求转发方式:

修改代码:

//请求转发
request.getRequestDispatcher("/Welcome.html").forward(request, response);

只需要将重定位代码删除,写这句即可。

图示:
在这里插入图片描述

说明:

  • 请求转发全过程只发起了一次请求;中间转发了多少次,对客户端来说最后反馈的消息都是从所请求的对象来的。
  • 请求转发,可以将请求的内容以及处理的结果一起转发给下一个节点。
  • 路径问题:请求转发 getRequestDispatcher( “/welcome.jsp”)中的“/”表示项目的根路径。

6.3 采用请求转发和重定向的区别:

在这里插入图片描述

7、会话技术

会话技术:

会话技术帮助服务器存储客户端状态,来区分客户端

一次会话:从打开浏览器访问站点的某些地址链接,到关闭浏览器,称为一次会话

7.1 Cookie:客户端会话技术

代码:
public class TestCookie extends HttpServlet {

    //读cookie
    /*
    *cookie从客户端来的,数据是从客户端到服务端-->使用request对象来获取cookie
    */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");

        PrintWriter out = response.getWriter();

        //读cookie
        Cookie[] cookies = request.getCookies();
        for(Cookie c:cookies){
            //获取cookie的name
            if(c.getName().equals("uname")){
                //URLDecoder.decode() url 解码
                out.println(URLDecoder.decode(c.getValue(),"utf-8"));
            }
        }
   }
    //写cookie
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");

        String username = request.getParameter("username");
        //URLEncoder.encode() url编码
        Cookie cookie = new Cookie("uname", URLEncoder.encode(username,"utf-8"));
        //设置cookie过期时间,单位是秒
        cookie.setMaxAge(24*60*60);	//一天
        response.addCookie(cookie);
        PrintWriter out = response.getWriter();
		//a标签默认提交方式是get提交
        out.println("<a href='/WebStudy01/cookie'>查看cookie</a>");
        }
}

.xml 文件配置:

  <!-- 测试cookie-->
    <servlet>
        <servlet-name>cookie</servlet-name>
        <servlet-class>com.servlet.study01.TestCookie</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>cookie</servlet-name>
        <url-pattern>/cookie</url-pattern>
    </servlet-mapping>
注意事项:
  • 关于cookie,无论是名字还是值,都不能包含特殊字符和空格。

  • 一般在存储值的时候,都需要进行URL编码。

  • 删除cookie:只需要设置过期时间为负数。

  • cookie的使用示意图:
    在这里插入图片描述

7.2 Session:服务端会话技术

1、为什么要使用sessin:

首先是在如果要去多个页面中共享数据,那么在不使用session的情况下,就只能通过请求转发的方式将数据带到下一个界面。然而重定向的方式就不行了。其次,记录用户信息,如果没有session就只能记得cookie中,但是cookie又是记录在浏览器客户端的,并且以文本形式存放的。不仅存放内容有局限性,而且安全性也有很大问题。

2、什么是session

session(会话)是在一段时间,一个客户端与服务器的一 连串相关的交互过程。(说明:“一段时间内”—>session具有时效性)

3、代码:
public class TestSession extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/html");

            //获取用户名和密码
            String username = request.getParameter("username");
            String password = request.getParameter("password");

            //记录用户信息到session
        /**
         *getSession方法说明:
         * 有两个参数重载。getSession(boolean参数)和getSession();
         * 有参:
         *      true:去request中获得Session,如果Session不存在则创建一个新的Session并返回
         *            如果Session存在,则直接返回已存在的Session
         *      false:获取Session,如果Session不存在,那么返回null
         * 无参:<==>getSession(true)
         */
        HttpSession session = request.getSession();
        //将数据保存到session中(保存基本信息)
        session.setAttribute("username", username);
        session.setAttribute("password", password);

        //注意:getAttribute(String string)
        System.out.println((String)session.getAttribute("username"));
        System.out.println((String)session.getAttribute("password"));

        //保存用户登录状态,一般会保存一个用户对象
//        User u = new User(username,password);
//        session.setAttribute("user", u);

        //进入到welcome界面
        request.getRequestDispatcher("/Welcome.html").forward(request, response);
    }
}

.xml文件配置:

 <!-- 测试session-->
    <servlet>
        <servlet-name>session</servlet-name>
        <servlet-class>com.servlet.study01.TestSession</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>session</servlet-name>
        <url-pattern>/session</url-pattern>
    </servlet-mapping>

4、设置session过期时间:

什么是session过期时间:

​ 从最后一次访问session开始计时,如果在过期时间之内没有对session进行再次访问,那么系统会将session对象回收。

设置方式1:在程序中设置
//设置session的过期时间(单位:秒),一般不常用
session.setMaxInactiveInterval(60*60);
设置方式2:在项目的web.xml中进行设置(一般设置在最上边)
  //设置session过期时间(单位:分钟)
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
设置方式3:在Tomat的web.xml中进行设置(设置方式与2相同)

在这里插入图片描述

说明:
1、在tomcat中进行设置,一般我们称为session 的默认过期时间(一般都是30分钟)。他会对所有发布到这个服务器上的项目起作用。

2、在项目的web.xml中设置,只会对本项目起作用。(优先级高于在tomcat中设置)

3、在程序中设置,一般是在临时需要增加session过期时间的时候进行设置。(例如:在教务系统中录入成绩的时候。当然现在一般不会采用这种方式,有更好的方式解决)

4、session的原理:
在这里插入图片描述
在这里插入图片描述

7.3 application / serveletContext

1、为什么是serveletContext:

WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。

servletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext()方法获得servletContext对象。也可以直接在servlet中调用getServeltContext()方法来直接获取ServletContext对象。

由于一个WEB应用中的所有servlet共享同一个ServletContext对象,因此 servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为 context或者application域对象。

2、application的特点:

1、存放在服务器端

2、所有用户公用

3、以key-value形式存放

4、可以存放任何对象

3、代码:
public class TestApplication extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");

        //获取servletContext对象
        ServletContext application = getServletContext();
        //写application对象(和servlet的方式一样)
        String username = request.getParameter("username");
        application.setAttribute("username",username);
        //读 返回结果是object类型,需要强制转型
        System.out.println((String)(application.getAttribute("username")));
    }
}

.xml文件配置:

   <!-- 测试application-->
    <servlet>
        <servlet-name>application</servlet-name>
        <servlet-class>com.servlet.study01.TestApplication</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>application</servlet-name>
        <url-pattern>/app</url-pattern>
    </servlet-mapping>

7.4cookie、session在这里插入图片描述

、application的区别

8、过滤器

基本思想和结构

1、Filtering 的基本思想:
将jsp,servlet,html看作资源,容器用来处理这些资源,并为资源提供服务。因此,可以在处理这些资源之前或之后,通过过滤器增加一些通用功能;比如:登录权限验证、字符编码转换、资源访问权限控制、敏感词汇过滤。而且这些过滤器可以形成一个链

在这里插入图片描述

2、过滤器结构:
在这里插入图片描述

编写过滤器

public class EncodeFiter implements Filter {
    private String encode = "";
    private String content = "";
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
         encode = filterConfig.getInitParameter("encode");
         content = filterConfig.getInitParameter("content");

    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding(encode);
        response.setCharacterEncoding(encode);
        response.setContentType(content);
        //过滤放行
        chain.doFilter(request, response);
    }
}

注意事项:

  • 过滤器本身是一个类,必须实现Filter接口
  • 在doFilter方法的最后一句,必须要有chain.doFilter(request, response);
  • 初始化参数不能写死,而要放在配置文件中。
  • 过滤器在服务器启动时就会被加载。

2、编写配置文件:

<!--    配置过滤器-->
    <filter>
        <filter-name>filter</filter-name>
        <filter-class>com.servlet.study.TestFilter</filter-class>
        <!--    配置初始化属性-->
        <init-param>
            <param-name>encode</param-name>
            <param-value>utf-8</param-value>
        </init-param>

        <init-param>
            <param-name>context</param-name>
            <param-value>text/html</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

监听器

监听器原理:

1、监听器的概念:

web监听器是一种Servlet中的特殊的类,它们能帮助开发者监听web中的特定事件,比如ServletContext,HttpSession,ServletRequest的创建和销毁;变量的创建、销毁和修改等。可以在某些动作前后增加处理,实现监控。(观察者模式的一种应用)

2、监听器常用的用途

1.通常使用web 监听器做以下的内容:2.统计在线人数,利用HttpSessionLisener

3.加载初始化信息:利用ServletContextListener

4.统计网站访问量

5.实现访问监控(监听request对象)—stuts2通过监听器来实现访问控制的3、监听器的接口

3、实现在线人数统计功能

1、实现原理:
监听session对象,当session创建的时候认为在线人数+1;当session销毁的时候认为在线人数-1
2、创建监听器:

public class OnlineListener implements HttpSessionListener {
    /**
     * session 创建时触发
     */
    @Override
    public void sessionCreated(HttpSessionEvent sessionEvent) {
          //在线人数
        ServletContext application = sessionEvent.getSession().getServletContext();

        if(application.getAttribute("count")==null){
             application.setAttribute("count",0);
        }else {
            Integer c1 =  (Integer)application.getAttribute("count");
            application.setAttribute("count",c1+1);
        }

    }
    /**
     * session 销毁时触发
     */
    @Override
    public void sessionDestroyed(HttpSessionEvent sessionEvent) {
        ServletContext application = sessionEvent.getSession().getServletContext();
        Integer c1 = (Integer)(application.getAttribute("count")) ;
        application.setAttribute("count", c1-1);
    }
}
public class TestSession extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

         //获取用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");

         //记录用户信息到session
        HttpSession session = request.getSession();
        //将数据保存到session中(保存基本信息)
        session.setAttribute("username", username);
        session.setAttribute("password", password);
        //监听在线人数
        PrintWriter out = response.getWriter();
        out.println("在线:"+username);
        out.println("<br>在线人数:"+getServletContext().getAttribute("count"));

        System.out.println((String)session.getAttribute("username"));
        System.out.println((String)session.getAttribute("password"));

    }
}

.xml文件配置:

<!--配置监听器-->
<listener>
    <listener-class>com.servlet.study01.OnlineListener</listener-class>
</listener>

9、XML

xml简介:

  1. XML–可扩展标记语言eXtensible Markup Language
  2. 由W3C组织发布,目前推荐遵守的是W3C组织于2000年发布的XML1.0规范
  3. XML的使命,就是以一个统一的格式,组织有关系的数据,为不同平台下的应用程序服务
  4. XML用来传输和存储数据,HTML用来显示数据
  5. XML没有预定义标签,均为自定义标签

xml用途:

  1. 配置文件
    JavaWeb中的web.xml
    C3P0中的c3p0-config.xml
  2. 数据交换格式
    Ajax
    WebService
  3. 数据存储
    保存关系型数据

xml基本语法

  1. XML文档组成
    ①XML声明
    version属性指定XML版本,固定值是1.0
    encoding指定的字符集,是告诉解析器使用什么字符集进行解码,而编码是由文本 编辑器决定的
    ②CDATA区
    当XML文档中需要写一些程序代码、SQL语句或其他不希望XML解析器进行解析 的内容时,就可以写在CDATA区中
    XML解析器会将CDATA区中的内容原封不动的输出
    CDATA区的定义格式:<![CDATA[…]]>
  2. 语法规则
    ①XML声明要么不写,要写就写在第一行,并且前面没有任何其他字符
    ②只能有一个根标签
    ③标签必须正确结束
    ④标签不能交叉嵌
    ⑤严格区分大小写
    ⑥属性必须有值,且必须加引号
    ⑦标签不能以数字开头
    ⑧注释不能嵌套

xml解析

  1. XML解析是指通过解析器读取XML文档,解释语法,并将文档转化成对象
  2. 常用的解析方式
    DOM(Document Object Model)
    SAX(Simple API for XML)
  3. DOM 和SAX解析的对比

在这里插入图片描述

  1. Dom4j解析示例

    解析:

    //1.创建解析器对象
    SAXReader saxReader = new SAXReader();
    //2.解析xml文件获取document对象
    Document document = saxReader.read("students.xml");
    //3.得到根元素
    Element root = document.getRootElement();
    

10、Ajax

  1. AJAX 是 Asynchronous JavaScript And XML 的简称。直译为,异步的JS和XML。
  2. AJAX的实际意义是,不发生页面跳转、异步载入内容并改写页面内容的技术。
  3. AJAX也可以简单的理解为通过JS向服务器发送请求。

异步处理

  1. 同步处理
    AJAX出现之前,我们访问互联网时一般都是同步请求,也就是当我们通过一个页面向服务器发送一个请求时,在服务器响应结束之前,我们的整个页面是不能操作的,也就是直观上来看他是卡主不动的。
    这就带来了非常糟糕的用户体验。首先,同步请求时,用户只能等待服务器的响应,而 不能做任何操作。其次,如果请求时间过长可能会给用户一个卡死的感觉。最后,同步请求的最大缺点就是即使整个页面中只有一小部分内容发生改变我们也要刷新整个页面。
  2. 异步处理
    而异步处理指的是我们在浏览网页的同时,通过AJAX向服务器发送请求,发送请求的过程中我们浏览网页的行为并不会收到任何影响,甚至主观上感知不到在向服务器发送请求。当服务器正常响应请求后,响应信息会直接发送到AJAX中,AJAX可以根据服务器响应的内容做一些操作。
    使用AJAX的异步请求基本上完美的解决了同步请求带来的问题。首先,发送请求时不会影响到用户的正常访问。其次,即使请求时间过长,用户不会有任何感知。最后,AJAX可以根据服务器的响应信息局部的修改页面,而不需要整个页面刷新。

异步请求对象

XMLHttpRequest对象是AJAX中非常重要的对象,所有的AJAX操作都是基于该对象的。
XMLHttpRequest对象用来封装请求报文,我们向服务器发送的请求信息全部都需要封装到该对象中。
这里需要稍微注意一下,XMLHttpRequest对象并没有成为标准,但是现在的主流浏览器都支持该对象,而一些如IE6的老版本浏览器中的创建方式有一些区别,但是问题不大。

使用JQuery框架来发送异步请求
  1. JQuery是当前比较主流的 JavaScript 库,封装了很多预定义的对象和实现函数,帮助使用者建立有高难度交互的页面,并且兼容大部分主流
    的浏览器.
    JQuery对同样提供了对Ajax的支持,可以更加方便快速的进行Ajax的开发,相关的方法有$.get $.post $.ajax等.
    JQuery的对象的本质就是dom对象的数组/集合

  2. JQuery对象与dom对象的相互转换
    JS转JQuery: var jObj = $(dObj);
    JQuery转JS: var dObj = jObj[0] 或者 var dObj = jObj.get(0)

  3. . g e t 方 法 和 .get方法和 .get.post方法

  4. $.ajax方法
    jQuery 底层 AJAX 实现。简单易用的高层实现见 . g e t , . p o s t 等 。 . p o s t 等 。 . ∗ p ∗ ∗ o ∗ ∗ s ∗ ∗ t ∗ 等 。 . a j a x ( ) 返 回 其 创 建 的 X M L H t t p R e q u e s t 对 象 。 大 多 数 情 况 下 你 无 需 直 接 操 作 该 函 数 , 除 非 你 需 要 操 作 不 常 用 的 选 项 , 以 获 得 更 多 的 灵 活 性 。 最 简 单 的 情 况 下 , .get, . p o s t 等 。 .post 等。.*p**o**s**t*等。.ajax() 返回其创建的 XMLHttpRequest 对象。大多数情况下你无需直接操作该函数,除非你需要操作不常用的选项,以获得更多的灵活性。最简单的情况下, .get,.post.post.post.ajax()XMLHttpRequest.ajax()可以不带任何参数直接使用。
    $.ajax方法的参数

  5. 具体的示例代码

    $.ajax({
    
        url:"http://www.microsoft.com", //请求的url地址
    
        dataType:"json", //返回格式为json
    
        async:true,//请求是否异步,默认为异步,这也是ajax重要特性
    
        data:{"id":"value"}, //参数值
    
        type:"GET", //请求方式
    
        beforeSend:function(){
            //请求前的处理
        },
    
        success:function(req){
            //请求成功时处理
        },
    
        complete:function(){
            //请求完成的处理
        },
        error:function(){
    
            //请求出错处理
        }
    
    });
    

11、JSP

定义:

JSP(Java Server Pages)是JavaWeb服务器端的动态资源,它与html页面的作用是相同的,显示数据和获取数据。

jsp: 作为请求发起页面,例如显示表单、超链接。
作为请求结束页面,例如显示数据。

Servlet:
作为请求中处理数据的环节。

jsp的组成
  • jsp = html + java脚本 + jsp标签(指令)

  • jsp中可直接使用的对象一共有9个,被称之为9大内置对象

  • 3种java脚本:
    <%…%>:写java代码片段,(类似方法)
    <%=…%>:用于输出,用于输出一条表达式(或变量)的结果。
    <%!…%>:声明,用来创建类的成员变量和成员方法(类似与类)

  • jsp注释:<%– … –%>

当服务器把jsp编译成java文件时已经忽略了注释部分!
jsp代码:

<%@ page language="java" import="java.util.*" import="java.text.*"
	contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<title>JSP Hello World</title>
		<style type="text/css">
			p{
				font-size: 35px;
				font-family: 宋体;
				color: blue;
			}
		</style>
	</head>
	<body>
		<h2 align="left" style="color: red;">无所成之事不可逆也</h2>
		<h2 align="left" style="color: red;">断剑重铸之日,骑士归来之时</h2>

		<p>您好 JSP</p>
		
		<%--以下为Java代码--%>
		<%
		   Date date=new Date();
	       SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	       String time=simpleDateFormat.format(date);
           out.println(time);
        %>
	</body>
</html>

12、JSTL

Java Server Pages Standard Tag Libray(JSTL):JSP 标准标签库,是一个定制标签类库的集合,用 于解决一些常见的问题,例如迭代一个映射或者集合、条件测试、XML 处理,甚至数据库和访问数据库 操作等。

首先我们需要去官网下载最新版本的DTD文件http://archive.apache.org/dist/jakarta/taglibs/standard/binaries/ 并且将文件中的jstl.jar拷贝到项目的lib中。

jstl核心标签

使用taglib指令导入标签库:

除了JSP动作标签外,使用其他第三方的标签库都需要:

  • 导包;
  • 在使用标签的JSP页面中使用taglib指令导入标签库;

下面是导入JSTL的core标签库:

<%@ taglib prefix="c"uri="http://java.sun.com/jstl/core" %>
  • prefix=“c”:指定标签库的前缀,这个前缀可以随便给值,但大家都会在使用core标签库时指定前缀为c;
  • uri=“http://java.sun.com/jstl/core”:指定标签库的uri,它不一定是真实存在的网址,但它可以让JSP找到标签库的描述文件;
4、core标签库常用标签:

(1)out和set标签

<c:out value=”aaa”/>输出aaa字符串常量
<c:out value=”${aaa}”/>与${aaa}相同
<c:out value=”${aaa}” default=”xxx”/>当${aaa}不存在时,输出xxx字符串
<%request.setAttribute(“a”,“”);%><c:out value="${a }" default=“xxx” escapeXml=“false” />当escapeXml为false,不会转换“<”、“>”。这可能会受到JavaScript攻击。
<c:set var=”a” value=”hello”/>在pageContext中添加name为a,value为hello的数据。
<c:set var=”a” value=”hello” scope=”session”/>在session中添加name为a,value为hello的数据。

(2)remove标签

<c:remove var=“a” scope=”page”/>删除pageContext中name为a的数据

(3)url标签:该标签会在需要重写URL时添加。

<c:url value="/"/>输出上下文路径:/项目名/
<c:url value="/" var=“a” scope=“request”/>把本该输出的结果赋给变量a。范围为request
<c:url value="/AServlet"/>输出:/项目名/AServlet
<c:url value="/AServlet"><c:param name=“username” value=“abc”/><c:param name=“password” value=“123”/>输出:/项目名/AServlet?username=abc&password=123 如果参数中包含中文,那么会自动使用URL编码!

(4)if标签:

if标签的test属性必须是一个boolean类型的值,如果test的值为true,那么执行if标签的内容,否则不执行。

<c:set var="a" value="hello"/>
<c:if test="${not empty a }">
	<c:out value="${a }"/>
</c:if>

(5)choose标签:

choose标签对应Java中的if/else if/else结构。when标签的test为true时,会执行这个when的内容。当所有when标签的test都为false时,才会执行otherwise标签的内容。

<c:set var="score" value="${param.score }"/>
<c:choose>
	<c:when test="${score > 100 || score < 0}">错误的分数:${score }</c:when>
	<c:when test="${score >= 90 }">A级</c:when>
	<c:when test="${score >= 80 }">B级</c:when>
	<c:when test="${score >= 70 }">C级</c:when>
	<c:when test="${score >= 60 }">D级</c:when>
	<c:otherwise>E级</c:otherwise>
</c:choose>

(6)forEach标签:

forEach当前就是循环标签了,forEach标签有多种两种使用方式:

  • 使用循环变量,指定开始和结束值,类似for(int i = 1; i <= 10; i++) {};
  • 循环遍历集合,类似for(Object o : 集合);

循环变量:

<c:set var="sum" value="0" /> 
<c:forEach var="i" begin="1" end="10"> 
	<c:set var="sum" value="${sum + i}" /> 
</c:forEach>
<c:out value="sum = ${sum }"/>
<c:set var="sum" value="0" />
<c:forEach var="i" begin="1" end="10" step ="2">
	<c:set var="sum" value="${sum + i}" />
</c:forEach>
<c:out value="sum = ${sum }"/>

遍历集合或数组方式:

<%
String[] names = {"zhangSan", "liSi", "wangWu", "zhaoLiu"};
pageContext.setAttribute("ns", names);
%>
<c:forEach var="item" items="${ns }">
	<c:out value="name: ${item }"/><br/>
</c:forEach>

遍历List:

<%
	List<String> names = new ArrayList<String>();
	names.add("zhangSan");
	names.add("liSi");
	names.add("wangWu");
	names.add("zhaoLiu");
	pageContext.setAttribute("ns", names);
%>
<c:forEach var="item" items="${ns }">
	<c:out value="name: ${item }"/><br/>
</c:forEach>

遍历Map:

<%
	Map<String,String> stu = new LinkedHashMap<String,String>();
	stu.put("number", "N_1001");
	stu.put("name", "zhangSan");
	stu.put("age", "23");
	stu.put("sex", "male");
	pageContext.setAttribute("stu", stu);
%>
<c:forEach var="item" items="${stu }">
	<c:out value="${item.key }: ${item.value }"/><br/>
</c:forEach>

forEach标签还有一个属性:varStatus,这个属性用来指定接收“循环状态”的变量名,例如:<forEach varStatus=”vs” …/>,这时就可以使用vs这个变量来获取循环的状态了。

  • count:int类型,当前以遍历元素的个数;
  • index:int类型,当前元素的下标;
  • first:boolean类型,是否为第一个元素;
  • last:boolean类型,是否为最后一个元素;
  • current:Object类型,表示当前项目。
<c:forEach var="item" items="${ns }" varStatus="vs">
	<c:if test="${vs.first }">第一行:</c:if>
	<c:if test="${vs.last }">最后一行:</c:if>
	<c:out value="第${vs.count }行: "/>
	<c:out value="[${vs.index }]: "/>
	<c:out value="name: ${vs.current }"/><br/>
</c:forEach>

5、fmt标签库常用标签:

fmt标签库是用来格式化输出的,通常需要格式化的有时间和数字。

格式化时间:

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
......
<%
	Date date = new Date();
	pageContext.setAttribute("d", date);
%>

<fmt:formatDate value="${d }" pattern="yyyy-MM-dd HH:mm:ss"/>

格式化数字:

<%
	double d1 = 3.5;
	double d2 = 4.4; 
	pageContext.setAttribute("d1", d1);
	pageContext.setAttribute("d2", d2);
%>
<fmt:formatNumber value="${d1 }" pattern="0.00"/><br/>

<fmt:formatNumber value="${d2 }" pattern="#.##"/>

13、EL表达式

目的:

​ 简化jsp页面,减少HTML代码与java代码的耦合。(减少在jsp页面中的Java代码)

基本语法

${EL表达式}

运算符

" . “和” [] "。这两个运算符都是取属性

${user.username}

${user[“username”]}

3.执行运算

1、语法:${运算表达式}

2、常见运算符:==(eq) !=(ne) <(lt) >(gt) <=(le) >=(ge) &&(and) ||(or) !(not)

3、判断是否为空:${empty name }

​ 作用1:判断对象是否存在,返回true和false

​ 作用2:判断集合数组中是否存在元素,返回true和false

​ 作用3:判断字符串是否是空串(null),返回true和false

4、三目运算符:${name == null ? “null” : name }

EL表达式的作用域

Page --> request --> session -->application

例如: ${username}这个表达式,会首先从page 的属性中去找username,如果找到那么输出;如果没有找到,那么继续到request对象中去找,一直到找到为止。如果到application中都没有找到,那么输出空。

例:

session.setAttribute(“uname”,“张三”);

request.setAttribute(“uname”,“李四”);

${uname}

上面这个程序输出结果:“李四”,而不会输出“张三”。

其他对象

对象名用法等价JSP代码或作用
param${param.name}request.getParameter(name)
paramValues${paramValues.name}request.getParameterValues(name)//返回一个字符串数组
header${header.name}request.getHeader(name)
headerValues${headerValues.name}request.getHeaderValues(name)
cookie${cookie.name.value}request.getCookie()
initParam${initParam.name}ServletContext.getInitparameter(name)
pageContext${pageContext.request.contextPath}获取WEB应用(项目的根路径)
pageContext${pageContext.request.sessionid}获取sessionId
pageContext${pageContext.request.remoteAddr}获取主机名

EL表达式的原理和注意点

原理:EL表达式在获取某个对象的属性值时,先将某个属性值首字母变成大写,然后加上get前缀,拼接成getter方法,通过反射将该对象构建出来,然后再对该对象执行getter方法,这与私有属性并没有关系,

所以要注意,JavaBean的属性名要小写,且要有getter方法,不然会报错。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值