java-web

基于socket和计算机网络的知识,学习时要穿插着一起思考!

1. web服务器及tomcat

1.1 web服务器的概念

两种开发模型

  • C/S又称Client/Server或客户/服务器模式。服务器通常采用高性能的PC、工作站或小型机,客户端需要安装专用的客户端软件。如QQ,微信等软件

  • B/S是Brower/Server的缩写,客户机上只要安装一个浏览器(Browser)。Browser/Server是建立在广域网的基础上的。

  • CS和BS结构各自的优、缺点

    • C/S的优点:

      是能充分发挥客户端PC的处理能力,很多工作可以在客户端处理后再提交给服务器。对应的优点就是客户端响应速度快。

    • C/S的缺点:

      客户端需要安装专用的客户端软件。首先涉及到安装的工作量,其次任何一台电脑出问题,如病毒、硬件损坏,都需要进行安装或维护。特别是有很多分部或专卖店的情况,不是工作量的问题,而是路程的问题。还有,系统软件升级时,每一台客户机需要重新安装,其维护和升级成本非常高。

    • B/S最大的优点:

      可以在任何地方进行操作而不用安装任何专门的软件。只要有一台能上网的电脑就能使用,客户端零维护。系统的扩展非常容易,只要能上网,就可以使用了。甚至可以在线申请,通过公司内部的安全认证(如CA证书)后,不需要人的参与,系统可以自动分配给用户一个账号进入系统。

web服务器分类

Web服务器是运行及发布Web应用的容器,只有将开发的Web项目放置到该容器中,才能使网络中的所有用户通过浏览器进行访问。开发Java Web应用所采用的服务器主要是与JSP/Servlet兼容的Web服务器,比较常用的有Tomcat、Resin、JBoss、WebSphere 和 WebLogic 等

  • Tomcat 服务器

    目前最为流行的Tomcat服务器是Apache-Jarkarta开源项目中的一个子项目,是一个小型、轻量级的支持JSP和Servlet 技术的Web服务器,也是初学者学习开发JSP应用的首选

  • Resin 服务器
    Resin是Caucho公司的产品,是一个非常流行的支持Servlet和JSP的服务器,速度非常快。Resin本身包含了一个支持HTML的Web服务器,这使它不仅可以显示动态内容,而且显示静态内容的能力也毫不逊色,因此许多网站都是使用Resin服务器构建

  • JBoss服务器

    JBoss是一个种遵从JavaEE规范的、开放源代码的、纯Java的EJB服务器,对于J2EE有很好的支持。JBoss采用JML API实现软件模块的集成与管理,其核心服务又是提供EJB服务器,不包含Servlet和JSP的Web容器,不过它可以和Tomcat完美结合

  • WebSphere 服务器

    WebSphere是IBM公司的产品,可进一步细分为 WebSphere Performance Pack、Cache Manager 和WebSphere Application Server等系列,其中WebSphere Application Server 是基于Java 的应用环境,可以运行于 Sun Solaris、Windows NT 等多种操作系统平台,用于建立、部署和管理Internet和Intranet Web应用程序。

  • WebLogic 服务器
    WebLogic 是BEA公司的产品(现在已经被Oracle收购),可进一步细分为 WebLogic Server、WebLogicEnterprise 和 WebLogic Portal 等系列,其中 WebLogic Server 的功能特别强大。WebLogic 支持企业级的、多层次的和完全分布式的Web应用,并且服务器的配置简单、界面友好。对于那些正在寻求能够提供Java平台所拥有的一切应用服务器的用户来说,WebLogic是一个十分理想的选择

1.2 tomcat

1.2.1 Tomcat下载与安装

下载地址:https://tomcat.apache.org/

安装步骤:

  1. 下载Tomcat
  2. 解压到一个没有特殊符号的目录中(一般纯英文即可)
  3. 进入到解压的目录下找到bin\startup.bat双击启动即可

注意:

  1. 不建议将服务器软件放在磁盘层次很多的文件夹中!2
  2. 不建议放在中文路径下!
  3. tomcat安装需要配置JAVA_HOME环境变量

注意:8080端口占用问题!!!

因为端口占用导致tomcat服务器无法登录:

报错信息:

1
Cannot locate document: /

解决办法:

image-20210702172309539

此时通过localhost:8080就可以成功登录了!!

1.2.2 tomcat的目录

  • bin:该目录下存放的是二进制可执行文件,如果是安装版,那么这个目录下会有两个exe文件:tomcat9.exe、tomcat9w.exe,前者是在控制台下启动Tomcat,后者是弹出UGI窗口启动Tomcat;如果是解压版,那么会有startup.bat和shutdown.bat文件,startup.bat用来启动Tomcat,但需要JDK的配置(上文提到的JAVA_HOME路径),shutdown.bat用来停止Tomcat;
  • conf:这是一个非常非常重要的目录,这个目录下有四个最为重要的文件:
    • server.xml:配置整个服务器信息。例如修改端口号,添加虚拟主机等;
    • tomcat-users.xml:存储tomcat用户的文件,这里保存的是tomcat的用户名及密码,以及用户的角色信息。可以按着该文件中的注释信息添加tomcat用户,然后就可以在Tomcat主页中进入Tomcat Manager页面了;
    • web.xml:部署描述符文件,这个文件中注册了很多MIME类型,即文档类型。这些MIME类型是客户端与服务器之间说明文档类型的,如用户请求一个html网页,那么服务器还会告诉客户端浏览器响应的文档是text/html类型的,这就是一个MIME类型。客户端浏览器通过这个MIME类型就知道如何处理它了。当然是在浏览器中显示这个html文件了。但如果服务器响应的是一个exe文件,那么浏览器就不可能显示它,而是应该弹出下载窗口才对。MIME就是用来说明文档的内容是什么类型的!
    • context.xml:对所有应用的统一配置,通常我们不会去配置它。
  • lib:Tomcat的类库,里面是一大堆jar文件。如果需要添加Tomcat依赖的jar文件,可以把它放到这个目录中,当然也可以把应用依赖的jar文件放到这个目录中,这个目录中的jar所有项目都可以共享之,但这样你的应用放到其他Tomcat下时就不能再共享这个目录下的Jar包了,所以建议只把Tomcat需要的Jar包放到这个目录下
  • logs:这个目录中都是日志文件,记录了Tomcat启动和关闭的信息,如果启动Tomcat时有错误,那么异常也会
    记录在日志文件中。
  • temp:存放Tomcat的临时文件,这个目录下的东西可以在停止Tomcat后删除!
  • webapps:存放web项目的目录,其中每个文件夹都是一个项目;如果这个目录下已经存在了目录,那么都是tomcat自带的项目。其中ROOT是一个特殊的项目,在地址栏中没有给出项目目录时,对应的就是ROOT项目http://localhost:8080/examples,进入示例项目。其中examples就是项目名,即文件夹的名字。
  • work:运行时生成的文件,最终运行的文件都在这里。通过webapps中的项目生成的!可以把这个目录下的内容删除,再次运行时会生再次生成work目录。当客户端用户访问一个JSP文件时,Tomcat会通过JSP生成Java文件,然后再编译Java文件生成class文件,生成的java和class文件都会存放到这个目录下。
  • LICENSE:许可证。
  • NOTICE:说明文件。

如何通过url访问服务器:

url:

http://服务器的ip地址:端口号/项目名/被访问的页面

示例:

http://localhost:8080/demo_bootstrap/index.html

用手机访问同一局域网内的笔记本:

image-20210418160620306

需要注意的是:

  • 启动tomcat后,tomcat会加载部署在服务器端的所有项目
  • 浏览器访问的页面是服务器端的页面,基本上服务器的项目和工作空间的项目要保持一致

1.2.3 IntelliJ IDEA配置Tomcat

创建java-web项目

  • 新建module

    注意:正常创建普通java项目,而不是Java Enterprise;

  • 添加框架支持

    • 创建完Java项目后,右击项目,选择Add Frameworks Support;

      add framework

    • 选择 Java EE8

    • 选中Web Application,默认create web.xml

      web.xml

  • 目录结构变化,如下

    目录介绍

对该项目加些配置

  • 创建classes和lib文件夹,名字不可改

    image-20210418161924449

  • 配置jar包和classes包:

    • 在File中找到Project Structure

    • 点击Modules ,选择Paths,选中Use module compile output path ,把路径改成刚刚创建的classes文件夹

    • ok后再点旁边的Dependencies,点击”+”号,选择1 JARs or directories

    • 选择你刚刚创建的lib文件夹,OK

    • 选中jar Directory。

      image-20210418162016490

      image-20210418162135471

Scope属性

每个依赖项的Scope选项进行该jar包的相关操作设置,默认为compile,根据需要调整设置:

(1)compile设置编译范围内有效,在编译和打包时都会将依赖项加载进去。

(2)test设置测试范围内有效,只在测试时使用,编译和打包时都不会加载该项。

(3)provided设置编译和测试的范围内有效,打包时不会加载该项。

(4)runtime设置在运行时加载该依赖项,但是编译时不依赖。

将本地项目部署到服务器中

  • 回到主界面后,点击Run ,选择Edit Configurations,这里可以选择tomcat版本及对其进行一些配置

    image-20210418162259918

    image-20210418162356544

  • 选择第二个选项卡Deployment->+->选择Artifacts,Application context表示工程路径,可以对项目的访问地址进行修改,如果只有一个/,则默认表示localhost:8080/,后面直接跟需要访问的页面即可,Apply;

    在这里插入图片描述

此时就可以直接启动tomcat服务器了,idea会自动打开本地浏览器访问Application context中设置的路径!!!

1.2.4 修改端口号

修改配置文件:/conf/server.xml

如果将端口号改成80,则访问项目时的请求路径就可以省略端口号。(我的80端口被微软系统占用)

1.2.5 tomcat如何管理项目

给tomcat增加管理员信息:

配置conf/tomcat-users.xml

注意:tomcat启动的时候会加载webapps下的所有项目

1
2
3
4
5
6
<!--<Connector port="8888" protocol="HTTP/1.1" connectionTimeout="20000"
redirectPort="8443" />
<tomcat-users>-->
<role rolename="manager-gui"/>
<user username="tomcat" password="tomcat" roles="manager-gui"/>
</tomcat-users>

上述两行标签是在第一次登录失败时返回的,将其复制后粘贴进来

