JavaWeb

后端部分

1.Tomcat服务器

1.1 背景了解:

1.1.1 Web资源分类:

静态资源:html、css、js、txt、mp4视频、jpg图片等
动态资源:jsp页面、servlet程序、asp、php等

1.2 Tomcat服务器和servlet程序版本的对应关系

servlet版本2.5之前(目前市面上用的最多的版本)(XML配置)
servlet版本3.0之后(注解版本)

1.3 修改Tomcat默认端口号(8080)

Tomcat目录下的conf文件夹————>server.xml文件————>Connector标签里面有个port属性(1-65535)
修改完后重启Tomcat服务器后生效
http协议默认的端口号:80

1.4 Tomcat服务器部署方式

1.4.1 方式一

①在Tomcat目录下的webapps中新建工程文件夹
②在文件夹中拷贝IDEA中的工程文件(pages、static以及html等文件)
③在浏览器地址界面,输入地址http://localhost:8080/工程文件夹名/想要访问的文件……

1.4.2 方式二

①在Tomcat目录下的conf文件夹————>Catalina文件夹————>localhost文件夹————>新建工程名称.xml文件(可以直接新建一个txt文件,然后直接改后缀名为xml文件)
②在xml文件中编辑————><Context path="/自定义的xml文件名" docBase="Web工程文件存放的目录"/>

1.5 Tomcat默认访问的工程和默认访问的资源

在浏览器地址栏中输入:http://ip:port/  没有工程名的时候,默认访问的是ROOT工程
在浏览器地址栏中输入:http://ip:port/工程名/  有工程名但是没有资源名的时候默认访问index.html页面

1.6 IDEA与Tomcat服务器整合

①File——>Settings——>Build,Execution,Deployment——>Application Servers——>点击“+”,选择Tomcat Server
②选择Tomcat服务器的安装目录位置,可通过浏览配置
③工程中新建New Module(Java Enterprise)时选择Application Server中选择配置的服务器

1.7 新建动态Web工程

①New Module
②Java Enterprise——>Tomcat服务器版本——>勾选Web Application,默认勾选Create web.xml
③输入模块名,点击finish完成创建Web目录结构解析:
①src 存放自己编写的java源代码
②web 专门用来存放web工程的资源文件,如:html界面,css文件,js文件等
③WEB-INF 受到服务器保护的目录,浏览器无法直接访问到此目录的内容
④一般在WEB-INF下新建一个lib文件夹用来存放jar包(IDEA中还需要自己配置导包)
⑤web.xml 是整个动态web工程的配置部署描述文件,可以在这里配置很多web工程的组建,比如:Servlet程序、Filter过滤器、Listener监听器,Session超时等等

1.8 Tomcat添加第三方jar包

方式一:可以通过与IDEA中类似的方法进行jar包的导入,即复制粘贴,右键add为library
方式二:
①File——>Project Structure——>Libraries——>“+”——>Java——>选择想要添加的jar包目录,创建一个类库,之后选择要给哪个模块使用,之后可以改类库的名字方便管理——>Apply
②Artifacts——>选择对应的类库——>Fix(Add xxx to artifact)

1.9 IDEA中如何部署web工程到Tomcat上运行

①建议修改web工程对应的Tomcat运行实例名称:点击页面上方运行按钮左边的下拉多选框,选择Edit Configurations...,之后建议将名称改成与当前web工程名称一致,之后Apply
②在Configurations中点击Deployment,通过"+"将需要部署的web工程添加到Tomcat运行实例中,"—"移除不需要的web工程,下面的Application context是默认生成的工程路径(这一步的主要目的是确认Tomcat实例中有你要部署运行的web工程)
③此时Configurations中的Server下,有个URL即启动Tomcat运行实例时,默认打开访问的地址
④此时点击运行按钮即可部署web工程到Tomcat上运行,当进行了修改之后,可以点击原先位置的update进行重新部署

1.10 其他细节说明

①一般Configurations中的Deployment中生成的默认工程路径会修改为与Web工程名称一致
②可以在Configurations中的Server中修改端口号,默认是8080
③可以在Configurations中的Server中的Open Browser修改运行使用的浏览器
④修改“资源热部署”——即页面修改后刷新界面修改就直接生效,在Configurations中的Server中的VM options下的On frame deactivation,将Do nothing修改为Update classes and resources,点击Apply生效,上面一栏的On 'Update' action中设置默认的那个弯箭头标志执行的操作类型,可以修改为重启服务器之类的操作

2.Servlet程序

2.1 什么是servlet?

①Servlet是JavaEE规范之一,就是接口
②Servlet是JavaWeb三大组件之一,三大组件分别是:Servlet程序,Filter过滤器、Listener监听器。
③Servlet是运行在服务器上的小程序,他可以接收客户端发来的请求并响应数据给客户端

2.2 Servlet程序的实现

①编写一个类去实现Servlet接口(Web工程中src文件夹新建一个Package,再新建class implements Servlet,通过ALT + insert——>Implement Methods重点关注service方法)
②实现Service方法,处理请求,并响应数据(如最简单的System.out.println("HelloServlet被访问了"))
③到web.xml中去配置servlet程序的访问地址添加<servlet>标签,包括servlet-name(起别名)以及servlet-class(对应的java类)添加对应的<servlet-mapping>标签,包括servlet-name(配置的url给哪个Servlet程序使用,和上面的对应)以及url-parttern(/xxx)注意:
①servlet-class的类不要从com.xxx.xxx.xxx开始敲,直接输入类名就可以,否则无法对应到你想要的对应的那个java类,具体原因我也不清楚
②url-parttern中/xxx需要与java类有逻辑上的对应关系,否则可读性非常差