2. Servlet

image-20210418165310155

  • 概念:

    Servlet(Server Applet),全称Java Servlet。是⽤Java编写的服务器端程序,其主要功能在于交互式地浏览和修改数据,⽣成动态Web内容。狭义的Servlet是指Java语⾔实现的⼀个接⼝,⼴义的Servlet是指任何实现了这个Servlet接⼝的类,⼀般情况下,⼈们将Servlet理解为后者。

    Servlet运⾏于⽀持Java的应⽤服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝⼤多数情况下Servlet只⽤来扩展基于HTTP协议的Web服务器。

  • ⼯作模式:
    ① 客户端发送请求⾄服务器
    ② 服务器启动并调⽤Servlet,Servlet根据客户端请求⽣成响应内容并将其传给服务器
    ③ 服务器将响应返回客户端

2.1 Servlet工作原理

2.1.1 Servlet API

image-20210418165630663

创建⼀个类实现Servlet接⼝,重写⽅法。或继承HttpServlet亦可(首先需要导入工具中的jar包)

1
2
3
4
5
6
7
8
9
10
11
public class demo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get...");
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("post...");
}
}

测试 html页面:

1
2
3
4
5
<h1>我的第一个javaweb项目</h1>
<a href="test">demo1测试:doGet方法</a>
<form action="test" method="post" >
<input type="submit" value="post-test">
</form>

在web.xml⽂档中配置映射关系(Servlet服务器类和前端请求间的映射关系)

1
2
3
4
5
6
7
8
<servlet>
<servlet-name>a1</servlet-name>
<servlet-class>com.java.demo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>a1</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>

理解:

image-20210418192310618

这里的项目结构实际上就是服务器的结构,当我访问服务器的ip,端口,项目名称时,其实访问的就是html文件所呈现的一个页面

2.1.2 工作原理

首先:一个应用程序可能有多个Servlet类相绑定!!!如视频中的TestServlet和HttpServlet都对同一个html文件生效

  • Servlet接⼝定义了Servlet与servlet容器之间的契约。这个契约是:Servlet容器将Servlet类载⼊内存,并产⽣Servlet实例和调⽤它具体的⽅法。但是要注意的是,在⼀个应⽤程序中,每种Servlet类型只能有⼀个实例。
  • ⽤户请求致使Servlet容器调⽤Servlet的Service()⽅法,并传⼊⼀个ServletRequest对象和⼀个ServletResponse对象。ServletRequest对象和ServletResponse对象都是由Servlet容器(例如TomCat)封装好的,并不需要程序员去实现,程序员可以直接使⽤这两个对象。
  • ServletRequest中封装了当前的Http请求,因此,开发⼈员不必解析和操作原始的Http数据。ServletResponse表示当前⽤户的Http响应,程序员只需直接操作ServletResponse对象就能把响应轻松的发回给⽤户。
  • 对于每⼀个应⽤程序,Servlet容器还会创建⼀个ServletContext对象。这个对象中封装了上下⽂(应⽤程序)的环境详情。每个应⽤程序只有⼀个ServletContext。每个Servlet对象也都有⼀个封装Servlet配置的ServletConfig对象。

2.1.3 Servlet的生命周期

当客户端⾸次发送第⼀次请求后,由容器(web服务器(tomcat))去解析请求, 根据请求找到对应的servlet,判断该类的对象是否存在,不存在则创建servlet实例,调取init()⽅法 进⾏初始化操作

初始化完成后调取service()⽅法,由service()判断客户端的请求⽅式,如果是get,则执⾏doGet(),如果是post则执⾏doPost().处理⽅法完成后,作出相应结果给客户端.单次请求处理完毕。

当⽤户发送第⼆次以后的请求时,会判断对象是否存在,但是不再执⾏init(),⽽直接执⾏service⽅法,调取doGet()/doPost()⽅法。

当服务器关闭时调取destroy()⽅法进⾏销毁。

四个过程:

  • 实例化 —先创建servlet实例

  • 初始化 —init()

  • 处理请求 —-service()

  • 服务终⽌ —destory()

    image-20210418234921786

2.2 请求

2.2.1 常用方法

HttpServletRequest表示Http环境中的Servlet请求。它扩展于javax.servlet.ServletRequest接⼝
常⽤⽅法:

  • String getParameter(String name):根据表单组件名称获取提交数据,返回值是String

需要在表单标签中加入姓名属性

1
<input name="username" type="text" id="" class="">

注:服务器在接收数据时使用字符串统⼀接收

  • String[ ] getParameterValues(String name):获取表单组件对应多个值时的请求数据

  • void setCharacterEncoding(String charset):指定每个请求的编码(针对post请求才起作⽤)

  • RequestDispatcher getRequestDispatcher(String path): —跳转页面,返回⼀个RequestDispatcher对象,该对象的forward( )⽅法⽤于转发请求
    示例:

    1
    req.getRequestDispatcher("/success.html").forward(req,resp);
  • 存值request.setAttribute("key",value)

    注:存值得时间域:只能用于一次request请求

  • 取值 request.getAttribute("key")取值后需要向下转型

2.2.2 客户端如何发送数据给服务器

  1. 通过表单 get/post提交
  2. 通过a标签发送数据(get提交)
1
2
3
<a href="请求名?key=value&key=value&key=value...">
示例:
<a href="/login?a=10&name=abc&pass=123">

这⾥的key值=表单元素的控件名,value值=表单中控件的value属性值

注: 第⼀个参数使⽤?拼接,之后的参数使⽤&拼接,获取数据还是通过String name=request.getParameter("name");

  1. 通过地址栏直接拼接-get请求

  2. js提交数据-get请求

    location.href="⽬标请求?key=value&key=value"

    注:⽅式2/3都属于get提交⽅式,表单提交可以使⽤get、post提交⽅式

2.2.3 处理请求乱码的问题

post提交时管⽤

  1. setCharacterEncoding("UTF-8")

使⽤于get提交

  1. String s=new String(变量名.getBytes("ISO-8859-1"),"UTF-8")

    1
    String s=new String(request.getParameter("key").getBytes("ISO-8859-1"),"GBK");
  2. 修改tomcat中配置⽂件,在Tomcat⽬录结构\conf\server.xml中设置字符集

    1
    2
    3
    <Connector port="8080" protocol="HTTP/1.1"
    connectionTimeout="20000"
    redirectPort="8443" URIEncoding="UTF-8" />

    注意:tomcat8.0以后不需要⼿动设置这个属性了

2.2.4 get和post请求的区别

2.3 响应

在Service API中,定义了⼀个HttpServletResponse接⼝,它继承⾃ServletResponse接⼝,专⻔⽤来封装HTTP响应消息。 在HttpServletResponse接⼝中定义了向客户端发送响应状态码,响应消息头,响应消息体的⽅法。

常⽤⽅法:

  • void addCookie(Cookie var1);:给这个响应添加⼀个cookie
  • void sendRedirect(String var1):发送⼀条响应码,将浏览器跳转到指定的位置
  • PrintWriter getWriter():获得字符流,通过字符流的write(String s)⽅法可以将字符串设置到response缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览器端。
  • setContentType()设置响应内容的类型
1
2
3
4
5
6
7
8
9
10
11
12
//进行用户信息的判断,没有查到用户就弹窗,查到就跳转到成功页面        
if(users==null){
//以弹窗方式提示用户,登录失败
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.println("<script>location.href='login.jsp';alert('用户名或密码不正确');</script>");
}else{
//跳转到主页面
//保存用户信息
req.getSession().setAttribute("u1",users);
resp.sendRedirect("index.jsp");
}

2.3.1 转发和重定向

image-20210419010142600

转发:对应请求方法

request.getRequestDispatcher("../success.jsp").forward(request,response)

在请求的时候地址栏显示的是我们的请求href字符串testrequest

1
http://localhost:8080/testrequest?upass=abc&uage=12

一次请求过后服务器直接就把html内容发过来了

重定向:对应响应方法

response.sendRedirect()

在请求的时候同样是通过href字符串testrequest,但是服务器会把你准备跳转的html文件的名称success.html发回来,这时候就可以拿着这个名字去请求,最终地址栏就更加好看了!

1
http://localhost:8080/success.html

相同点:

都⽤来跳转⻚⾯

不同点:

a.重定向时地址栏会改变,request中存储的数据会丢失.转发时地址栏显示的是请求页面的地址,request数据可以保存。

如上面所示http://localhost:8080/testrequest?upass=abc&uage=12,每一次刷新都能获取数据

b.转发属于⼀次请求⼀次响应,重定向属于两次请求(地址栏修改了两次)两次响应。

补充:使⽤out对象往⻚⾯中输出js或html,css

2.4 session会话

概念:

request存的值只能在单次请求中保存,保存的数据不能跨页面,当重定向时,request存的值会丢失

session的数据可以在多个页面中共享,即使重定向页面,数据不会丢失

session中可以包含n个request。

会话的概念:从打开浏览器到关闭浏览器,期间访问服务器就称为⼀次会话

常⽤⽅法:

  • void setAttribute(String key,Object value):以key/value的形式保存对象值,将数据存储在服务器端

  • Object getAttribute(String key):通过key获取对象值

  • void invalidate():设置session对象失效

  • String getId():获取sessionid,当第⼀次登录成功后,session会产⽣⼀个唯⼀的id,浏览器之后访问时如果发现id值还是之前id,那么说明 当前访问的属于同⼀个会话

  • void setMaxInactiveInterval(int interval):设定session的⾮活动时间

    比如长时间不进行操作会让你重新登录,就是在会话期间没进行任何操作,在指定时间后会退出session,防止资源一直被占用

    示例:
    ⽅式1:session.setMaxInactiveInterval(10*60):设置有效时间为10分钟

    ⽅式2:修改web.xml

    1
    2
    3
    <session-config>
    <session-timeout>10</session-timeout>//单位:分钟
    </session-config>
  • int getMaxInactiveInterval():获取session的有效⾮活动时间(以秒为单位),默认的有效时间:30分钟

  • void removeAttribute(String key):从session中删除指定名称(key)所对应的对象

让session失效的⽅式:(1)invalidate() (2)removeAttribute(“key”) (3)直接关闭浏览器

可以理解为:每次打开一个新的浏览器的时候、或者是打开一个新的窗口的时候,打开的就是一个新的session会话

2.5 获得初始化参数