2.3 servlet的生命周期

①servlet构造器方法
②init初始化方法
第一次访问的时候调用,单例
③service方法
每次刷新都会重新调用该方法
④destroy销毁方法
销毁的时候调用该方法

2.4 servlet请求的分发处理(get和post请求)

get请求和post请求执行的操作不一样,但是service函数只有一个,因此需要判断请求类型区别对待,借助getMethod()方法①ServletRequest的子类可以调用getMethod()方法,入口参数类型为ServletRequest类型,因此需要先通过其子类实例化:HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest
②String method = httpServletRequest.getMethod();
此外由于get和post执行的操作可能不止一个,在通过getMethod方法获取到请求类型后,通常在外面通过自定义函数的方式,进行封装,之后再进行调用。

2.5 通过继承HttpServlet实现servlet接口

一般开发过程中不直接从Servlet接口实现,而是从他的子类进行实现
①编写一个类去继承HttpServlet类(注意这里的是类不是接口)
②根据业务需要重写goGet或doPost方法(注意需要删除第一行的super.……否则会调用父类中的方法,网页会给出405的错误提示)
③到web.xml中配置Servlet程序的访问地址

2.6 IDEA直接创建Servlet程序

①src包右键New——>Servlet(如果没有再检查一下依赖)
②填写类名、包名、全包名自动生成注意:
①去选下面的勾选项,不使用3.0以上版本的注解
②包名是从点击的resourceRoot开始算的,即从右键选中的文件夹开始算的,如果之前没有该包名会新建一个对应的包
③新建完成后仍需要在web.xml中配置地址

2.7 Servlet继承关系

Servlet————>接口,负责定义Servlet程序的访问规范
GenericServlet——>作为类,实现了Servlet接口,做了很多空实现,并持有一个ServletConfig类的引用
HttpServlet——>抽象类实现了service方法,实现了请求的分发处理,负责抛异常,提示不支持Get/Post请求
自定义的Servlet——>重写doGet和doPost方法

2.8 ServletConfig类

从名称上看就知道是Servlet程序的配置信息类
(在继承自Servlet的类中alter+insert即可快速引入接口函数,其中Init函数的入口参数中即有此servletConfig)
①可以获取Servlet程序的别名servlet-name的值servletConfig.getServletName();
②获取初始化init-parama.在web.xml中对应的<servlet>标签内,可定义<init-param>键值对,分别配置参数名和参数值b.通过servletConfig.getInitParameter(name:"xxx")获取对应的参数的值
③获取ServletContext对象servletConfig.getServletContext();获取ServletContext对象补充说明:
①Servlet程序和ServletConfig对象都是由Tomcat服务器创建,我们使用即可
②Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象,因此每次获取ServletConfig对象的时候智能获取自身的,不能获取别的。getServletConfig()也能获取对象,但是获取到的ServletConfig对象是GenericServlet类中的,如果继承的类中重写Init()方法,需要super.init(config),否则会导致父类中的this.config = config操作丢失而引起子类中的空指针异常。

2.9 ServletContext对象