request.setCharacterEncoding(“utf-8”);代码的耦合度太⾼,不便于后期维护修改。可以通过初始化参数实现

实现⽅式:

  1. web.xml中先定义初始化参数(局部初始化参数)

    1
    2
    3
    4
    5
    6
    7
    8
    <servlet>
    <servlet-name></servlet-name>
    <servlet-class></servlet-class>
    <init-param>
    <param-name>encoding</param-name>
    <param-value>utf-8</param-value>
    </init-param>
    </servlet>

    servlet中获得初始化参数,重写init()⽅法

    1
    2
    3
    public void init(ServletConfig config) throws ServletException {
    encoding= config.getInitParameter("encoding");
    }

    注意:这种⽅式的初始化参数仅限于当前servlet类中使⽤。

  2. 全局初始化参数

    定义,context-param是和servlet标签同级别

    1
    2
    3
    4
    <context-param>
    <param-name>bianma</param-name>
    <param-value>utf-8</param-value>
    </context-param>

    获得数据

    1
    2
    3
    public void init(ServletConfig config) throws ServletException {
    bianhao=config.getServletContext().getInitParameter("bianma");
    }

2.6 servlet3.0

@WebServlet注解配置Servlet

从Servlet3.0开始,配置Servlet⽀持注解⽅式,但还是保留了配置web.xml⽅式,所有使⽤Servlet有两种⽅式:

(1)Servlet类上使⽤@WebServlet注解进⾏配置

(2)web.xml⽂件中配置

image-20210419015334391

实例:以Demo1为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@WebServlet(name = "myUserServlet",urlPatterns = "/user/test", //斜杠必须
loadOnStartup = 1,
initParams = {
@WebInitParam(name="name", value="⼩明"),
@WebInitParam(name="pwd", value="123456")
}
)
public class UserServlet extends HttpServlet {
private static final long serialVersionUID = 7109220574468622594L;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
System.out.println("servlet初始化...");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponseresponse) throws ServletException, IOException {
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
PrintWriter pw = response.getWriter();
pw.append("Hello Servlet!<br>" );
//servletName
pw.append("servletName:" + getServletName() + "<br>");
//initParam
ServletConfig servletConfig = this.getServletConfig();
Enumeration<String> paramNames = servletConfig.getInitParameterNames();
while (paramNames.hasMoreElements()) {
String paramName = paramNames.nextElement();
pw.append(paramName + ":" + servletConfig.getInitParameter(paramName) +
"<br>");
}
pw.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponseresponse) throws ServletException, IOException {
doGet(request, response);
}
}

loadOnStartup:

标记容器是否在启动应⽤时就加载Servlet,默认不配置或数值为负数时表示客户端第⼀次请求Servlet时再加载;

0或正数表示启动应⽤就加载,正数情况下,数值越⼩,加载该Servlet的优先级越⾼;

实例://斜杠必须

1
@WebServlet(value="/test1",loadOnStartup=1)

urlPatterns:/斜杠必须(一定要加斜杠,切记切记)