①是一个接口,表示上下文对象
②一个Web工程,只有一个ServletContext对象实例
③是一个域对象:可以像Map一样存取数据的对象,这里的域指的是存取数据的操作范围
④ServletContext会在Web工程部署启动的时候创建,在web工程停止的时候销毁Map:存数据用put(),取数据用get(),删除数据用remove()
域对象:存数据用setAttribute(),取数据用getAttribute(),删除数据用removeAttribute()四个作用:
①获取web.xml中配置的上下文参数context-param(属于整个Web工程的)ServletContext context = getServletConfig().getServletContext();context.getInitParameter(name:"xxxx")
②获取当前的工程路径,格式:/工程路径context.getContextPath();
③获取工程部署后在服务器硬盘上的绝对路径context.getRealPath("/")(/被浏览器解析为http://ip:端口号/工程名/ 映射到IDEA代码的web目录<br/>)
④像Map一样存储数据context.setAttribute(name:"xxx",object:"xxxx");context.getAttribute(name:"xxx");存储范围为整个web工程

2.10 Http协议

①GET请求a.请求行请求的方式:                    GET请求的资源路径:[+?+请求参数]请求的协议的版本号              HTTP/1.1b.请求头key:value组成,不同的键值对表示不同的含义
浏览器F12打开开发者调试界面,在提交表单内容的时候可以观察到请求行和请求头的内容,如2.11所述:②POST请求a.请求行请求的方式:                    POST请求的资源路径:[+?+请求参数]请求的协议的版本号              HTTP/1.1b.请求头key:value组成,不同的键值对表示不同的含义空行c.请求体即发送给服务器的数据

2.11 常用的请求头类型

①Accept: text/html, application/xhtml+xml, image/jxr, */*(表示客户端可以接收的数据类型)
②Accept-Encoding: gzip, deflate(客户端可以接收的数据编码(压缩)格式)
③Accept-Language: zh-CN(客户端可以接收的语言类型)
④Connection: Keep-Alive(告诉当前服务器当前请求连接如何处理,还有一种为closed)
⑤Host: localhost:8080(请求的服务器IP和端口号)
⑥Referer: http://localhost:8080/servlet/test.html(当前请求是从哪里产生的)
⑦User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko(浏览器的信息)
⑧Content-Type:表示发送的数据类型application/x-www-form-urlencoded表示提交的数据格式是:name=value&name=value,然后对其进行url编码url编码就是把非英文的内容转换为:%xx%xxmultipart/form-data表示以多段的形式提交数据给服务器(以流的形式提交,用于上传)
⑨Content-Length:表示发送的数据的长度
⑩Cache-Control:表示如何控制缓存(no-cache不缓存)

2.12 GET请求和POST请求怎么区分?

GET请求:①form标签,method="get"②a标签③link标签引入css④Script标签引入js文件⑤img标签引入图片⑥iframe引入html页面⑦在浏览器地址栏中输入地址后敲回车
POST请求:①form标签 method="post"

2.13 响应的Http协议介绍

a.响应行响应的协议和版本号  HTTP/1.1响应状态码          200响应状态描述符       OK
b.响应头key:value         不同的响应头有其不同的含义空行
c.响应体回传给客户端的数据

2.14 常见的响应状态码

200 表示请求成功
302 表示请求重定向
404 表示请求服务器已经收到了,但是你要的数据不存在(请求地址错误)
500 表示服务器已经收到请求,但是服务器内部错误(代码错误)

2.15 MIME类型说明(HTTP协议中的数据类型)

英文全称是:Mutipurpose Internet Mail Extensions 多功能Internet邮件扩充服务
类型格式:大类型/小类型
超文本标记语言文本  .html,.htm  text/html
普通文本           .txt        text/plain
RTF文本           .rtf        application/rtf(苹果和linux操作系统上常见,windows几乎不用)
GIF图形           .gif         image/gif
JPEG图形          .jpeg,.jpg   image/jpeg
au声音文件         .au         audio/basic
MIDI音乐文件       mid,midi    audio/midi,audio/x-midi
RealAudio音乐文件  .ra,.ram    audio/x-pn-realaudio
MPEG文件          .mpg,.mpeg   video/mpeg
AVI文件           .avi         video/x-msvideo
GZIP文件          .gz          application/x-gzip
TAR文件           .tar         application/x-tar

2.16 HttpServletRequest类

每次只要有请求进入Tomcat服务器,Tomcat服务器就回吧请求过来的HTTP协议信息解析好封装到Request对象中,然后传递到service方法(doGet和doPost)中供我们使用,我们可以通过HttpServletRequest对象获取到所有请求的信息常用方法有:
①getRequestURI()              获取请求的资源路径
②getRequestURL()              获取请求的统一资源定位符(绝对路径)
③getRemoteHost()              获取客户端的ip地址
④getHeader()                  获取请求头
⑤getParameter()               获取请求参数
⑥getParameterValues()         获取请求的参数(多个值的时候使用)
⑦getMethod()                  获取请求的方式(GET还是POST)
⑧setAttribute(key,value)      设置域数据
⑨getAttribute()               获取域数据
⑩getRequestDispatcher()       获取请求转发对象继承自HttpServlet类的doGet和doPost方法的入口参数中有HTTPServletRequest对象req
req.getRequestURI() => /工程名/资源路径
req.getRequestURL() => http://ip:端口号 + URI
req.getRemoteHost() => 127.0.0.1即localhost,如果使用真实的ip地址访问,得到的就是真实的客户端ip地址
req.getHeader(name:"User-Agent") => 可以获取发送请求的浏览器参数
req.getParameter(name:"xxx") => 获取参数(用String接收即可)
req.getParameterValues(name:"xxx") => 获取多个参数(用String[]接收,打印时Arrays.asList(xxx))注意:
post请求在提交表单的时候会出现中文乱码的问题,解决办法:在获取请求参数之前,通过setCharacterEncoding("UTF-8")方法解决乱码问题。必须在获取任何请求参数之前使用,在获取任何一个参数之后再调用就会失效。

2.17 请求的转发(servlet1 => servlet2)

服务器收到请求后,从一个资源跳转到另一个资源的操作
流程:req.getParameter(name:"……")(检查资料) => req.setAttribute(name:"xxx",value:"xxx")(盖章) => req.getRequestDispatcher("/servlert2")(问路) => xxxDispatcher.forward(req,resp)(跳转)特点:
①浏览器地址栏没有变化
②他们是一次请求
③他们共享req域中的数据(Attribute)
④可以转发到WEB-INF目录下(直接访问的话浏览器禁止访问)
⑤是否可以访问工程以外的资源?不能!

2.18 base标签的作用

用于设置页面相对路径工作时参照的地址使用base标签的原因:
使用a标签进行跳转的时候"/a/b/c.html",通过"../../index.html"跳转回去没有问题,当使用请求转发的方式进行跳转的时候跳转过去没问题,通过servlet-mapping实现跳转。但是跳转回来的时候由于../../是相对路径,与浏览器当前的地址有关,回退到错误的地址导致跳转回来失败,这时候即可以使用base标签使之从base标签开始使用相对路径跳转。一般base标签放在title标签下面,如:
<base href="http://localhost:8080/07_servlet/a/b/c.html"> 最后面的"c.html"可以省略,但是/不能省略,不省略才是目录。

2.19 "/"不同的解析结果

如果被浏览器解析,得到的地址是:http://ip:端口号/<a href="/">斜杠</a>
如果被服务器解析,得到的地址是:http://ip:port/工程路径①<url-pattern>/servlet1</url-pattern>②servletContext.getRealPath("/")③request.getRequestDispatcher("/")
特殊情况:response.sendRedict("/") => 这是把斜杠发送给浏览器解析,得到的是浏览器解析的结果 => 请求重定向

2.20 HttpServletResponse类

与HttpServletRequest类相似,每次请求进来,Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用,通过设置该对象设置返回给客户端的信息两个输出流:
字节流    getOutputStream()    常用于下载(传递二进制数据)
字符流    getWriter()          常用于回传字符串(常用)
两个流只能二选一,否则会报错默认响应的编码为ISO-8859-1,此时解析服务器返回给客户端的中文会出现乱码问题,解决办法:
方法一:
①通过resp.setCharacterEncoding("UTF-8")设置服务器编码为UTF-8
②通过响应头设置客户端的浏览器也使用UTF-8字符集解析页面:resp.setHeader(name:"content-Type",value:"text/html;charset=UTF-8")
需要同时设置服务器和浏览器的字符集,少一个都不可以
方法二:
//这一行代码会同时设置服务器和客户端都使用UTF-8字符集,还设置了响应头
resp.setContentType("text/html;charset=UTF-8")
注意:方法二一定要在获取流对象之前调用才有效

2.21 请求重定向

是指客户端给服务器发请求,然后服务器告诉客户端,给你一下新地址,你去新地址访问。(因为之前的地址可能已经被废弃)
①告知客户端此地址已搬迁 ==>> 响应码 302
②并且告知新的地址      ==>>  响应头 Location方法一:
resp.setStatus(302) ==>>  表示重定向
resp.setHeader(name:"Location",value:"新地址") ==>>  设置响应头,告知新地址
方法二:(推荐使用)
resp.setRedirect(location:"新地址")特点:
①地址栏会发生变化
②两次请求
③不共享req的Attribute域数据
④不能访问WEB-INF下的资源
⑤可以访问工程外的资源(如访问百度)

2.22 JavaEE三层架构(SSH和SSM框架的由来)

①Web层/视图展现层 ==>> Sevlet程序、SpringMVCa.获取请求参数,封装成Bean对象b.调用service层处理业务c.响应数据给客户端、请求转发、重定向
②Service业务层 ==>> Spring框架a.处理业务逻辑b.调用持久层保存到数据库
③Dao持久层 ==>>  Jdbc、DbUtils、Mybatis、HibernateDao持久层,只负责跟数据库交互,执行CRUD操作分层的目的是为了实现解耦,降低代码的耦合度,方便项目后期的维护和升级①Web层  com.atguigu.web/servlet/controller②Service层  com.atguigu.service Service接口包  +  com.atguigu.service.impl Service接口实现类③Dao层  com.atguigu.dao Dao接口包  +  com.atguigu.dao.impl Dao接口实现类④实体Bean对象  com.atguigu.pojo/entity/domain/bean  JavaBean类⑤测试包  com.atguigu.test/junit⑥工具类包  com.atguigu.utils

2.23 书城项目第二阶段

①创建项目所需的数据库和表
②编写数据库表所对应的JavaBean对象(属性、getter&setter、toString、Structure)
③编写工具类JdbcUtils
④编写BaseDao
⑤编写UserDao和测试 => 接口注意:
①在编写工具类JdbcUtils时,需要用到jdbc.properties配置文件,尚硅谷视频教程中是放在src目录下的,但是由于用的IDEA版本不同,构建的项目结构也有所不同,查CSDN后发现,只有将jdbc.properties文件放在/src/main/resources里面才能使getResourceAsStream()方法读取到,否则就会报空指针异常,据CSDN上反映,后面将工程部署在web上时可能会出现新找不到文件的问题。
根本原因是需要将存放property配置文件的文件夹右键mark directory as resource root

3.JSP相关

虽然有很多有过开发经验的工程师都建议,尽量不要使用JSP,但是,作为物联网领域学习的新人来说,还是要了解一下JSP的,不然遇到老项目维护用的是JSP怎么办呢,最关键的是先学习整套流程,等到自己真切体会到JSP的不便之处的时候相信才是真的懂JSP了,这个时候再去学新技术,如themeleaf或者VUE等可能才会更加深刻。

3.1 JSP

全称:java server pages
主要作用是代替Servlet程序回传html页面的数据
servlet回传html页面数据是一件非常繁琐的事情,开发和维护的成本都极高
JSP的本质还是Servlet程序,Tomcat会将JSP页面翻译成Java源文件,将其编译成为.class字节码程序

3.2 JSP的头部page指令

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
①language属性     表示jsp翻译之后是什么语言文件,目前只支持java
②contentType属性  表示jsp返回的数据类型是什么,也是源码中response。setContentType()参数值
③pageEncoding     表示当前jsp页面文件本身的字符集
④import           跟java源代码中一样,用于导包,⑤autoFlush        设置当out输出流缓冲区满了之后,是否自动刷新冲级区。默认值是true。
⑥buffer           设置out缓冲区的大小,默认是8kb⑦errorPage属性    设置当jsp页面运行出错时,自动跳转去的错误页面路径⑧isErrorPage      设置当前jsp页面是否是错误信息页面,默认是false,如果是true可以⑨session          设置访问当前jsp页面,是否会创建HttpSession对象,默认是true
⑩extend           设置jsp翻译出来的java类默认继承值

3.3 声明脚本

<%! xxx %>
①声明类属性<%!private Integer id;private static Map<String,Object> map;%>
②声明static静态代码块<%!static {map = new Hashmap<String,Object>();map.put("key1","value1");map.put("key2","value2");}%>
③声明类方法<%!public int abc(){return 12;}%>
④声明内部类<%!public static class A(){private Integer id = 12;}%>

3.4 表达式脚本

<%= xxx %>
特点:
①所有的表达式脚本都会被翻译到_jspService()中
②表达式脚本都会被翻译成为out.print()输出到页面上
③由于表达式脚本翻译的内容都在_jspService()方法中,所以在_jspService()方法中的对象都可以直接使用
④表达式脚本中的表达式不能以分号结尾
如:
<%=12%>
<%=12.12%>
<%="xxx"%>
<%=map%>
<%=request.getParameter("username")%>

3.5 代码脚本(思考为什么需要将for循环代码分开写)

<%for(int j = 0; j < 10; j++){
%>
<%   System.out.println(j)}
%>

练习一:输出九九乘法口诀:
练习二:输出有10个学生的信息表:

3.6 jsp中的三种注释

①html注释  <!-- xxx -->
②java注释  //xxx 或 /* xxx */
③jsp注释   <%-- xxx --%>
在代码脚本中使用java注释方式,而jsp注释可以用于jsp页面的所有位置

3.7 jsp的九大内置对象

request      请求对象
response     响应对象
pageContext  jsp的上下文对象
session      会话对象
application  ServletContext对象
config       ServletConfig对象
out          jsp输出流对象
page         指向当前jsp的对象
exception    异常对象

3.8 jsp四大域对象

pageContext  (PageContextImpl类)      当前jsp页面范围内有效
request      (HttpServletRequest类)   一次请求内有效
session      (HttpSession类)          一个会话范围内有效(打开浏览器访问服务器,直到关闭浏览器)
application  (ServletContext类)       整个web工程范围内都有效(只要web工程不停止,数据都在)四个域都可以存储数据,在使用上有优先顺序,依次从小到大读取
pageContext => request => session => application


由于jsp翻译之后,底层源代码都是使用out来进行输出,所以在一般情况下,在jsp页面统一使用out来进行输出,避免打乱页面输出内容的顺序(这是针对上图中response。getWrite().write(“xxx”)也可以输出的层面来说的),即在getWriter.write()和out之间选out。

out.write()  输出字符串没问题
out.print()  输出任意数据都没有问题(都转换为字符串后调用的write输出)
在使用out时,统一使用out.print()来进行输出

3.9 静态包含与动态包含

<%@ include file=""%> 就是静态包含
file属性指定要包含的jsp页面的路径
地址中第一个斜杠 / 表示为 http://ip:port/工程路径/  映射到代码的web目录静态包含的特点:
①静态包含不会翻译被包含的jsp页面
②静态包含其实是包被包含的jsp页面的代码拷贝到包含的位置执行输出
如:
<%@ include file="/include/footer.jsp"%><jsp:include page=""></jsp:include> 这是动态包含
page属性是要包含的jsp页面的路径
动态包含也可以像静态包含一样,把被包含的内容执行输出到包含位置动态包含的特点:
①动态包含会把包含的jsp页面翻译成java代码
②动态包含底层代码使用如下的代码去调用被包含的Jsp页面执行输出JspRuntimeLibrary.include(request,response,"/include/footer.jsp",out,false);
③动态包含,可以传递参数:
如:
<jsp:include page="/include/footer.jsp"><jsp:param name="username" value="bbj"/><jsp:param name="password" value="root">
</jsp:include>
一般情况下都使用静态包含

3.10 jsp标签转发

<jsp:forword page=""></jsp:forward> 是请求转发标签,功能是请求转发
page属性设置请求转发的路径
如:
<jsp:forward page="/scope2.jsp"></jsp:forward>

请求转发示意:(一整套下来是一次请求)

3.11 Listener监听器

JavaWeb的三大组件之一,JavaWeb的三大组件:Servlet程序、Filter过滤器、Listener监听器
Listener它是JavaEE的规范,就是接口
作用:监听某种事物的变化,通过回调函数,反馈给客户(程序)去做一些相应的处理servletContextListener可以监听ServletContext对象的创建和销毁
servletContext对象在web工程启动的时候创建,在web工程停止的时候销毁
监听到创建和销毁之后都会分别调用ServletContextListener监听器的方法反馈
步骤如下:
①编写一个类去实现ServletContextListener
②实现其两个回调方法
③到web.xml中去配置监听器

3.12 EL表达式

Expression Language 表达式语言
主要是代替jsp页面中的表达式脚本在jsp页面中进行数据的输出(因为EL表达式在输出数据的时候,要比jsp的表达式脚本要简洁很多)

<body><%request.setAttribute("key"."值");%>表达式脚本输出key的值是:<%= request.getAttribute("key1")==?null"":request.getAttribute("key1")%><br/>EL表达式输出key的值是:${key1}
</body>

以上代码段显示出了使用jsp表达式脚本和使用EL表达式写法下的复杂度对比

EL表达式的格式是:${表达式}
EL表达式在输出null值的时候,输出的是空串,jsp表达式脚本输出null值的时候,输出的是null字符串


注意:EL表达式输出的值并不是属性本身的值,而是属性对应的“读”方法的值,即使没有定义该属性,定义了该属性为名的“get”方法即可,如果是Boolean属性的则对应“is”方法

3.12.1 关系运算

3.12.2 逻辑运算
3.12.3 算数运算

3.13 empty运算

用于判断一个数据是否为空,如果为空,则输出true,不为空则输出false

①值为null值的时候,为空
②值为空串的时候,为空
③值是Object类型数组,长度为0的时候、
④list集合,元素个数为0
⑤map集合,元素个数为0

3.14 三元运算

表达式1?表达式2:表达式3
如果表达式1的值为真,返回表达式2的值,如果表达式1的值为假,返回表达式3的值

3.15 “.”运算和[]中括号运算

.运算可以输出Bean对象中某个属性的值
[]中括号运算,可以输出有序集合中某个元素的值
并且[]中括号运算,还可以输出map集合中key里含有特殊字符的key的值(即当key中含有特殊字符时,点运算不再适用,需要使用中括号运算)
如:${ map['a.a.a'] } <br>

3.16 EL表达式的11个隐含对象

pageContext        PageContextImpl          可以获取jsp九大内置对象
pageScope          Map<String,Object>       可以获取pageContext域中的数据
requestScope       Map<String,Object>       可以获取Request域中的数据
sessionScope       Map<String,Object>       可以获取Session域中的数据
applicationScope   Map<String,Object>       可以获取ServletContext域中的数据param              Map<String,String>       可以获取请求参数的信息
paramValues        Map<String,String[]>     获取多个请求参数的值的时候使用header             Map<String,String>       可以获取请求头的信息
headerValues       Map<String,String[]>     获取多个请求头值的情况cookie             Map<String,Cookie>       可以获取当前请求的CookieinitParam          Map<String,String>       可以获取在web.xml文件中配置的<context-param>上下文参数

3.16.1 EL获取四个特定域中的属性

pageScope         ==>>  pageContext域
requestScope      ==>>  Request域
sessionScope      ==>>  Session域
applicationScope  ==>>  ServletContext域
当四个域都有数据时可以通过此方式输出特定域的内容,否则会按照域的大小进行搜索

3.16.2 pageContext对象

企业中的简化写法:
<%pageContext.setAttribute("req",request);
%>
${ req.scheme }<br>

3.16.3 EL表达式其他隐含对象的使用

param&paramValues:
header&headerValues:
cookie:
initParam:
需要注意,“<”和“>”需要转换表达形式

3.17 JSTL标签库

EL表达式主要是为了替换jsp中的表达式脚本,而JSTL标签库是为了替换代码脚本

使用步骤:

①先导入JSTL标签库的jar包taglib-standard-impl-1.2.1.jartaglib-standard-spec-1.2.1.jar
②使用taglib指令引入标签库,如::<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

3.17.1 set标签

<c:set scope="page" var="abc" value="abcValue"/>相当于:域对象.setAttribute(key,value);
scope 属性设置保存到哪个域page表示PageContext域(默认值)request表示Request域session表示Session域application表示ServletContext域
var属性值设置key值是多少
value属性设置值

3.17.2 if标签(只能做单路判断)

<c:if test="${ 12! = 12 }"><h1> 12等于12 </h1>
</c:if>

3.17.3 多路判断(<c:choose><c:when><c:otherwise>)

<c:choose><c:when test="${ requestScope.height > 190 }"><h2> 小巨人 </h2></c:when>……<c:otherwise><h2> 剩下的情况 </h2></c:otherwise>
</c:choose>
注意事项:
①标签里不能使用html注释,要使用jsp注释
②when标签的父标签一定要是choose标签(即无论何时想要使用when标签做多路判断,一定要先试用choose标签)

3.17.4 forEach标签(遍历)

①遍历1到10,输出
<c:forEach begin="1" end="10" var="i"><tr><td> 第${i}行 </td></tr>
</c:forEach>
begin属性设置开始的索引
end属性设置结束的索引
var属性表示循环的变量(当前遍历到的数据)
for(int i =1; i <10; i++)②遍历Object数组
<%request.setAttribute("arr",new String[]{''18640541354","18688886666","18699998888"})
%>
<c:forEach items="${ requestScope.arr }" var="item">${ item }<br>
<c:forEach>
items表示遍历到的数据
var表示当前遍历到的数据
for(Object item:arr)③遍历Map集合
<%Map<String,Object> map = new HashMap<String,Object>();map.put("key1","value1");map.put("key2","value2");map.put("key3","value3");request.setAttribute("map",map)
%>
<c:forEach items="${ requestScope.map }" var="entry"><h1>${entry.key} = ${entry.value}</h1>
</c:forEach>
相当于:for(Map.Entry<String,Object> entry : map.entrySet()){}④遍历List集合
<%List<Student> studentList = new ArrayList<Student>();for(int i = 1;i <=10; i++){studentList.add(new Student(……))}request.setAttribute("stus",studentList);
%>
<c:forEach items="${requestScope.stus}" var="stu">${ stu }<br>
</c:forEach>属性总结:
items     表示遍历到的集合
var       表示遍历到的数据
begin     表示遍历的开始索引值
end       表示结束的索引值
step      属性表示遍历的步长值
varStatus 属性表示当前遍历到的数据的状态
其中varStatus中的状态由Java源码中的接口LoopTagStatus定义,通过以下方式调用:
在属性中定义 => varStatus="stus"
通过“.”调用 => stus.Current/stus.Index/stus.First……

3.18 文件上传与下载

3.18.1 文件上传

①要有一个form标签,method = post请求
②form标签的encType属性值必须为multipart/form-data值
③在form标签中使用input type = file添加上传的文件
④编写服务器代码(Servlet程序)接收,处理上传的数据
encType = multipart/form-data表示提交的数据,以多段(每一个表单项一个数据段)的行驶进行拼接,然后以二进制流的形式发送给服务器

示例如下:

文件上传时发送的http协议解析

服务器接收数据时以流的形式接收:

ServletInputStream inputStream = req.getInputStream();byte[] buffer = new byte[1024000];
int read = inputStream.read(buffer);
System.out.println(new String(buffer,0,read));

服务器处理接收到的数据用到的包有Commons-fileupload.jar和commons-io.jar包,由Apache提供,常用类如下:


示例:

protected void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{//1.先判断上传的数据是否是多端数据(只有是多段的数据,才是文件上传的)if(ServletFileUpload.isMultipartContent(req)){//创建FileItemFactory工厂实现类FileItemFactory fileItemFactory = new DiskFileItemFactory();//创建用于解析上传数据的工具类ServletFileUpload类ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);try{//解析上传的数据,得到每一个表单项FileItemList<FileItem> list = servletFileUpload.parseRequest(req);//循环判断,每一个表单项,是普通类型还是上传的文件for(FileItem fileItem:list){if(fileItem.isFormField()){//普通表单项System.out.println("表单项的name属性值:" + fileItem.getFieldName());//参数UTF-8,解决乱码问题System.out.println("表单项的value属性值:" + fileItem.getString("UTF-8"));}else{//上传的文件System.out.println("表单项的name属性值:" + fileItem.getFieldName());System.out.println("上传的文件名:" + fileItem.getName());fileItem.write(new File("e:\\" + fileItem.getName()));}}}catch(Exception e){e.printStackTrace();}}
}

3.18.2 文件下载

protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{//1.获取要下载的文件名String downloadFileName = "2.jpg";//2.读取要下载的文件内容(通过ServletContext对象可以读取)ServletContext servletContext = get ServletContext();//3.获取要下载的文件类型String mimeType =servletContext.getMimeType("/file/" + downloadFileName);System.out.println("下载的文件类型:" + mimeType);//4.在回传前,通过响应头告诉客户端返回的数据类型resp.setContentType(mimeType);//5.还要告诉客户端收到的数据是用于下载使用(还是使用响应头)//Content-Disposition响应头,表示收到的数据怎么处理//attachment表示附件,表示下载使用//filename 表示指定下载的文件名resp.setHeader("Content-Disposition","attachment;filename=" + downloadFileName);InputStream resourceAsStream = servletContext.getResoueceAsStream("/file/" + downloadFileName)//6.获取响应的输出流OutputStream outputStream = resp.getOutputStream();//7.把下载的文件内容回传给客户端//8.读取输入流中全部的数据,复制给输出流,输出给客户端IOUtils.copy(resourceAsStream,outputStream);
}

下载文件中含有中文名称时:

①(谷歌和IE浏览器)需要进行url编码,转化为%xx%xx%xx……的编码,之后可以识别和显示中文文件名
②火狐浏览器需要进行Base64编码

url编码:

resp.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode("中国.jpg","UTF-8"))

Base64编码:

Base64解码:

编码之后内容变为:
上图中xxxx内容部分浏览器会隐藏,因为内容太多,视觉上很不好,可通过下列代码调取:

"filename==?UTF-8?B?" + new BASE64Encoder().encode("中国.jpg".getBytes("UTF-8")) + "?="
中间的部分即xxxx内容

3.19 书城第三阶段(代码优化)

3.19.1 将Html改为jsp

①首先在页面顶部添加page指令<%@ page contentType="text/html;charset=UTF-8" language="java" %>
②然后refactor => rename 重命名为.jsp后缀
③使用IDEA搜索替换引用到的.html为.jsp



3.19.2 抽取公共内容

将jsp页面中大量重复的部分复制到新的jsp页面中,将原来的的地方通过静态包含的方式替换
<%@ include file="/pages/common/head.jsp"%>

3.19.3 动态获取Base路径
Beanutils和logging

3.19.3 表单提交失败的错误回显

①Servlet程序修改:

②Jsp页面修改:


例:验证码错误回显:

例:用户名已存在错误回显:

总而言之,需要回显的数据保存到request域中

3.19.4 合并login和regist

实际项目开发中是一个模块对应一个servlet程序

通过action的value值来进行分别处理

将注册登录功能单独写成函数,在对应的分支中进行方法调用,便于维护,结构更加清晰
Login和regist函数直接复制doPost方法,修改方法名称即可,因为需要的入口参数一致。

再通过反射优化if else代码:(即直接通过invoke调用目标业务、方法)

将UserServlet.class.getDeclaredMethod方法替换为如下内容:

this.getClass().getDeclaredMethod(action,HttpServletRequest.class,HttpServletResponse.class)

将invoke内的内容替换为:

(this,req,resp)

再将各自servlet程序里面相同步骤的任务进行抽取,抽取成BaseServlet程序:
视频示例中是将各自servlet程序中的doPost方法抽取到BaseServlet中:
3.19.4 数据的封装和抽取BeanUtils的使用

BeanUtils工具类,他可以一次性的把所有请求的参数注入到JavaBean中

BeanUtils中的populate方法注入:

将上述代码部分封装为WebUtils的工具类:

User user = new User();
WebUtils.copyParamToBean(req,resp);

注入的本质是找到对应参数的写方法(SET方法)

再进行优化,将HttpServlet中的req写成Map类型的Value,因为httpservlet对应的API只有在WEB层才有对应的API可以进行处理,除此之外的DAO层以及Service层都没办法处理,而Map类型三层都可以处理。

再进行优化,可以将以下两行代码合成一行:

需要的操作如下:

①修改方法的返回值类型为Object,return bean;
②强制类型转换



再进行优化,可以通过使用泛型,省去强制类型转换这一步骤:

可以省去强制类型转换步骤:

注意事项

1.xxx.html文件新建在webapp文件夹下即可,注意,不要在WEB-INF里面建,里面存放web.xml配置文

【JavaWeb】学习笔记(Tomcat)相关推荐

  1. javaWeb学习笔记 --- tomcat

    tomcat 服务器 动态web资源(如:PHP, JSP, Servlet)运行需要服务器环境 客户端发送请求到服务器,服务器调用动态web资源 Servlet容器.web容器.服务器 (接收请求并 ...

  2. JavaWeb学习笔记——Tomcat配置

    使用的Tomcat版本是apache-tomcat-6.0.20 详细的环境变量配置参考<windows 7系统安装与配置Tomcat服务器环境> 网址为http://jingyan.ba ...

  3. JavaWeb学习笔记-Tomcat虚拟目录与虚拟主机介绍

    Tomcat虚拟目录与虚拟主机介绍 1.主配置文件 server.xml conf文件夹中包含server.xml配置文件 8080 端口:tomcat服务默认端口号.访问url地址后必须手动写:80 ...

  4. JavaWeb学习笔记(软件系统体系结构、Tomcat、Web应用、HTTP协议)

    JavaWeb学习笔记 JavaWeb学习笔记 软件系统体系结构 常见软件系统体系结构C/S.B/S Web资源 Web服务器 Tomcat Tomcat概述 安装.启动.配置Tomcat Web应用 ...

  5. JavaWeb学习笔记2 —— Web服务器简介

    JavaWeb学习笔记2 -- Web服务器简介 参考教程B站狂神https://www.bilibili.com/video/BV12J411M7Sj 相关技术 ASP: 微软:国内最早流行的就是A ...

  6. B站狂神说JavaWeb学习笔记

    JavaWeb学习笔记(根据b站狂神说java编写) 1.基本概念 1.1 前言 静态Web: 提供给所有人看数据不会发生变化! HTML,CSS 动态Web: 有数据交互,登录账号密码,网站访问人数 ...

  7. 【Javaweb学习笔记】在Eclipse中创建Web项目

    [Javaweb学习笔记]在Eclipse中创建Web项目 哈喽大家好,这里是Java框架学习笔记专栏第二期 本期内容--在Eclipse中创建Web项目 前期回顾: 第一期--schema约束 笔者 ...

  8. java web孤傲苍狼,JavaWeb学习笔记

    我看的资料是孤傲苍狼的javaweb学习笔记,他写的真的很全,这或许就是社区力量吧!哪些问题不知道,上网搜一搜就有了,让自己不进步的敌人,只有懒惰了. 这是我接触JavaWeb的第二周,有一些自己的理 ...

  9. Javaweb学习笔记(JSP标准标签库)

    Javaweb学习笔记(JSP标准标签库) JSTL入门 安装和测试JSTL JSTL中的Core标签库 < c:out>标签 标签 标签 < c:catch>标签 标签 标签 ...

  10. JavaWeb学习笔记(十)--HttpServletRequest

    1. HttpServletRequest简介 HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中 2. Ht ...

最新文章

  1. js 操作vuex数据_Vuex 数据状态持久化如何处理?
  2. 赵雪轩:数据科学助力我的智能化航天梦 | 提升之路系列
  3. publishing failed with multiple errors resource is out of sync with the file system--转
  4. wordpress学习笔记
  5. asp.net实现GZip压缩和GZip解压
  6. Java与C++进行系统间交互:Protocol Buffer
  7. 解读腾讯极速高清AR-SR的画质改善机制
  8. adapter为null_软件设计精要之——适配器(Adapter)模式
  9. Linux下载_Linux系统各种版本ISO镜像下载(redhat,centos,oracle,ubuntu,openSUSE)
  10. Windows之Xmanager连接linux打开Oracle视图操作
  11. 图像处理之卷积---任意卷积核的快速实现
  12. Windows Server 2016上具有Docker容器SQL Server
  13. ALSA之PCM分析
  14. mac 上 php 验证码不显示图片
  15. 【Python通过分贝监测Windows系统是否有声音播放】
  16. 硬核图解面试最怕的红黑树【建议反复摩擦】
  17. linux系统查看内核版本是多少,在linux下查看内核版本、gcc版本、操作系统多少位等参数...
  18. 10款提高工作效率的工具软件,你值得拥有!
  19. 在3ds max中,什么是PBR材质?
  20. Arduino基础入门篇28—舵机控制

热门文章

  1. 深度相机的障碍物检测
  2. 关于 cursor_sharing = similar
  3. 实验五 Logistics回归
  4. 新人怎么入门游戏建模?从哪一个软件开始学习?
  5. Ubuntu下一个LTS版本20.04代号Focal Fossa,明年4月正式发布
  6. mysql从库比主库数据多_linux mysql主从复制配置
  7. 【无标Unity基于ShaderLab实现光照系统(着色器代码实现小结)
  8. 转文章格式的小PDF软件
  9. Linux shuf命令
  10. 做直播三个月赚了13亿,但陌陌却不是直播公司