传入字符串表示对于该地址(href/action)的访问都可以用该类来接收,可以用{"","","}的方式传入多个url

name:

可以指定也可以不指定,通过getServletName()可以获取到,若不指定,则为Servlet的完整类名,如:cn.edu.njit.servlet.UserServlet

在使⽤注解⽅式时,需要注意:

根元素中不能配置属性metadata-complete=”true”,否则⽆法加载Servlet。metadata-complete属性表示通知Web容器是否寻找注解,

默认不写或者设置false,容器会扫描注解,为Web应⽤程序构建有效的元数据;metadata-complete=”true”,会在启动时不扫描注解

(hannotation)。如果不扫描注解的话,⽤注解进⾏的配置就⽆法⽣效,例如:@WebServlet

urlPatterns的常⽤规则:
/或者/:拦截所有 .do:拦截指定后缀
/user/test:拦截路径
/user/.do、/.do、test*.do都是⾮法的,启动时候会报错

3. JSP

3.1 概念

什么是JSP?

JSP全名为Java Server Pages,中⽂名叫java服务器⻚⾯,其根本是⼀个简化的Servlet设计,它 是由Sun Microsystems公司倡导、许多公司参与⼀起建⽴的⼀种动态⽹⻚技术标准。JSP技术有点类似ASP技术,它是在传统的⽹⻚HTML⽂件(.htm,.html)中插⼊Java程序段(Scriptlet)和JSP标记(tag),从⽽形成JSP⽂件,后缀名为(.jsp)。 ⽤JSP开发的Web应⽤是跨平台的,既能在Linux下运⾏,也能在其他操作系统上运⾏。
JSP将⽹⻚逻辑与⽹⻚设计的显示分离,⽀持可重⽤的基于组件的设计,使基于Web的应⽤程序的开发变得迅速和容易。
.html 静态⻚⾯(包含固定的⻚⾯内容)
*.jsp 动态⻚⾯(⻚⾯数据可以动态更新,⽀持嵌套java代码和html代码)

JSP为什么会出现

  1. servlet展示信息的不⽅便,引⼊了JSP。
  2. JSP本质上也是⼀个servlet!!!!!!
  3. JSP就是在HTML⻚⾯中嵌⼊了java代码。

JSP中如何嵌套java代码

答案:⼩脚本(<% java代码%>)

1
2
3
声明标签 <%!变量或者⽅法声明%>
表达式标签 <%= 表达式%> 在⻚⾯上显示的效果
程序代码标签 <%java代码%> ⻚⾯上动态展示内容

page指令:
<%@ page language=”java” import=”java.util.*” pageEncoding=”UTF-8”%>

1
2
3
4
5
<body>
<%! int i=10;%><!--成员变量-->
<%! public void show(){}%> <!--成员⽅法-->
<%=i%> <!--输出变量值-->
</body>

如果把⼀个数据存在request域中,取值操作如下:

image-20210419034353548

jsp中的注释

1
2
<!-- html注释内容,查看源码时能看到 -->
<%-- jsp注释,查看⻚⾯源码时看不到 --%>

3.2 JSP的原理

image-20210419213718614

当浏览器访问http://localhost:8080/test/index.jsp。服务器发现后缀为.jsp,它会根据路径找到index.jsp⽂件,会将index.jsp翻译成index_jsp.java⽂件,对这个java⽂件进⾏编译,产⽣⼀个index_jsp.class⽂件,将class⽂件加载运⾏。

此时在work文件夹中可以看到产生的java和class文件!!

image-20210419213941543

也就是说最终翻译成class,被虚拟机加载,本质就是servlet,拥有类似servlet中请求和响应的方法

响应回去就是把JSP中的HTML代码以流的⽅式写回浏览器。

3.3 JSP内置对象

JSP中⼀共预先定义了9个这样的对象,分别为:request、response、session、application、out、pagecontext、config、page、exception

1、request对象

request 对象是 javax.servlet.httpServletRequest类型的对象。 该对象代表了客户端的请求信息,主要⽤于接受通过HTTP协议传送到服

务器的数据。(包括头信息、系统信息、请求⽅式以及请求参数等)。request对象的作⽤域为⼀次请求。

2、response对象

response 代表的是对客户端的响应,主要是将JSP容器处理过的对象传回到客户端。response对象也具有作⽤域,它只在JSP⻚⾯内有

效。所属类型:HttpServletResponse

3、session对象

session 对象是由服务器⾃动创建的与⽤户请求相关的对象。服务器为每个⽤户都⽣成⼀个session对象,⽤于保存该⽤户的信息,跟踪⽤

户的操作状态。session对象内部使⽤Map类来保存数据,因此保存数据的格式为 “Key/value”。 session对象的value可以使复杂的对象类

型,⽽不仅仅局限于字符串类型。HttpSession
4、application对象

application 对象可将信息保存在服务器中,直到服务器关闭,否则application对象中保存的信息会在整个应⽤中都有效。与session对象

相⽐,application对象⽣命周期更⻓,类似于系统的“全局变量”ServletContext

1
2
3
4
5
区别:
request:单次请求
session:浏览器访问期间(会话期间)
application:服务器启动期间,所存的数据可以跨浏览器
pageContext:单个页面内

5、out 对象

out 对象⽤于在Web浏览器内输出信息,并且管理应⽤服务器上的输出缓冲区。在使⽤ out 对象输出数据时,可以对数据缓冲区进⾏操

作,及时清除缓冲区中的残余数据,为其他的输出让出缓冲空间。待数据输出完毕后,要及时关闭输出流。

示例:

1
out.print("<script type='text/javascript'>alert('⽤户名不存在');location.href='index.jsp'</script>");

6、pageContext 对象

pageContext 对象的作⽤是取得任何范围的参数,通过它可以获取 JSP⻚⾯的out、request、reponse、session、application 等对象。

pageContext对象的创建和初始化都是由容器来完成的,在JSP⻚⾯中可以直接使⽤ pageContext对象。

7、config 对象

config 对象的主要作⽤是取得服务器的配置信息。通过 pageConext对象的 getServletConfig() ⽅法可以获取⼀个config对象。当⼀个

Servlet 初始化时,容器把某些信息通过config对象传递给这个Servlet。 开发者可以在web.xml ⽂件中为应⽤程序环境中的Servlet程序和

JSP⻚⾯提供初始化参数。

1
2
3
//将image路径转换成服务器端的路径
String url= config.getServletContext().getRealPath("/image");
<h1>url=<%=url %></h1>

8、page 对象

page 对象代表JSP本身,只有在JSP⻚⾯内才是合法的。 page隐含对象本质上包含当前 Servlet接⼝引⽤的变量,类似于Java编程中的 this

指针。
9、exception 对象
exception 对象的作⽤是显示异常信息,只有在包含 isErrorPage=”true” 的⻚⾯中才可以被使⽤,在⼀般的JSP⻚⾯中使⽤该对象将⽆法编译JSP⽂件。excepation对象和Java的所有对象⼀样,都具有系统提供的继承结构。exception 对象⼏乎定义了所有异常情况。在Java程序中,可以使⽤try/catch关键字来处理异常情况; 如果在JSP⻚⾯中出现没有捕获到的异常,就会⽣成 exception 对象,并把exception 对象传送到在page指令中设定的错误⻚⾯中,然后在错误⻚⾯中处理相应的 exception 对象。
(1)先在可能发⽣错误的⻚⾯中添加errorPage属性:

1
<%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="test1.jsp" %>

(2) 在error.jsp⻚⾯中设置isErrorPage=”true” 的属性(使⽤exception对象之前,需要先将当前⻚⾯设置成错误⻚⾯)

1
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>

request,session,application,pageContext四种数据存储对象的区别:

test页面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   <%//作用域为一次请求%>
<%request.setAttribute("a1","aaa");%>
request=<%=request.getAttribute("a1")%><br/>
<% //作用域为浏览器访问期间%>
<%
session.setAttribute("b1","bbb");
%>
session=<%=session.getAttribute("b1")%><br/>
<%//作用域为服务器运行期间,类似于全局变量ServletContext%>
<%
application.setAttribute("c1","ccc");
%>
application =<%=application.getAttribute("c1")%><br/>
<%//作用域为当前网页%>
<%
pageContext.setAttribute("d1","ddd");
%>
pageContext=<%=pageContext.getAttribute("d1")%><br/>
<a href="test1.jsp">test1.jsp</a>

image-20210419222810007

test1页面:

1
2
3
4
5
6
7
8
<%//作用域为一次请求%>
request=<%=request.getAttribute("a1")%><br/>
<% //作用域为浏览器访问期间%>
session=<%=session.getAttribute("b1")%><br/>
<%//作用域为服务器运行期间,类似于全局变量ServletContext%>
application =<%=application.getAttribute("c1")%><br/>
<%//作用域为当前网页%>
pageContext=<%=pageContext.getAttribute("d1")%><br/>

image-20210419222837352

可以明显看出跳转页面后,只有session和application的数据还能够有效访问,当切换浏览器进行访问test1.jsp时,同样无法获取session的值!!

3.4 JSP的指令

JSP指令⽤来设置整个JSP⻚⾯相关的属性,如⽹⻚的编码⽅式和脚本语⾔。语法格式如下:

<%@ directive attribute="value" %>

directive:指令名称 attribute 属性名 value:属性值

image-20210419225751630

3.4.1 Page指令

Page指令为容器提供当前⻚⾯的使⽤说明⼀个JSP⻚⾯可以包含多个page指令
语法格式:
<%@ page attribute="value" %>

image-20210419225859091

3.4.2 include指令

JSP可以通过include指令来包含其他⽂件。被包含的⽂件可以是JSP⽂件、HTML⽂件或⽂本⽂件。包含的⽂件就好像是该JSP⽂件的⼀部分,会被同时编译执⾏。(类似于html中的frameset或者iFrame标签)

语法格式:

<%@ include file="⽂件相对 url 地址" %>

include 指令中的⽂件名实际上是⼀个相对的 URL 地址。如果您没有给⽂件关联⼀个路径,JSP编译器默认在当前路径下寻找。

3.4.3 Taglib指令

JSP API允许⽤户⾃定义标签,⼀个⾃定义标签库就是⾃定义标签的集合。
Taglib指令引⼊⼀个⾃定义标签集合的定义,包括库路径、⾃定义标签

格式:

<%@ taglib uri="uri" prefix="" %>

uri属性确定标签库的位置,prefix属性指定标签库的前缀(可⾃定义)。

3.5 JSP出现的状态码

每一次请求和响应都会有一个状态码,是对操作结果的一个数值型标记,可以帮助我们找出错误

image-20210419231751653

3.6 EL表达式

实际开发中并不会用小脚本的方式!!也就是不会让显示部分和逻辑代码嵌套,逻辑部分还是交由后台执行,这里的EL表达式和下面的JSTL都是为了简化显示。

什么是Expression Language 表达式语⾔?

最初定义于JSTL1.0部分

在JSP2.0中,EL从JSTL中剥离出来,放置在JSP规范中,称为JSP2.0规范的⼀部分

在JSP中使⽤EL表达式,可以简化对象和变量的访问是EL表达式

EL表达式语法

语法格式:${需要展示信息的名字}

注意:

  • 无法显示定义的变量,想要读取变量,该变量一定要保存在作用域中

  • 当表达式没有指定变量或者对象的范围时,那么容器会依次从pageContext—>request—>session—>application中查找该变量或对象,我们可以通过隐含对象获得指定作⽤域的值:

对于集合和多个域有相同key值的取值?

1
2
3
4
5
6
7
8
9
10
11
12
13
List<String> l = new ArrayList<String>();
int a = 10;
pageContext.setAttribute("a1", a);
l.add("a");
l.add("b");
pageContext.setAttribute("a2", l);
Map<String,String> m = new HashMap<>();
m.put("today","今天天气不错");
pageContext.setAttribute("a3",m);
pageContext.setAttribute("a4", "pageContext内容");
request.setAttribute("a4", "request内容");
session.setAttribute("a4", "session内容");
application.setAttribute("a4", "application内容");
1
2
3
4
5
6
7
${20<30? "aaa":"bbb"}
a = ${a}<br>
a = ${a1}<br>
a = ${a2[1]}<br>
key = ${a3.today}
session-a4 = ${sessionScope.a4}
a4 = ${a4}

显示结果:

1
2
3
4
5
6
7
8
9
10
this is top
this is middle
this is bottom
50
false
true
aaa a =
a = 10
a = b
key = 今天天气不错 session-a4 = session内容 a4 = pageContext内容

EL中基础操作符:

image-20210420233833236

1
2
3
4
5
判断变量是否有值或是否存在:${empty key值}
List list2=new ArrayList();
list2.add("aa");
request.setAttribute("list222",list2);
判断list中是否有数据:${empty list222}

3.7 JSTL

一:什么是JSTL?

JSP标准标签库(JSTL)是⼀个JSP标签集合,它封装了JSP应⽤的通⽤核⼼功能。

JSTL⽀持通⽤的、结构化的任务,⽐如迭代,条件判断,XML⽂档操作,国际化标签,SQL标签。 除了这些,它还提供了⼀个框架来使⽤集成JSTL的⾃定义标签。

根据JSTL标签所提供的功能,可以将其分为5个类别。核⼼标签 格式化标签 sql标签 xml标签 jstl函数

二:JSTL的作⽤和语法格式:

作⽤:简化jsp⻚⾯编写代码

语法格式:

  1. 下载 jakarta-taglibs-standard-1.1.2.zip 包并解压,将 jakarta-taglibs-standard-1.1.2/lib/ 下的两个 jar ⽂件:standard.jar 和 jstl.jar ⽂件拷⻉到 /WEB-INF/lib/ 下。
  2. 在JSP⻚⾯中引⼊<%@ taglib prefix=”⻚⾯使⽤的名称” uri=”功能范围的路径”%>

    image-20210421000911845

三:核⼼标签

核⼼标签是最常⽤的 JSTL标签。引⽤核⼼标签库的语法如下:

1
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

核⼼标签的分类

  • 表达式操作: out、set、remove、catch

  • 流程控制:if、choose、when、otherwise

  • 迭代操作:forEach、forTokens

  • URL操作:import、param、url、redirect

  • Set标签
    <c:set> 主要⽤来将变量存储⾄JSP范围中 或是JavaBean的属性或Map对象中

    image-20210421001757369

    <c:out>主要⽤来显示数据的内容

    image-20210421001833627

    <c:remove> 主要负责移除变量

    image-20210421001912043

    <c:if> 主要⽤于进⾏if判断,如果为true,则输出标签体中的内容

    image-20210421001948836

    <c:choose>,<c:when>,<c:otherwise> 作⽤相当于if-else

    image-20210421002019812

    <c:forEach> 循环控制,它可以将数组,集合(Collection)中的成员循序浏览⼀遍

    image-20210421002052717

格式化标签

  1. fmt:formatDate 作⽤:将⽇期类型格式化为指定模式的字符串属性

    value:将要被格式化的数据

    pattern:格式化的模式,与SimpleDateFormat的参数设置⼀样

    var:格式化后的字符串所要存放的变量,若不指定var,则会将格式化的结果直接显示在⻚⾯

    scope:变量存放的域属性空间,默认page

    type:其取值为date、time、both,表示给出的value是⽇期、时间、还是两者都包含,默认是date

  2. fmt:parseDate 作⽤:⽤于将指定字符串转化为⽇期类型

    <fmt:parseDate value="${now }" pattern="yyyy-MM-dd" var="today"/>

    Value服务器获取的时间

    Pattern:转换的格式

    Var:⻚⾯显示的变量

  3. fmt:formatNumber 按照指定格式对数字进⾏格式化属性

    maxIntegerDigits:整数部分最多的位数

    minIntegerDigits:整数部分最少的位数

    maxFrctionDigits:⼩数部分最多的位数

    minFrctionDigits:⼩数部分最少的位数

    var:存储格式化结果的变量

    scope:var属性的作⽤域

    integerOnly:是否只解析整型数true或者浮点数false

4. session和cookie

什么是会话跟踪技术

会话跟踪是Web程序中常⽤的技术,⽤来跟踪⽤户的整个会话。保持对⽤户会话期间的数据管理。常⽤的会话跟踪技术是Cookie与Session。

  • Cookie通过在客户端记录信息确定⽤户身份
  • Session通过在服务器端记录信息确定⽤户身份。

概念

  • Cookie是客户端(⼀般指浏览器)请求服务器后,服务器发给客户端的⼀个辨认标识,保存在客户端,当客户端再次向服务器发送请求时,会携带着这个辨认标识,服务器就可以通过这个标识来识别客户端的身份或状态等。

  • Cookie的作⽤:

    跟踪会话,记录⼀次会话中(即Session,⼀次会话可能会有多次请求,当然也可以有多个Cookie来跟踪不同的信息)的信息,这样服务器就会知道⽤户的状态,⽐如有没有登录成功,付款时购物⻋中的东⻄等,就相当于贴在客户端脑⻔上的纸条,浏览器看不到,但服务器看得到。

注意:不同浏览器存储的cookie内容不同,解析方式也不同

Cookie的应⽤

  • 保持⽤户登录状态

    将⽤户的信息保存到Cookie中,并发送给浏览器,并且将有效时间设置为⼀个较⻓的时间,这样浏览器在以后访问⽹站时,都会带着该Cookie,服务器以此来辨识⽤户,⽤户就不再需要输⼊⽤户名和密码等信息。

  • 记录⽤户名

    ⼀旦⽤户登录成功以后,下次再登录时,直接将Cookie中的⽤户名读取并显示出来,这样⽤户就不需要再次输⼊⽤户名,只输⼊密码即可。

Cookie的设置和获取

  • 通过HttpServletResponse.addCookie的⽅式设置Cookie

    注意:new Cookie()时两个参数都是字符串

    1
    2
    Cookie cookie = new Cookie("jieguo","true");
    response.addCookie(cookie);
  • 浏览器中查看cookie的内容:

    image-20210421122907388

  • 服务端获取客户端携带的cookie:通过HttpServletRequest获取

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <%
    Cookie[] cookies = request.getCookies();
    if(cookies != null)
    for(Cookie c : cookies){
    String name = c.getName();//获取Cookie名称
    if("jieguo".equals(name)){
    String value = c.getValue();//获取Cookie的值
    bool = Boolean.valueOf(value);//将值转为Boolean类型
    }
    }
    %>

删除Cookie

  • 立即失效

    通过设置同名Cookie的最⼤存活时间为0,删除Cookie是指使浏览器不再保存Cookie,使Cookie⽴即失

    举例:使name为username的Cookie⽴即失效

    1
    2
    3
    4
    5
    6
    //1.创建⼀个name为username的Cookie
    Cookie cookie = new Cookie("username", "aaa");
    //2.设置Cookie的有效时间为0
    cookie.setMaxAge(0);//删除cookie的关键
    //3.将cookie发送给浏览器,来替换同名Cookie
    response.addCookie(cookie);
  • Cookie的有效时间
    Cookie发送给浏览器以后,浏览器并不会永久保存,也就是到了⼀定的时间以后浏览器会⾃动销毁Cookie。Cookie的默认有效时间为⼀次会话(⼀次打开关闭浏览器的过程),我们也可以⼿动指定Cookie的有效时间

    实例:126邮箱在登录时可以选择10天免登录

1
2
3
4
5
6
7
8
9
10
//setMaxAge⽤来设置Cookie的最⼤有效时间,需要int型的参数,代表有效的秒数
cookie.setMaxAge(秒数);
//当参数⼤于0时,会设置为指定的秒数
cookie.setMaxAge(30);
//当参数等于0时,浏览器不会保存Cookie,Cookie⽴即失效
cookie.setMaxAge(0);
//当参数⼩于0时,和不设置是⼀样,当前会话有效
cookie.setMaxAge(-100);
//设置⼀个永久有效的Cookie,并⾮永久,只是使Cookie的⽣命很⻓⽽已
cookie.setMaxAge(60*60*24*365*10)

4.2 session

概念

  • Session是另⼀种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,⽽Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。如果说Cookie机制是通过检查客户身上的“通⾏证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建⽴的⼀份客户档案,客户来访的时候只需要查询客户档案表就可以了。

    需要注意:session持续占用服务器资源,不能随便用

创建Session的格式

Session对应的类为javax.servlet.http.HttpSession类。每个来访者对应⼀个Session对象,所有该客户的状态信息都保存在这Session对象⾥。Session对象是在客户端第⼀次请求服务器的时候创建的。

Session也是⼀种key-value的属性对,通过getAttribute(Stringkey)和setAttribute(String key,Objectvalue)⽅法读写客户状态信息。Servlet⾥通过request.getSession()⽅法获取该客户的 Session

例如:

1
2
3
HttpSession session = request.getSession(); // 获取Session对象
session.setAttribute("loginTime", new Date()); // 设置Session中的属性
out.println("登录时间为:" +(Date)session.getAttribute("loginTime")); // 获取Session属性

Session的⽣命周期

Session保存在服务器端。为了获得更⾼的存取速度,服务器⼀般把Session放在内存⾥。每个⽤户都会有⼀个独⽴的Session。如果

Session内容过于复杂,当⼤量客户访问服务器时可能会导致内存溢出。因此,Session⾥的信息应该尽量精简。

  • 产生:

    Session在⽤户第⼀次访问服务器的时候⾃动创建。需要注意只有访问JSP、Servlet等程序时才会创建Session,只访问HTML、IMAGE等静态资源并不会创建Session。如果尚未⽣成Session,也可以使request.getSession(true)强制⽣成Session。

  • 如何失效

    Session⽣成后,只要⽤户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。⽤户每访问服务器⼀次,⽆论是否读写Session,服务器都认为该⽤户的Session“活跃(active)”了⼀次。由于会有越来越多的⽤户访问服务器,因此Session也会越来越多。

    为防⽌内存溢出,服务器会把⻓时间内没有活跃的Session从内存删除。这个时间就是Session的超时时间。如果超过了超时时间没访问过服务器,Session就⾃动失效了。

    获取、修改有效时间:

    Session的超时时间为maxInactiveInterval属性,可以通过对应的getMaxInactiveInterval()获取,通过setMaxInactiveInterval(longinterval)修改。
    Session的超时时间也可以在web.xml中修改。另外,通过调⽤Session的invalidate()⽅法可以使Session失效。

    1
    2
    3
    <session-config>
    <session-timeout>30</session-timeout>
    </session-config>
  • 直接注销session

    invalidate()

常用方法

image-20210421140851558

Session和Cookie的区别

  • Cookie数据保存在客户端,Session数据保存在服务器端。
  • Session是由应⽤服务器维持的⼀个服务器端的存储空间,⽤户在连接服务器时,会由服务器⽣成⼀个唯⼀的SessionID,⽤该SessionID 为标识符来存取服务器端的Session存储空间。⽽SessionID这⼀数据则是保存到客户端,⽤Cookie保存的,⽤户提交⻚⾯时,会将这⼀SessionID提交到服务器端,来存取Session数据。这⼀过程,是不⽤开发⼈员⼲预的。**所以⼀旦客户端禁⽤Cookie,那么Session也会失效。**
  • Cookies是属于Session对象的⼀种。但有不同,Cookies不会占服务器资源,是存在客服端内存或者⼀个Cookie的⽂本⽂件中;⽽Session则会占⽤服务器资源。所以,尽量不要使⽤Session,⽽使⽤Cookies。但是我们⼀般认为Cookie是不可靠的,Cookies是保存在本机上的,但是其信息的完全可⻅性且易于本地编辑性,往往可以引起很多的安全问题Session是可靠地。但是⽬前很多著名的站点也都⽤Cookie。

5. 过滤器(Filter)和监听器(Listener)

5.1 Filter

概念

过滤器实际上就是对web资源进⾏拦截,做⼀些处理后再交给下⼀个过滤器或servlet处理,通常都是⽤来拦截request进⾏处理的,也可以对返回的response进⾏拦截处理

image-20210421142948852

过滤器的语法格式:

  • 创建⼀个类实现Filter接⼝

    public class CharSetFilter implements Filter{}`

  • 重写接⼝中的⽅法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public void destroy() { //销毁的⽅法}
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    //过滤⽅法 主要是对request和response进⾏⼀些处理,然后交给下⼀个过滤器或Servlet处理
    //有过滤器走过滤器,没有过滤器走servlet
    System.out.println("过滤器开始");
    //调取下一个过滤器
    filterChain.doFilter(servletRequest,servletResponse);
    System.out.println("过滤器结束");
    }
    public void init(FilterConfig config) throws ServletException {
    /*初始化⽅法 接收⼀个FilterConfig类型的参数 该参数是对Filter的⼀些配置*/
    }
  • 在web.xml⽂件中配置

    1
    2
    3
    4
    5
    6
    7
    8
    <filter>
    <filter-name>过滤器名称</filter-name>
    <filter-class>过滤器所在的路径</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>过滤器名称</filter-name>
    <url-pattern>需要过滤的资源</url-pattern>
    </filter-mapping>

实例:

  • 单个过滤器执行结果

    1
    2
    3
    过滤器开始
    aaa //这是执行了servlet中的打印方法
    过滤器结束
  • 两个过滤器的执行结果

    1
    2
    3
    4
    5
    6
    7
    8
    //先执行过滤器1
    过滤器开始
    //执行到filterChain.doFilter(servletRequest,servletResponse);启动第二个过滤器
    过滤器2开始
    //执行到filterChain.doFilter(servletRequest,servletResponse);没有第三个过滤器,执行servlet
    aaa
    过滤器2结束
    过滤器结束

    注意:两个过滤器执行的先后顺序由xml配置的先后顺序决定!!

过滤器的使用场合

  • 如何防⽌⽤户未登录就执⾏后续操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    //防止未登录访问
    String requestURI = req.getRequestURI();//获得请求地址
    System.out.println("requestURL="+requestURI);
    Object username= req.getSession().getAttribute("username");
    if(requestURI.endsWith("testsession.jsp")&&username==null){
    resp.sendRedirect("index.jsp");
    }
    }
  • 设置编码⽅式—统⼀设置编码

    如果需要对所有servlet都执行编码操作,只要把xml中的url-Partten中的/login改为/*

    1
    2
    3
    4
    5
    6
    7
    8
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    System.out.println("过滤器开始");
    HttpServletRequest req= (HttpServletRequest)servletRequest;
    req.setCharacterEncoding("utf-8");
    //调取下一个过滤器
    filterChain.doFilter(servletRequest,servletResponse);
    System.out.println("过滤器结束");
    }
  • 加密解密(密码的加密和解密)

  • ⾮法⽂字筛选

  • 下载资源的限制
    过滤器的特点:在servlet之前和之后都会被执⾏

5.2 Listener

概念

监听器就是监听某个域对象的的状态变化的组件

监听器的相关概念:

  • 事件源:被监听的对象(三个域对象 request、session、servletContext)

  • 监听器:监听事件源对象事件源对象的状态的变化都会触发监听器

  • 注册监听器:将监听器与事件源进⾏绑定

  • 响应⾏为:监听器监听到事件源的状态变化时所涉及的功能代码(程序员编写代码)

监听器分类:

第⼀维度按照被监听的对象划分:ServletRequest域、HttpSession域、ServletContext域

第⼆维度按照监听的内容分:监听域对象的创建与销毁的、监听域对象的属性变化的

image-20210421152453782

监听三⼤域对象的创建与销毁的监听器

监听器的编写步骤(重点):

  • 编写⼀个监听器类去实现监听器接⼝
  • 覆盖监听器的⽅法
  • 需要在web.xml中进⾏配置—注册
1
2
3
<listener>
<listener-class>com.java.AttributeListener</listener-class>
</listener>

常用监听器接口

  • ServletContextListener

    监听ServletContext域的创建与销毁的监听器

    Servlet域的⽣命周期
    何时创建:服务器启动创建
    何时销毁:服务器关闭销毁

    ServletContextListener监听器的主要作⽤
    初始化的⼯作:初始化对象、初始化数据(加载数据库驱动、连接池的初始化)加载⼀些初始化的配置⽂件(spring的配置⽂件)
    任务调度(定时器—Timer/TimerTask)

  • HttpSessionListener
    监听Httpsession域的创建和销毁的监听器
    HttpSession对象的⽣命周期
    何时创建:第⼀次调⽤request.getSession时创建
    何时销毁:服务器关闭销毁、session过期(默认30分钟,修改默认的30分钟是在Tomcat的web.xml,修改当前项⽬的过期时间是在⾃⼰项⽬的web.xml中)、⼿动销毁

    HttpSessionListener监听器的主要作⽤:
    由于每次访问⽹站都会默认创建session对象(jsp⻚⾯中page指令中的session属性默认为true,即被访问时创建session),可以⽤于计数⽹站访问过的⼈

  • ServletRequestListener
    监听ServletRequest域创建与销毁的监听器

6. MVC

写Java Web项⽬时会发现,⼀个中型或者⼤型项⽬随着代码的增多,会发现:代码既可以写在src⽬录
下,也可以写在WebContent⽬录下。src下可以建很多包 ,WebContent下可以建很多⽂件夹。

所以问题就来了:

⼀个新的类到底往哪个⽬录下的哪个⽂件夹⾥写?

此时解决办法就是:需要⼀个模式去规范,到底哪个类该往哪⾥写。

6.1 MVC设计模式

Web MVC中的M(model)-V(view)-C(controller)概念和标准MVC概念⼀样,我们再看⼀下Web MVC标准架构,如下图所示:

image-20210421201133156

在Web MVC模式下,模型⽆法主动推数据给视图,如果⽤户想要视图更新,需要再发送⼀次请求(即请求-响应模型)。

  • M:(Model) 模型 : 应⽤程序的核⼼功能,管理这个模块中⽤的数据和值(bean,dao)

    java基础部分的内省内容介绍了javabean的概念,以及如何通过内省的方式获取bean类中的get/set方法!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    JavaBeans :是Java中⼀种特殊的类(换⾔之:JavaBean就是⼀个Java类).
    ⼀个Java类 ,满⾜以下要求,则可称为⼀个JavaBean
    a. public修饰的类,提供public ⽆参构造⽅法
    b. 所有属性 都是private
    C. 提供getter和setter⽅法
    从使⽤层⾯来看,JavaBean分为2⼤类:
    a. 封装业务逻辑的JavaBean(eg:LoginDao.java 封装了登录逻辑)
    b. 封装数据的JavaBean(实体类:eg:Student.java Vadio.java 。往往对应于数据库中的⼀张
    表,即数据库中有个Student表,项⽬中就有个Student.java类)通常:表名=类名,列名=属性名
    JavaBean是⼀个可以重复使⽤的组件,通过编写⼀个组件来实现某种通⽤功能,“⼀次编写、任何地⽅执
    ⾏、任何地⽅重⽤”
  • V(View )视图:视图提供模型的展示,管理模型如何显示给⽤户,它是应⽤程序的外观;(jsp/html)

  • C(Controller)控制器:对⽤户的输⼊做出反应,管理⽤户和视图的交互,是连接模型和视图的枢纽。(servlet/service)MVC⽤于将web(UI)层进⾏职责解耦

    说明:mvc设计模式(不属于23种设计模式)

6.2 三层架构

三层架构:

通常意义上的三层架构就是将整个业务应⽤划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。区分层次的⽬的即为了“⾼内聚,低耦合”的思想。

  • 哪三层?
    • 表现层(UI):通俗讲就是展现给⽤户的界⾯,即⽤户在使⽤⼀个系统的时候他的所⻅所得。jsp/html
    • 业务逻辑层(BLL):针对具体问题的操作,也可以说是对数据层的操作,对数据业务逻辑处理。servlet,service
    • 数据访问层(DAL):该层所做事务直接操作数据库,针对数据的增添、删除、修改、更新、查找等。dao
  • 代表框架:
    • 表现层实现的代表作品是Struts,springmvc框架
    • 业务层实现的代表作品是Spring
    • 持久层实现的代表作品是Hibernate,mybatis
  • 层就相当于⼀个⿊盒⼦,我们不⽤知道它内部怎么实现,只需要知道如何去调⽤它就⾏了。每层只与上下相邻的两层打交道。当⼀层内部由于技术变迁发⽣变化时,只要接⼝不变,其他层不⽤做任何改变。分层之后灵活性提⾼,也便于团队分⼯开发。

6.3 三层架构和MVC的区别与联系

image-20210421203306582

实例:

客户端发送请求>servlet>service>dao>数据库

7. Ajax

7.1 Ajax简介

AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。

AJAX 不是新的编程语⾔,⽽是⼀种使⽤现有标准的新⽅法。

AJAX 是与服务器交换数据并更新部分⽹⻚的艺术,在不重新加载整个⻚⾯的情况下。

7.2 Ajax所包含的技术

ajax并⾮⼀种新的技术,⽽是⼏种原有技术的结合体。它由下列技术组合⽽成。

  1. 使⽤CSS和XHTML来表示。

  2. 使⽤DOM模型来交互和动态显示。

  3. 使⽤XMLHttpRequest来和服务器进⾏异步通信。

  4. 使⽤javascript来绑定和调⽤。

  5. AJAX 的核⼼是 XMLHttpRequest 对象。

    不同的浏览器创建 XMLHttpRequest 对象的⽅法是有差异的。IE 浏览器使⽤ ActiveXObject,⽽其他的浏览器使⽤名为 XMLHttpRequest 的 JavaScript 内建对象

7.3 Ajax的工作原理

Ajax的⼯作原理相当于在⽤户和服务器之间加了—个中间层(AJAX引擎),使⽤户操作与服务器响应异步化。并不是所有的⽤户请求都提交给服务器。像—些数据验证和数据处理等都交给Ajax引擎⾃⼰来做,,只有确定需要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。

  • 传统的web应用模型

    UI>>HTTP请求>>web服务器>>数据存储和逻辑处理>>返回HTML和CSS数据

  • 利用Ajax异步的web应用模型

    image-20210423090912818

    多了一个Ajax作为中介,客户端发送的是本地的js请求,再由浏览器转换为http请求发送到服务器

    同时对于服务器的返回数据,也是由Ajax引擎转换到HTML

  • 浏览器的普通交互方式

    image-20210423091302011

  • Ajax交互方式

    image-20210423091325507

异步的理解:

浏览器调用JS调用Ajax引擎,向服务器发送html请求,服务器接收请求 并做出反应,向浏览器发送xml或文本数据,而不是整个html页面(我认为ajax引擎就是xmlhttprequest对象,通过xmlhttprequest向服务器发送请求)

Ajax是一种技术,而我认为实现该技术的核心是XmlHttpRequest,XmlHttpRequest(XMLHTTP是个传送XML格式数据的超文本传输协议)是XMLHTTP组件的对象,通过这个对象,浏览器就可向服务器请求并处理响应了(此通信是数据层面的交互),而不阻塞用户


Ajax生成的XMLHttpRequest对象就像是将用户想要对服务器进行的请求暂时存储为XML数据,然后再向服务器提交,此时就可以实现多个响应的异步执行!!!!

  • 之前的提交请求后跳转(包括跳转会原页面)的方式:导致用户只能一次请求后就要等待
  • 之前的前端js进行用户判断的方式:无法调用后台数据库的数据进行验证

实例:

  • 在创建Web站点时,在客户端执⾏屏幕更新为⽤户提供了很⼤的灵活性。下⾯是使⽤Ajax可以完成的功能:
  • 动态更新购物⻋的物品总数,⽆需⽤户单击Update并等待服务器重新发送整个⻚⾯。
  • 提升站点的性能,这是通过减少从服务器下载的数据量⽽实现的。例如,在Amazon的购物⻋⻚⾯,当更新篮⼦中的⼀项物品的数量时,会重新载⼊整个⻚⾯,这必须下载32K的数据。如果使⽤Ajax计算新的总量,服务器只会返回新的总量值,因此所需的带宽仅为原来的百分之⼀。
  • 消除了每次⽤户输⼊时的⻚⾯刷新。例如,在Ajax中,如果⽤户在分⻚列表上单击Next,则服务器数据只刷新列表⽽不是整个⻚⾯。
  • 直接编辑表格数据,⽽不是要求⽤户导航到新的⻚⾯来编辑数据。对于Ajax,当⽤户单击Edit时,可以将静态表格刷新为内容可编辑的表格。⽤户单击Done之后,就可以发出⼀个Ajax请求来更新服务器,并刷新表格,使其包含静态、只读的数据。

7.4 XMLHttpRequest常⽤属性

  1. onreadystatechange 属性
    onreadystatechange 属性存有处理服务器响应的函数。
    下⾯的代码定义⼀个空的函数,可同时对 onreadystatechange 属性进⾏设置:

    1
    xmlHttp.onreadystatechange = function() { //我们需要在这写⼀些代码}
  2. readyState 属性
    readyState 属性存有服务器响应的状态信息。每当 readyState 改变时,onreadystatechange 函数就会被执⾏。
    readyState 属性可能的值:

    image-20210423093323545

    我们要向这个 onreadystatechange 函数添加⼀条 If 语句,来测试我们的响应是否已完成(意味着可获得数据):

    1
    2
    3
    4
    5
    xmlHttp.onreadystatechange = function() {
    if (xmlHttp.readyState == 4) {
    //从服务器的response获得数据
    }
    }
  3. responseText 属性
    可以通过 responseText 属性来取回由服务器返回的数据。
    在我们的代码中,我们将把时间⽂本框的值设置为等于 responseText:

    1
    2
    3
    4
    5
    xmlHttp.onreadystatechange = function() {
    if (xmlHttp.readyState == 4) {
    document.myForm.time.value = xmlHttp.responseText;
    }
    }

    其它属性如下:

    image-20210423093516948

7.5 XMLHttpRequest⽅法

  1. open() ⽅法
    open() 有三个参数。第⼀个参数定义发送请求所使⽤的⽅法,第⼆个参数规定服务器端脚本的URL,第三个参数规定应当对请求进⾏异步地处理。

    1
    xmlHttp.open("GET","test.php",true);
  2. send() ⽅法
    send() ⽅法将请求送往服务器。如果我们假设 HTML ⽂件和 PHP ⽂件位于相同的⽬录,那么代码是这
    样的:

    1
    xmlHttp.send(null);
  3. 其他方法如下:

    image-20210423093620695

完整的Ajax动态响应实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<script type="text/javascript">
function test(){
//发送异步请求
//1.创建XMLHttpRequest
//注意:⼀般我们⼿写AJAX的时候,⾸先要判断该浏览器是否⽀持XMLHttpRequest对象,如果⽀持则创建该对象,如果不⽀持则创建ActiveX对象(如果是IE5或者IE6浏览器,则使⽤ActiveX对象,创建⽅法是:)。
var xmlhttp;
if(window.XMLHttpRequest){
//非IE
xmlhttp = new XMLHttpRequest();
}else if(window.ActiveXObject){
//IE
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//2.打开链接
var uname = document.getElementById("uname").value;
xmlhttp.open("get","/testuname?username="+uname, true);
//3.指定回调函数
xmlhttp.onreadystatechange=function(){
//3.1 判断状态
if(xmlhttp.readyState==4){
var responseText = xmlhttp.responseText;
document.getElementById("rs").innerText = responseText;
}
}
//4.发送数据
xmlhttp.send();
}
</script>

第二步:请求方法:

在WEB开发中,请求有两种形式,⼀个是get,⼀个是post,所以在这⾥需要设置⼀下具体使⽤哪个请求,XMLHttpRequest对象的open()⽅法就是来设置请求⽅式的。

image-20210423094532847

如将上面的get请求转为post请求:

1
2
3
4
5
6
7
8
9
10
//如何发送post请求
xmlhttp.open("post","/testuname", true);
//如何传递get里面的参数, 在send方法中传
//第四步:设置发送请求的内容和发送报送。然后发送请求
var params = "userName=" + uname;
// 增加time随机参数,防⽌读取缓存
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-
urlencoded;charset=UTF-8");
// 向请求添加 HTTP 头,POST如果有数据⼀定加加!!!!
xmlHttp.send(params);

异步 - True 或 False?
AJAX 指的是异步 JavaScript 和 XML(Asynchronous JavaScript and XML)。XMLHttpRequest 对象如果要⽤于 AJAX 的话,其 open() ⽅法的 async 参数必须设置为 true:对于 web 开发⼈员来说,发送异步请求是⼀个巨⼤的进步。很多在服务器执⾏的任务都相当费时。AJAX 出现之前,这可能会引起应⽤程序挂起或停⽌。通过 AJAX,JavaScript ⽆需等待服务器的响应,⽽是:

在等待服务器响应时执⾏其他脚本,当响应就绪后对响应进⾏处理

第三步:调⽤回调函数

所谓回调函数,就是请求在后台处理完,再返回到前台所实现的功能。

如果在上⼀步中open⽅法的第三个参数选择的是true,那么当前就是异步请求,这个时候需要写⼀个回调函数,XMLHttpRequest对象有⼀个onreadystatechange属性,这个属性返回的是⼀个匿名的⽅法,所以回调函数就在这⾥写xmlHttp.onreadystatechange=function{},function{}内部就是回调函数的内容。

在这个例⼦⾥,我们的回调函数要实现的功能就是接收后台处理后反馈给前台的数据,然后将这个数据显示到指定的div上。因为从
后台返回的数据可能是错误的,所以在回调函数中⾸先要判断后台返回的信息是否正确,如果正确才可以继续执⾏。代码如下:

1
2
3
4
5
6
7
8
9
10
11
//第三步:注册回调函数
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var obj = document.getElementById(id);
obj.innerHTML = xmlHttp.responseText;
} else {
alert("AJAX服务器返回错误!");
}
}
}

在上⾯代码中,xmlHttp.readyState是存有XMLHttpRequest 的状态。从 0 到 4 发⽣变化。0: 请求未初始化。1: 服务器连接已建⽴。2: 请求已接收。3: 请求处理中。4: 请求已完成,且响应已就绪。所以这⾥我们判断只有当xmlHttp.readyState为4的时候才可以继续执⾏。

xmlHttp.status是服务器返回的结果,其中200代表正确。404代表未找到⻚⾯,所以这⾥我们判断只有当xmlHttp.status等于200的时候才可以继续执⾏。

1
var obj = document.getElementById(id);obj.innerHTML = xmlHttp.responseText;

这段代码就是回调函数的核⼼内容,就是获取后台返回的数据,然后将这个数据赋值给id为testid的div。xmlHttp对象有两个属性都可以获取后台返回的数据,分别是:responseText和responseXML,其中responseText是⽤来获得字符串形式的响应数据,responseXML是⽤来获得 XML 形式的响应数据。⾄于选择哪⼀个是取决于后台给返回的数据的,这个例⼦⾥我们只是显示⼀条字符串数据所以选择
的是responseText。responseXML将会在以后的例⼦中介绍。

AJAX状态值与状态码区别

AJAX状态值是指,运⾏AJAX所经历过的⼏种状态,⽆论访问是否成功都将响应的步骤,可以理解成为AJAX运⾏步骤。如:正在发送,正在响应等,由AJAX对象与服务器交互时所得;使⽤“ajax.readyState”获得。(由数字1~4单位数字组成)

AJAX状态码是指,⽆论AJAX访问是否成功,由HTTP协议根据所提交的信息,服务器所返回的HTTP头信息代码,该信息使⽤“ajax.status”所获得;(由数字1XX,2XX三位数字组成,详细查看RFC)这就是我们在使⽤AJAX时为什么采⽤下⾯的⽅式判断所获得的信息是否正确的原因。

1
if(ajax.readyState == 4 && ajax.status == 200) {。。。。);}
  • AJAX运⾏步骤与状态值说明:

    在AJAX实际运⾏当中,对于访问XMLHttpRequest(XHR)时并不是⼀次完成的,⽽是分别经历了多种状态后取得的结果,对于这种状态在AJAX中共有5种,分别是:

    0 - (未初始化)还没有调⽤send()⽅法
    1 - (载⼊)已调⽤send()⽅法,正在发送请求
    2 - (载⼊完成)send()⽅法执⾏完成,
    3 - (交互)正在解析响应内容
    4 - (完成)响应内容解析完成,可以在客户端调⽤了

    对于上⾯的状态,其中“0”状态是在定义后⾃动具有的状态值,⽽对于成功访问的状态(得到信息)我们⼤多数采⽤“4”进⾏判断。
    AJAX状态码分为5类
    1:请求收到,继续处理
    2:操作成功收到,分析、接受
    3:完成此请求必须进⼀步处理
    4:请求包含⼀个错误语法或不能完成
    5:服务器执⾏⼀个完全有效请求失败

    再具体就如下:
    100——客户必须继续发出请求
    101——客户要求服务器根据请求转换HTTP协议版本
    200——交易成功
    201——提示知道新⽂件的URL
    202——接受和处理、但处理未完成
    203——返回信息不确定或不完整
    204——请求收到,但返回信息为空
    205——服务器完成了请求,⽤户代理必须复位当前已经浏览过的⽂件
    206——服务器已经完成了部分⽤户的GET请求
    300——请求的资源可在多处得到
    301——删除请求数据
    302——在其他地址发现了请求数据
    303——建议客户访问其他URL或访问⽅式
    304——客户端已经执⾏了GET,但⽂件未变化
    305——请求的资源必须从服务器指定的地址得到
    306——前⼀版本HTTP中使⽤的代码,现⾏版本中不再使⽤
    307——申明请求的资源临时性删除
    400——错误请求,如语法错误
    401——请求授权失败
    402——保留有效ChargeTo头响应
    403——请求不允许
    404——没有发现⽂件、查询或URl
    405——⽤户在Request-Line字段定义的⽅法不允许
    406——根据⽤户发送的Accept拖,请求资源不可访问
    407——类似401,⽤户必须⾸先在代理服务器上得到授权
    408——客户端没有在⽤户指定的饿时间内完成请求
    409——对当前资源状态,请求不能完成
    410——服务器上不再有此资源且⽆进⼀步的参考地址

    411——服务器拒绝⽤户定义的Content-Length属性请求
    412——⼀个或多个请求头字段在当前请求中错误
    413——请求的资源⼤于服务器允许的⼤⼩
    414——请求的资源URL⻓于服务器允许的⻓度
    415——请求资源不⽀持请求项⽬格式
    416——请求中包含Range请求头字段,在当前请求资源范围内没有range指示值,请求也不包含If-Range请求头字段
    417——服务器不满⾜请求Expect头字段指定的期望值,如果是代理服务器,可能是下⼀级服务器不能满⾜请求
    500——服务器产⽣内部错误
    501——服务器不⽀持请求的函数
    502——服务器暂时不可⽤,有时是为了防⽌发⽣系统过载
    503——服务器过载或暂停维修
    504——关⼝过载,服务器使⽤另⼀个关⼝或服务来响应⽤户,等待时间设定值较⻓
    505——服务器不⽀持或拒绝⽀请求头中指定的HTTP版本

7.6 jquery的ajax操作

7.6.1 ajax()⽅法

可以通过发送 HTTP请求加载远程数据,是 jQuery 最底层的 Ajax 实现,具有较⾼灵活性。
$.ajax( [settings] );

参数 settings 是$.ajax ( )⽅法的参数列表,⽤于配置 Ajax 请求的键值对集合;

1
2
3
4
5
6
7
8
$.ajax({
url:请求地址,
type:"get | post | put | delete " 默认是get,
data:请求参数 {"id":"123","pwd":"123456"},
dataType:请求数据类型"html | text | json | xml | script | jsonp ",
success:function(data,dataTextStatus,jqxhr){ },//请求成功时
error:function(jqxhr,textStatus,error)//请求失败时
})

7.6.2 get() 方法

通过远程 HTTP GET 请求载⼊信息。这是⼀个简单的 GET 请求功能以取代复杂 $.ajax 。

1
2
3
$.get(url,data,function(result) {
//省略将服务器返回的数据显示到⻚⾯的代码
});

url:请求的路径
data:发送的数据
success:成功函数
datatype 返回的数据

7.6.3 post() 方法

1
2
3
$.post(url,data,function(result) {
//省略将服务器返回的数据显示到⻚⾯的代码
});

url:请求的路径
data:发送的数据
success:成功函数
datatype 返回的数据

8. JSON

java基础中的json内容:第11章

JSON (JavaScript Object Notation) 是⼀种轻量级的数据交换格式。 易于⼈阅读和编写。同时也易于机器解析和⽣成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition -December 1999的⼀个⼦集。 JSON采⽤完全独⽴于语⾔的⽂本格式,但是也使⽤了类似于C语⾔家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语⾔。

8.1 JSON对象定义和使用

1
2
3
4
5
6
7
var 变量名 = {
“key” : value , // Number类型
“key2” : “value” , // 字符串类型
“key3” : [] , // 数组类型
“key4” : {}, // json 对象类型
“key5” : [{},{}] // json 数组
};

JSON对象的访问:

json对象,顾名思义,就知道它是⼀个对象。⾥⾯的key就是对象的属性。我们要访问⼀个对象的属性,只需要使⽤[对象名.属性名]的⽅式访问即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<script type="text/javascript">
// json的定义
var jsons = {
"key1":"abc", // 字符串类型
"key2":1234, // Number
"key3":[1234,"21341","53"], // 数组
"key4":{ // json类型
"key4_1" : 12,
"key4_2" : "kkk"
},
"key5":[{ // json数组
"key5_1_1" : 12,
"key5_1_2" : "abc"
},{
"key5_2_1" : 41,
"key5_2_2" : "bbj"
}]
};
// 访问json的属性
alert(jsons.key1); // "abc"
// 访问json的数组属性
alert(jsons.key3[1]); // "21341"
// 访问json的json属性
alert(jsons.key4.key4_1);//12
// 访问json的json数组
alert(jsons.key5[0].key5_1_2);//"abc"
</script>

8.2 JSON在java中的使⽤(重要)

我们要使⽤json和java中使⽤,我们需要使⽤到⼀个第三⽅的包。它就是

image-20210424132756139

java对象和json之间的转换

  • 单个对象或map集合
    java->json:

    1
    2
    3
    4
    5
    Users user2=new Users();
    user2.setUsername("李四");
    user2.setPassword("abc");
    user2.setAge(20);
    JSONObject obj=JSONObject.fromObject(user);//obj就是json格式的

    json->java:

    1
    2
    3
    String str="{'username':'李四','password':'admin','age':19}";
    JSONObject json=JSONObject.fromObject(str);
    Users user=(Users)JSONObject.toBean(json,Users.class);
  • 对象集合和json的转换

    java集合->json数组

    1
    2
    3
    4
    List list=new ArrayList();
    list.add("dd");
    list.add("aa");
    JSONArray obj=JSONArray.fromObject(list);//set也是这么转

    json数组->java数组

    1
    2
    3
    4
    String str2="[{'age':20,'password':'abc','username':'李四'},
    {'age':10,'password':'adb','username':'张三'}]";
    JSONArray json2=JSONArray.fromObject(str2);
    Object[] obj=(Object[])JSONArray.toArray(json2,Users.class);

    json数组->java集合

    1
    2
    3
    4
    5
    String str3="[{'age':20,'password':'abc','username':'李四'},
    {'age':10,'password':'adb','username':'展示⼲'}]";
    JSONArray json3=JSONArray.fromObject(str3);
    //默认转换成ArrayList
    List<Users> list=(List<Users>) JSONArray.toCollection(json3,Users.class);

Ajax和json总结

配合实现用户检测和信息填充

在MVC作业中,实现了将数据库信息作为表格呈现在jsp中

在此基础上,将Ajax实现页面的局部刷新(非跳转刷新),同时用json格式替换xml格式作为数据的传输格式

bean层

1
2
3
4
5
Student{
stuid;stuname;age;sex;
//有参构造;
//无参构造;
}

dao层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//接口:
public interface StudentDao {

//定义操作数据库的方法
public List<Student> getall();
public Student findByName(String name);
}
//实现类:
public class StudentDaoImpl extends DruidUtil implements StudentDao {
@Override
//MVC获取数据库全部信息
public List<Student> getall() {
List list=new ArrayList();
Connection connection =null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
try {
connection = getConnection();
preparedStatement = connection.prepareStatement("select * from student");
resultSet = preparedStatement.executeQuery();
while(resultSet.next()){
Student student = new Student();
student.setStuid(resultSet.getInt("stuid"));
student.setStuname(resultSet.getString("stuname"));
student.setAge(resultSet.getInt("age"));
student.setSex(resultSet.getInt("sex"));
list.add(student);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(connection,preparedStatement,resultSet);
}

return list;
}
//获取响应用户名的信息
public Student findByName(String name){
System.out.println("StudentDaoImpl执行");
Student student = new Student();
Connection connection =null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
try {
connection = getConnection();
preparedStatement = connection.prepareStatement("select * from student where stuname=?");
preparedStatement.setString(1,name);
resultSet = preparedStatement.executeQuery();
while(resultSet.next()){
student.setStuid(resultSet.getInt("stuid"));
student.setStuname(resultSet.getString("stuname"));
student.setAge(resultSet.getInt("age"));
student.setSex(resultSet.getInt("sex"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(connection,preparedStatement,resultSet);
}
return student;
}
}

service层

接收沟通数据库的dao层的结果,交给沟通前端的servlet层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//接口
public interface StudentService {
//查询全部
public List<Student> getall();
public Student findByName(String name);
}
//实现类
public class StudentServiceImpl implements StudentService {
private StudentDao studentDao=new StudentDaoImpl();
@Override
public List<Student> getall() {
return studentDao.getall();
}
public Student findByName(String name){
System.out.println("StudentServiceImpl执行");
return studentDao.findByName(name);}
}

servlet层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@WebServlet(urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String stuname = req.getParameter("stuname");
StudentServiceImpl studentService = new StudentServiceImpl();
Student student = studentService.findByName(stuname);
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
// Ajax中的dataType为“JSON”,响应信息的格式就必须为JSON
if(student.getAge()==null){
//将需要的内容改为JSON格式的字符串,然后再转为JSON
String a = "{\"stuname\":\"notexist\"}";
JSONObject jsonObject = JSONObject.fromObject(a);
writer.println(jsonObject);
}else{
JSONObject jsonObject = JSONObject.fromObject(student);
writer.print(jsonObject);
}
}
}

前端页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
$(function(){
$("#stuname").blur(function(){
var name = $(this).val();
//jquery实现Ajax
$.post("/login","stuname="+name,function(rs){
//转换成可以处理的js!!!!
rs=eval("("+rs+")");
//字符串是否相同的判断!!!!
if("notexist"===rs.stuname){
$("#rs").html(rs.stuname);
}else{
$("#stuname").val(rs.stuname);
$("#age").val(rs.age);
$("#sex").val(rs.sex===1?'男':'女');
}
//此时的rs是json格式的对象

});
});
})
</script>
<body>
<a href="getstus">查询学生列表</a><br>
用户名:<input type="text" id="stuname"><span id="rs"></span><br>
年龄:<input type="text" id="age"><br>
性别:<input type="text" id="sex"><br>
<button>注册</button>
<button>登录</button>
</body>
</html>

9. 文件的上传的下载

  1. 将jar包添加到项目中:smartupload.jar

  2. 准备上传的页面

    1
    2
    3
    4
    5
    <form action="toUpload" method="post" enctype="multipart/form-data" >
    书名:<input type="text" name="bookName"/><br>
    图片:<input type="file" name="自定义名称"/><br>
    <input type="submit" value="提交"/>
    </form>

    注意

    • form标签中要添加enctype属性
    • 提交方式必须是post
  3. 开始获取数据,保存文件(上传)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    @WebServlet(urlPatterns = "/uploadtest")
    public class UpLoadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    try {
    //1.创建上传文件的对象
    SmartUpload smartUpLoad = new SmartUpload();
    //2.获得pageContext对象,初始化上传操作
    JspFactory factory=JspFactory.getDefaultFactory();
    /**
    * 参数1:servlet对象
    * 参数2:、3:request和response对象
    * 参数4:字符串,指定跳转失败的页面
    * 参数5:是否使用session
    * 参数6:缓冲区,单位字节
    * 参数7:缓冲区满了是否自动添加到输出流
    */
    PageContext pagecontext=factory.getPageContext(this, req,resp,null,false,1024,true);
    smartUpLoad.initialize(pagecontext);
    //3 设置编码
    smartUpLoad.setCharset("utf-8");
    //4 上传
    smartUpLoad.upload();
    //4-1此时如果表单中有其他数据时,不能通过request直接获取,需要通过SmartUpload对象获取
    //并且该代码要在SmartUpload操作完成后添加
    String name=smartUpLoad.getRequest().getParameter("uname");
    System.out.println("uname="+name);
    //4-2通过上传服务器的方式得到文件的基本信息
    File file = smartUpLoad.getFiles().getFile(0);
    String filename=file.getFileName();
    String type=file.getContentType();
    System.out.println("type="+type);
    //指定上传路径
    String upLoadPath="/uploadfiles/"+filename;
    //保存到指定位置
    file.saveAs(upLoadPath,File.SAVEAS_VIRTUAL);
    //跳转到成功页面
    req.setAttribute("filename",filename);
    req.getRequestDispatcher("success.jsp").forward(req,resp);
    } catch (SmartUploadException e) {
    e.printStackTrace();
    }
    }
    }
    **注意:斜杠方向:/**
  4. 下载

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String filename = req.getParameter("filename");
    String path = "/uploadfiles/"+filename;
    //设置响应的头信息和响应类型
    resp.setContentType("application/octet-stream");
    //attachment 告诉浏览器以附件的方式下载文件(弹出下载框)
    filename= URLEncoder.encode(filename,"utf-8");
    resp.addHeader("Content-Disposition","attachment;filename="+filename);
    //跳转页面
    req.getRequestDispatcher(path).forward(req,resp);
    //清空缓冲区:将服务端缓冲区的文件内容,立即权并不传送给客户端
    resp.flushBuffer();
    }

PageContext pagecontext=factory.getPageContext(this, req,resp,null,false,1024,true);中各参数的含义

image-20210424234755898

常用方法:

image-20210424234852274