1. Tomcat<br />1 动态网站<br />a) webapps目录下创建一个项目目录<br />b) 在该目录下创建如下内容:<br /> i. WEB-INF目录:<br />1. WEB-INF目录下创建web.xml文件<br />2. 该目录下的html文件不能直接通过客户端(浏览器)访问<br /> ii. 创建动态(html+jsp)或静态网站<br />2、配置外部应用(了解)<br />原来我们的项目是放在webapps下,现在放到外面,也希望tomcat可以找到它<br />方法有两种:<br />(1 conf/server.xml:打开server.xml文件,找到<Host>元素,在其中添加<Context>元素。<br /><Context path=”” docBase=””/><br />a) path : 指定当前应用的名称<br />b) docBase : 指定应用的物理位置<br />c) 浏览器访问地址 http://localhost:8080/path/index.html<br />(2) conf/Catalina/localhost: 在该文件夹内创建itcast_hello.xml文件,在该文件中编写<Context>元素,代码如下:<br /><Context docBase=”C:/hello”/><br />a) 文件名 : 指定当前应用的名称<br />b) docBase : 指定应用的无位置<br />c) 浏览器访问路径 :[http://localhost:8080/itcast_hello/index.html](http://localhost:8080/itcast_hello/index.html)<br /> <br />3.配置虚拟主机(了解)<br /> (1)在conf/server.xml文件中,修改端口号为80<br /> (2)绑定网页和127.0.0.1的绑定关系 C:\WINDOWS\system32\drivers\etc\hosts<br /> 127.0.0.1 网址<br /> (3)在server.xml文件中添加一个<Host><br /><Host name=”URL” appBase=”应用目录” uppackWARs=”true” autoDeploy=”true”><br /></Host><br /> <br />4.POST请求<br /> **Content-Type: **application/x-www-form-urlencoded<br /> 表示表单中的数据自动采用url编码,遇到中文会乱码<br /> 字节+128—>转成16进制—>添加%前缀 <br />utf-8: 一个汉字3个字节<br />gbk: 一个汉字2个字节<br /> <br /> 5.Referer 请求从哪里发出<br /> <br /> <br />6.配置文件<br /> 在conf/context.xml内配置,会对所有项目都有影响。<br /> 在conf\Catalina\localhost目录下,对某以个项目进行配置时,文件名必须为项目名。<br /> 例如:TestSession.xml<br /> <br /> Servlet<br /> 特性:<br /> 单例:一个类只有一个对象,可能存在多个Servlet类<br /> 线程不安全的,效率高<br />Servlet类由我们来写,但对象由服务器来创建,并且由服务器调用相应的方法<br /> <br />1.概述<br />Servlet是JavaWeb三大组件之一,属于动态资源。作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:<br /> 接收请求数据<br /> 处理请求<br /> 完成响应<br />必须实现javax.servlet.Servlet接口。<br /> <br />2.实现Servlet的三种方式(由我们自己写)<br /> (1)实现javax.servlet.Servlet接口<br /> Servlet中的方法大多数不由我们来调用,而是由Tomcat我们来调用<br /> Servlet的对象不由我们来创建,而是由Tomcat来创建<br /> 例子:AServlet<br /> (2)实现javax.servlet.GenericServlet类<br /> (3)实现javax.servlet.http.HttpServlet类(通常,方便)<br /> <br />3.如何让浏览器访问Servlet<br /> 1.给Servlet指定一个Servlet路径(让Servlet与一个路径绑定在一起)<br /> 这需要在web.xml中对Servlet进行配置<br /> <servlet><br /> <servlet-name>XXX</servlet-name><br /> <servlet-class>包名.类名</servlet-class><br /></servlet><br /><servlet-mapping><br /> <servlet-name>XXX</servlet-name><br /> <url-pattern>/XXX</url-pattern><br /></servlet-mapping><br /> <br /> 2.浏览器地址栏访问Servlet路径<br /> <br /> <br />4.ServletConfig<br /> 概述:一个ServletConfig对象对应一端web.xml中servlet配置信息<br /> <servlet><br /> <servlet-name>XXX</servlet-name><br /> <servlet-class>包名.类名</servlet-class><br /></servlet><br />方法:<br /> String getServletName() : 获取<servlet-name>中的内容<br /> ServletContext getServletContext() : 获取Servlet上下文对象<br /> String getInitParameter(String name) : 通过名称获取指定初始化参数的值<br /> Enumeration getInitParameterNames() : 获取所有初始化参数的名称<br /> <br />初始化参数(写在<servlet>内):<br /> <init-param><br /><param-name>p1</param-name><br /><param-value>v1</param-value><br /> </init-param><br /> <init-param><br /><param-name>p2</param-name><br /><param-value>v2</param-value><br /> </init-param><br /> <br /> 5.ServletRequest 和 ServletResponse<br /> ServletRequest : 请求<br /> ServletRequest : 响应<br /> <br />6.GenericServlet<br /> 抽象类<br /> 继承并重写方法即可<br /> <br />7.HttpServlet<br /> <br /> 生命周期方法:<br /> public void **service**([ServletRequest]() req,[ServletResponse]() res)<br /> 一旦发出请求,协议已定,参数强转,调用下面的service方法<br /> 强转参数为http协议相关的类型<br /> protected void **service**([HttpServletRequest]() req,[HttpServletResponse]() resp)<br /> 参数已经是Http协议相关的,使用起来更加方便<br /> 它会通过request得到当前请求的请求方式, 例如:GET或POST<br /> 根据请求方式再调用doGet()或doPost()方法<br /> 注意:<br />doGet和doPost方法由我们自己覆盖!如果你没有覆盖,并且它们被调用了,那么会出现405<br /> <br />8.Servlet细节<br /> 1、线程不安全的,效率高<br /> (1)不要在Servlet中创建成员变量,创建局部变量即可<br />(2)可以创建无状态的成员变量<br />(3)可以创建有状态的成员变量,但状态必须为只读的<br /> <br />2、默认情况下,服务器会在某个Servlet第一次收到请求时创建它,也可以在web.xml对Servlet进行配置,使服务器启动时就创建Servlet。<br /> <br />在项目中的WEB-INF中的web.xml中,在<servlet>中配置<load-on-startup>,其中给出一个非负整数,小的先创建,大的后创建,即启动服务器就创建Servlet对象的顺序。<br /> 3、<url-pattern><br /> (1)一个<servlet-mapping>中可以写多个<url-pattern><br /> (2)还可以使用通配符*,可以匹配任何的前缀和后缀<br /> <br />9.ServletContext(重要)<br /> 概述:<br /> 一个项目只有一个ServletContext对象!<br /> 我们可以在N多个Servlet中获取这个唯一的对象,使用它可以给多个Servlet传递数据。<br /> 这个对象在Tomcat启动时创建,在Tomcat关闭才会死去。<br /> <br />获取ServletContext对象:<br />(1) 在Servlet中获取,ServletConfig类的getServletContext()<br />(2) 在GenericServlet或HttpServlet中获取,getServletContext()<br /> <br />域对象功能:<br /> 域对象就是用来在多个Servlet中传递数据!(存数据和取数据)<br /> 四大域对象的类:PageContext ServletRequest HttpSession ServletContext<br /> 所有域对象都有存储数据的功能,因为域对象内部有一个Map,用来存储数据。<br /> <br />ServletContext对象用来操作数据的方法:<br /> void setAttribute(String name,Object object)<br /> 存储一个域属性,使用相同的name,会覆盖上一次的。<br /> Object getAttribute(String name)<br /> 获取属性的值<br /> void removeAttribute(String name)<br /> 用来移除ServletContext中的域属性<br /> Enumeration getAttributeNames()<br /> 获取所有域属性的名称<br /> <br /> 获取应用初始化参数:<br />Servlet也可以获取初始化参数,但它是局部的参数。一个Servlet只能获取自己的初始化参数,不能获取别人的,即初始化参数只为一个Servlet准备。<br /> <context-param><br /> <param-name>context-name</param-name><br /> <param-value>context-value </param-value><br /></context-param><br /> <br /> <br />获取资源相关方法:TestServletContext项目 Test.DServlet<br />案例1:获取真实路径 <br />案例2:获取资源流<br />案例3:获取指定目录下所有资源路径<br /> <br /> 练习:访问量的统计(一个项目中所有的资源被访问都要对访问量进行累加)<br /> <br />思想:<br />创建一个int类型的变量,用来保存变量,然后把它保存到ServletContext的域中,这样可以保证所有的Servlet都可以访问到!<br />(1)最初时,ServletContext中没有保存访问量相关的属性。<br />(2)当本站第一次被访问时,创建一个变量,设置其值为1,保存到ServletContext中。<br />(3)当以后的访问时,就可以从ServletContext中获取这个变量,然后在其基础上加1。<br /> <br />代码实现:<br />(1) 获取ServletContext对象,查看是否存在名为count的属性,如果存在,说明不是第一次访问,如果不存在,说明是第一次访问。<br />a) 第一次访问:调用ServletContext的setAttribute()方法传递一个属性,名为count,值为1<br />b) 第2~N次访问:调用ServletContext的getAttribute()方法获取名为count的属性,给属性值加1,再调用ServletContext的setAttribute()方法完成设置。<br /> <br />获取类路径下的资源:<br />类路径:对于一个javaweb项目而言,就是/WEB-INF/classes和/WEB-INF/lib/下的每个jar包<br />注意事项:<br />(1)src下的文件除了.java文件,其余的都会发布到/WEB-INF/classes里。而java文件只会发布.class文件。<br />(2)如果想往javaweb项目中放入外来的jar包,只需要复制到/WEB-INF/lib中即可。<br />案例:读取/WEB-INF/classes下login.html文件的内容。<br />代码实现: TestServletContext项目 Test.FServlet<br />步骤:<br />(1) 得到ClassLoader<br />a) 先得到Class,再得到ClassLoader<br />this.getClass().getClassLoader()<br />(2) 调用其getResourceAsStream(),得到一个InputStream<br /> <br />注意:<br />ClassLoader中的getResourceAsStream方法,路径是相对calsses目录的<br /> Class中的getResourceAsStream方法,路径是相对于当前.class文件存放的目录。<br /> 加了“/”后,路径是相对于classes目录下的。<br /> <br /> 10.请求响应流程图<br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608014149926-efbeb6ba-0338-488a-abc0-4b0a1fa92575.png#align=left&display=inline&height=224&margin=%5Bobject%20Object%5D&originHeight=300&originWidth=556&status=done&style=none&width=415)<br /> response: (HttpServletResponse)<br /> http协议中响应内容。<br /> (1)状态码:200成功 404客户端错误 500服务器端错误 303重定向<br /> sendError(int sc) : 发送错误状态码<br /> sendError(int sc,String msg) : 发送错误状态码,并带一个错误信息<br /> sendStatus(int sc) : 发送成功的状态码<br />(2)响应头:Content-Type、Refresh、Location等等<br /> 头就是一个键值对! ( 1个键1个值 1个键多个值)<br /> 所有的响应,包括流和响应体都是Response完成!<br /> 方法:<br />(**)setHeader(String name,String value) : 适用于单值的响应头<br /> addHeader(String name,String value) : 适用于多值的响应头<br /> setIntHeader(String name,int value) : 适用于单值的int类型的响应头<br /> addIntHeader(String name,int value) : 适用于多值的int类型的响应头<br /> setDateHeader(String name,long value) : 适用于单值的毫秒类型的响应头<br /> addDateHeader(String name,long value) : 适用于多值的毫秒类型的响应头<br /> <br />案例1:发送302,设置Location头,完成重定向<br /> 所有的重定向都要发Location头部<br />response.setHeader(“Location”,”重定向的路径”)<br />response.sendRedirect(“重定向的路径”) <br />代码实现: TestResponse项目 Test.AServlet 和Test.BServlet<br /> <br />案例2:定时刷新,设置Refresh头(定时重定向)<br /> 键:Refresh 值: 时间(秒);URL=/项目名/Servlet路径<br />代码实现:TestResponse项目 Test.CServlet<br />案例3:禁用浏览器缓存:Cache-Control、pragma、expires<br />代码实现:TestResponse项目 Test.DServlet<br /> <br />(3) 响应体 : 通常是html,也可以是图片<br />Response的两个流:(两个流不能同时使用,否则会抛出异常)<br /> SevletOutputStream : 用来向客户端发送字节数据<br /> PrintWriter : 用来向客户端发送字符数据! 需要设置编码!<br /> <br />request: (HttpServletRequest):<br /> 封装了客户端所有的请求数据!(请求行 请求头 空行 请求体(get没体))<br />(1) 获取常用信息<br />a) 获取客户端IP request.getRemoteAddr()<br /> i. 案例1:封IP <br />b) 请求方式 request.getMethod()<br /> <br />(2) 获取HTTP请求头<br />a) String getHeader(String name) 适用于单值的请求头<br />b) Int getIntHeader(String name) 适用于单值int类型的请求头<br />c) String getHeader(String name) 适用于单值毫秒类型的请求头<br />d) Enumeration<String getHeader(String name) 适用于多值请求头<br /> <br />案例1:通过User-Agent识别用户浏览器类型<br />代码实现: TestRequest项目 Test.AServlet<br /> <br />案例2:防盗链(如果请求不是通过本站的超链接发出的,发送错误状态码404)<br /> Referer :请求从哪里来的! (直接在地址栏输入网址没有Referer)<br />代码实现: TestRequest项目 Test.BServlet<br /> <br />(3) 获取请求URL<br />a) String getScheme() 获取协议<br />b) String getServerName() 获取服务器名<br />c) String getServerPort() 获取服务器端口<br />d) String getContextPath() 获取项目名<br />e) String getServerPath() 获取Servlet路径<br />f) String getQueryString() 获取参数部分,即问号后面的部分(不包含问号)<br />g) String getRequestURI() 获取请求URI, 项目名+Servlet路径<br />h) String getRequestURL() 获取请求URL 不包含参数的整个请求路径<br />代码实现: TestRequest项目 Test.CServlet<br /> <br />(4) 获取请求参数<br />请求参数:<br />(1) 由客户端发送给服务器!可能在请求体中(POST),也可能在URL之后(GET)<br />(2) 种类:1个参数名1个值 1个参数名多个值<br /> <br /> <br />a) String getParameter(String name) <br />获取指定名称的请求参数值,适用于单值请求参数<br />b) String[] getParameterValues(String name)<br />获取指定名称的请求参数值,适用于多值请求参数<br />c) Enumeration<String> getParameterName()<br />获取所有请求参数名称<br />d) Map<String,String[]> getParameterMap()<br />获取所有请求参数,其中key为参数名,value为参数值<br /> <br />案例1:超链接参数<br />案例2:表单数据<br />代码实现:TestRequest项目 Test.DServlet<br /> <br />(5) 请求转发和请求包含<br />RequestDispatcher rd=request.getRequestDispatcher(“/MyServlet”)<br />使用request获取RequestDispatcher对象,方法的参数为被转发或包含的Servlet路径!<br />请求转发:rd.forward(request,response)<br /> 由下一个Servlet完成响应体,上一个Servlet可以设置响应头<br /> 第一个Servlet所作出的响应体是不出现在客户端中的<br />请求包含:rd.include(request,response)<br /> 由两个Servlet共同完成响应体<br />无论是请求转发还是请求包含,都在一个请求范围内!使用同一个request和resposnse!<br /> <br />(6) Request域<br />Servlet中三大域对象: request、session、application。都有如下方法:<br />a) void setAttribute(String name,Object value)<br />b) Object getAttribute(String name)<br />同一请求范围内使用request. setAttribute、request. getAttribute来传值!<br />前一个Servlet调用setAttribute来保存值,后一个Servlet调用getAttribute获取值<br />c) void removeAttribute(String name)<br /> <br />请求结束,request死去,Attribute也就消失。<br /> <br />(7) 请求转发和重定向的区别<br />a) 请求转发是一次请求一次响应。重定向是两次请求两次响应<br />b) 请求转发地址栏不发生变化。重定向会显示后一个请求的地址<br />c) 请求转发只能转发到本项目的其他Servlet。重定向不只能重定向到本项目的其它Servlet,还能重定向到其它项目中去。<br />d) 请求转发是服务器端行为,只需给出转发的Servlet路径。重定向需要给出RequestURI,即项目名+Servlet路径。<br />e) 请求转发的效率高,因为是一个请求!<br /> <br />11.编码<br /> 常见字符编码:iso-8859-1(不支持中文)、gbk(系统默认编码,中国的国标码)、<br />utf-8(万国码,支持全世界的编码,所以我们使用这个)<br /> <br />(1) 响应编码<br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608014150248-0232dff2-8567-4300-aa84-a739c320f5a6.png#align=left&display=inline&height=260&margin=%5Bobject%20Object%5D&originHeight=545&originWidth=870&status=done&style=none&width=415)<br />浏览器默认编码gbk,服务器默认编码iso。编码不统一,所以会乱码。<br />response.setCharaceterEncoding(“utf-8”) 设置字符流的编码是utf-8<br />setHeader(“Content-Type”,”text/html;charset=utf-8”)<br />告诉浏览器,服务器使用的是utf-8的编码格式。该方法会自动调用setCharaceterEncoding(“utf-8”)<br /> 设置编码的快捷方法: response.setContentType(“text/html;charset=utf-8”)<br /> <br />(2) 请求编码(客户端发送给服务器的请求参数是什么编码)<br />客户端首先要打开一个页面,然后在页面中提交表单或者点击超链接!在请求这个页面时,服务器响应的编码是什么,那么客户端发送请求时的编码就是什么!<br /> <br />GET请求编码处理:(两种方法)<br />(1) String username=request.getParameter(“username”)<br />byte[] b=username.getBytes(“iso-9959-1”)<br />username=new String(b,”utf-8”)<br />(2)在server.xml中配置URIEncoding=utf-8(不推荐使用) <br />POST请求编码处理: <br /> request.setCharacterEncoding(“utf-8”)<br />(3)URL编码<br /> 表单的类型:Content-Type : application/x-www-form-urlencoded<br /> (就是把中文转换成%后面跟随2位的16进制)<br /> <br />为什么要用它?(在客户端和服务器之间传递中文的时需要把它转换成网络适合的方式)<br /> 它不是字符编码!<br /> 它是用来在客户端和服务器之间传递参数的一种方式!<br />POST请求默认使用URL编码,Tomcat会自动使用URL解码!<br />URL编码:String username=URLEncoder.encode(username,”utf-8”)<br />URL解码:String username=URLDecoder.decode(username,”utf-8”)<br />后期我们要将超链接中的中文全部经过URL编码。(学了jsp)<br /> <br />12.路径<br />(1) web.xml中<url-pattern>路径(Servlet路径)<br /> 要么以‘*’开头,要么以‘/’开头<br />(2) 转发和包含路径<br />以‘/’开头,相对当前项目路径,例如:[http://localhost:8080/](http://localhost:8080/)项目名/ <br />不以‘/’开头,相对当前Servlet路径。<br />(3) 重定向路径(客户端路径)<br />以‘/’开头,相对当前主机,例如:http://localhost:8080/<br />(4) 页面中超链接和表单路径<br />与重定向相同,都是客户端路径!需要添加项目名!<br /><a href=”AServlet”> 不以‘/’开头,相对当前页面所在路径 <br />(5) ServletContext获取资源路径<br />相对当前项目目录,即index.jsp所在目录<br />(6) ClassLoader获取资源路径<br />相对classes目录,不能以‘/’开头<br />(7) Class获取资源路径<br />以‘/’开头,相对classes目录<br />不以‘/’开头,相对当前.class文件所在目录<br /> <br /> <br /> JSP<br />1. JSP的作用<br />a) Servlet:<br />缺点:不适合设置html响应体,需要大量的response.getWriter().print(“”)<br />优点:动态资源,可以编程<br />b) html:<br />缺点:html是静态页面,不能包含动态信息<br />优点:不用为输出html标签而发愁<br />c) jsp:<br />优点:在原有html的基础上添加java脚本,构成jsp页面<br /> <br />2. JSP和Servlet的分工<br />JSP:<br /> 作为请求发起页面,例如:显示表单、超链接<br /> 作为请求结束页面,例如:显示数据<br />Servlet:<br /> 作为请求中处理数据的环节<br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608014150560-6cd9d522-08ae-42bb-8ee7-49af7054dcff.png#align=left&display=inline&height=212&margin=%5Bobject%20Object%5D&originHeight=343&originWidth=670&status=done&style=none&width=415)<br />案例1:实现加法<br />代码实现:JSP1项目 jia文件夹(form.jsp , result.jsp) Test.AServlet<br /> <br />3. JSP的组成<br />(1)jsp = html + java脚本 + jsp标签(指令)<br />(2)jsp中无需创建即可使用的对象一共有9个,被称为9个内置对象。例如:<br />request、out、response、session、pageContext、config、page、exception、application<br /> (3)3种java脚本:<br /> <%...%> : java代码片段(常用),用于定义0~N条java语句<br /> (该处定义的变量称为局部变量)<br />(方法内能放什么,这里就能放什么)<br /><%=…%> : java表达式,用于输出(常用),用于输出一条表达式(或变量)的结果(response.getWriter().print()能放什么,这里就能)<br /><%!...%> : 声明,用来创建类的成员变量和成员方法(基本不用)<br />(输出成员变量,需加this,访问完后,值不销毁)<br /> (类中可以放什么,这里就能放什么)<br /> <br />4. JSP原理(理解)<br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608014150917-0290beee-4826-4c98-aef6-8fec39a650f2.png#align=left&display=inline&height=298&margin=%5Bobject%20Object%5D&originHeight=452&originWidth=629&status=done&style=none&width=415)<br />jsp其实是一种特殊的Servlet!<br />(1)当jsp页面第一次被访问时,服务器会把jsp编译成java文件(这个java其实是一个Servlet类)<br />(2)然后再把java编译成.class文件<br />(3)然后创建该类对象<br />(4)最后调用它的service()方法<br />(5)第二次请求同一jsp时,直接调用service()方法<br /> 在tomcat的word目录下可以找到jsp对应的.java源代码<br /> 查看jsp对应java文件<br />(1) java脚本<br /><%...%>中的数据原封不动出现在java文件中。<br /><%=...%>中的数据会放在out.print()中,不是输出字符串,而是输出变量<br /> (2)html<br />html数据都会在out.write()中出现,而且是在双引号内。即当前字符串输出给客户端<br /> <br />5. JSP注释<br />语法:<%-- … --%> : 当服务器把jsp编译成java文件时已经忽略了注释部分!<br /><!-- <%=aaa %> --!> : 会执行jsp指令,但是结果被html注释掉了<br /> <br />6. JSP的三大指令<br />格式:<%@指令名 attr1=”” attr2=””%> 例如:<% @page info=”xx”…%><br /> <br />概述:一般都会把jsp指令放到JSP文件的最上方,但这不是必须的!<br /> 一个JSP页面中,可以有0~N个指令的定义!<br />a) page(最复杂)<br />概述:page指令是最为常用的,也是属性最多的!<br />没有必须属性,只有可选属性!<br />属性:<br />(1)pageEncoding:指定当前的jsp页面的编码!文件保存的编码格式和pageEncoding设置的一样,就不会乱码!在服务器要把jsp编译成java文件时需要使用pageEncoding<br />(2)contentType: 它表示添加一个响应头:Content-Type!等同于response.setContentType(“text/html;charset=utf-8”);<br />如果两个属性只提供一个,那么另一个的默认值为设置那一个<br />如果两个属性都没有设置,那么默认值为iso<br /> <br />(3)import : 导包!可以出现多次!<br />(4)errorPage :当前页面如果抛出异常,那么要转发到哪个页面,由errorPage决定!状态码为200,是请求转发!<br />(5)isErrorPage :它指定当前页面是否为处理错误的页面!<br /> 设为true后,状态码为500。而且这个页面可以使用9大内置对象之一exception!<br /> <br />代码测试:TestJsp项目 error文件夹中的a.jsp、errorPage.jsp <br />在web.xml中配置错误页面:<br /> (1)<br /><error-page><br /> <error-code>404</error-code><br /> <location>/error404.jsp</location><br /> </error-page><br /> (2)<br /><error-page><br /> <exception-type>抛出异常类型</ exception-type ><br /> <location>/error404.jsp</location><br /> </error-page><br /> <br /> <error-code>指定响应码,<location>指定转发的页面<br /> <br />(6)autoFlush : 指定jsp的输出流缓冲区满时,是否会自动刷新!默认为true。如果为false时,那么在缓冲区满时抛出异常!<br />(7)buffer :指定缓冲区大小,默认为8KB,通常不需要修改<br />(8)isELIgnored :是否忽略el表达式,默认为false,不忽略,即支持<br />(9)language(基本没用) :指定当前jsp编译后的语言类型,默认为java。<br />(10)info(基本没用) :jsp说明性信息<br />(11)isThreadSafe(基本没用) :当前的jsp是否支持并发访问默认为false。如果为true,jsp生成的Servlet会去实现一个过时的标记接口SingleThreadModel,这时JSP就只能处理单线程的访问<br />(12)session(基本没用) :默认为true,表示当前JSP页面可以使用session对象。如果为false,表示当前JSP页面不能使用session对象<br />(13)extends(基本没用) : 指定当前JSP页面生成的Servlet的父类<br />b) include(静态包含)<br />(1)与RequestDispatcher的include()方法功能相似!<br />(2)<%@include%> 它是在jsp编译成java文件时完成的!它们共同生成一个java文件,然后再生成一个class!<br />(3)RequestDispatcher的include()是一个方法,包含和被包含的是两个Servlet,即两个.class文件!它们只是把响应的内容在运行时合并了!<br />作用:把页面分解了,使用包含的方式组合在一起,这样一个页面中不变的部分,就是一个独立的jsp,而我们只需要处理变化的页面<br />代码测试:TestJsp项目 include文件夹中的hel.jsp、lo.jsp<br /> <br />c) taglib(导入标签库)<br /> 两个属性:<br /> (1)prefix :指定标签库在本页面中的前缀!由我们自己起名! <br /> (2)uri :指定标签库的位置<br /> <br />7. JSP九大内置对象(无需创建就可以使用)<br />a) out(JspWriter) : response.getWriter(),用来向客户端发送文本数据<br />b) config(ServletConfig) : 对应“真身”中的ServletConfig<br />c) page(Object) : 当前JSP页面的“this”,即当前对象。Object page=this;<br />d) pageContext(PageContext) :页面上下文对象,域对象之一<br />e) exception(Throwable): 只有在错误页面中可以使用这个对象<br />f) request(HttpServletRequest): 即HttpServletRequest类的对象<br />g) response(HttpServletResponse) :即HttpServletResponse类的对象<br />h) application(ServletContext): 即ServletContext类的对象。只有一个,生命跟随服务器(服务器打开即生命开始,服务器关闭即生命结束)<br />i) session(HttpSession) :即HttpSession类的对象,不是每个JSP页面中都可以使用,如果在某个JSP页面中设置<%@page session=”false”%>,说明这个JSP页面不能使用session。<br /> <br />域对象排序(从大到小):<br /> ServletContext : 整个应用程序<br /> HttpSession : 整个会话(一个会话中只有一个用户)<br /> HttpServletRequest : 一个请求链<br />PageContext : 一个JSP页面!这个域是在当前JSP页面和当前JSP页面中使用的标签之间共享数据<br /> PageContext :<br /> 作用:<br />(1)可以在当前JSP页面和当前JSP页面中使用的标签之间共享数据<br /> (2)域对象<br /> (3)代理其它域(可以往其它域存取数据)<br />pageContext.setAttribute(“xx”,”XX”,PageContext.SESSION_SCOPE)<br /> (4)全域查找(在四大域对象中查找,从小到大,依次查找)<br /> pageContext.findAttribute(“xx”)<br /> (5)获取其它8个内置对象<br /> <br />8. JSP的动作标签<br />概述:1、这些jsp的动作标签,与html提供的标签有本质的区别<br />2、动作标签是由Tomcat(服务器)来解释执行。与java代码一样,都是在服务器端执行的。<br /> 3、html的标签由浏览器来执行。<br />种类:<br />(1)<jsp:forward> :转发!与RequestDispatcher的forward方法一样。一个是在Servlet中使用,一个是在jsp中使用<br /> <br />代码测试:TestJsp项目 Jspforward文件夹里面的a.jsp、b.jsp<br /> <br />(2)<jsp:include> :包含!与RequestDispatcher的include方法一样。一个是在Servlet中使用,一个是在jsp中使用<br /> <br /> 代码测试:TestJsp项目 Jspinclude文件夹里面的a.jsp、b.jsp<br /> <br /> 注意:<br />1、<%@include%>是在编译时完成,即把当前JSP和被包含的JSP合并成一个JSP,然后再编译成一个Servlet。都是静态包含<br />2、<jsp:include>是在运行时完成,即把当前JSP和被包含的JSP都会各自生成Servlet,然后在执行当前JSP的Servlet时完成包含另一个JSP的Servlet。是动态包含<br /> <br />(3)<jsp:param> :用来作为forward和include的子标签!用来给转发或包含的页面传递参数!<br /> <br /> 代码测试:TestJsp项目 Jspforward文件夹里面的a.jsp、b.jsp<br /> <br />9. 配置Tomcat安装路径的conf文件夹的文件<br />a) context.xml<br /><Context reloadable="true"><br /> <br />10. JavaBean<br /> 概述:**JavaBean是一个遵循特定写法的Java类**<br /> 规范:<br />1. 必须要有一个默认构造器<br />2. 提供get/set方法,如果只有get方法,那么这个属性为只读属性<br />3. 属性:有get/set方法的 成员,还可以没有成员,只有get/set方法。属性名称由get/set方法来决定!而不是成员名称!<br />4. 方法名称满足了一定的规范,那么它就是属性!boolean类型的属性,它的读方法可以是is开头,也可以get开头!<br /> <br />内省(了解): <br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608014151171-d4eed6e7-ff38-4350-b7de-a765408c920c.png#align=left&display=inline&height=150&margin=%5Bobject%20Object%5D&originHeight=398&originWidth=1099&status=done&style=none&width=415) commons-beanutils,它是依赖内省完成的!(简单,因为内省依赖反射)<br /> 代码测试:TestJsp项目 JavaBean包里的所有类!
    1. JSP与JavaBean相关的标签
      (1) :创建或查询Bean(有就查找,没有就创建)

         “id“属性用于指定JavaBean实例对象的引用名称和其存储在域范围中的名称。
         “class“属性用于指定JavaBean的完整类名(即必须带有包名)。
         “scope“属性用于指定JavaBean实例对象所存储的域范围,其取值只能是page、 request、session和application等四个值中的一个,其默认值是page。

      (2) :用于设置和访问JavaBean对象的属性
      语法格式一:
      <jsp:setProperty name=”beanName” property=”propertyName” value=”string**字符串”/>
        
      语法格式二:

        
      语法格式三:

        
      语法格式四:
          

      name属性用于指定JavaBean对象的名称。    property属性用于指定JavaBean实例对象的属性名。

      value属性用于指定JavaBean对象的某个属性的值,value的值可以是字符串,也可以是表达式。为字符串时,该值会自动转化为JavaBean属性相应的类型,如果value的值是一个表达式,那么该表达式的计算结果必须与所要设置的JavaBean属性的类型一致。   
      param属性用于将JavaBean实例对象的某个属性值设置为一个请求参数值,该属性值同样会自动转换成要设置的JavaBean属性的类型。

      (3) :用于读取JavaBean对象的属性,也就是调用JavaBean对象的get方法,然后将读取的属性值转换成字符串后插入进输出的响应正文中。



      name属性用于指定JavaBean实例对象的名称,其值应与标签 的id属性值相同。
      property属性用于指定JavaBean实例对象的属性名。

      如果一个JavaBean实例对象的某个属性的值为null,那么,使用标签输出该属性的结果将是一个内容为“null”的字符串。

      12. EL表达式
      (1)概述:EL是JSP内置的表达式语言!
      Jsp2.0开始,不让使用java脚本,而是使用EL表达式和动态标签来替代。
      EL替代的是<%=…%>,也就是说,EL只能做输出!
      (2)格式:${ }
      (3)关闭EL
      如果希望整个JSP忽略EL表达式,需要在page指令中指定isELIgnored=”true”
      如果希望忽略某个EL表达式,可以在表达式的面前加“\”

      (4)EL表达式来读取四大域
      ${xxx} :全域查找名为xxx的属性,如果不存在,输出空字符串,而不是输出null
      ${pageScope.xxx}、${requestScope.xxx} :指定域查找
      ${sessionScope.xxx}、${applicationScope.xxx} :指定域查找
      代码测试:TestJsp项目 EL文件夹里的index.jsp

      (5)JavaBean导航(重要)
      代码测试:TestJsp项目 EL文件夹里的a.jsp

      (6)EL表达式可以输出的东西都在11个内置对象中(10个是Map,pageContext不是)
      1、pageScope
      2、requestScope
      3、sessionScope
      4、applicationScope
      5、param :
      Map类型,可以用来获取请求参数。
      与request.getParameter()方法相同。适用于单值参数。
      6、paramValues :
      Map类型,可以用来获取请求参数。
      当一个参数名,对应多个参数值时,可以使用它。适用于多值参数。

      代码测试 :TestJsp项目 EL文件夹里的param.jsp 、paramValues.jsp
      7、header :
      Map类型,用来获取请求头。适用于单值请求头。
      代码测试 :TestJsp项目 EL文件夹里的header.jsp

      8、headerValues :
      Map类型。当一个请求头名称,对应多个值时,使用该对象。

      9、initParam :
      Map类型。对应web.xml中的参数
      代码测试 :TestJsp项目 EL文件夹里的initParam.jsp

      10、cookie :
      Map类型。Key是Cookie的名字,值是Cookie对象。
      例如:
      <% response.addCookie(new Cookie(“xxx”,”XXX”)) %>
      获取cookie对象: ${cookie.xxx}
      获取cookie的名称:${cookie.xxx.name}
      获取cookie的值:${cookie.xxx.value}
      代码测试 :TestJsp项目 EL文件夹里的cookie.jsp

      11、pageContext :
      代码测试 :TestJsp项目 EL文件夹里的pageContext.jsp JavaWeb - 图1

      (7)EL运算符
      JavaWeb - 图2

      (8)EL函数库(由JSTL提供的!)
      概述:EL函数库就是定义一些有返回值的静态方法,然后通过EL语言调用。
      不只是JSTL可以定义EL函数库,我们可以自定义EL函数库。
      导包: fn.tld(G:/jar包/fn.tld)
      导入函数库:<%@taglib prefix=”fn” uri=”http://java.sun.com/jsp/jstl/functions”%>
      EL函数库介绍:(只列举了特殊的)
      格式:${fn:length(arr)}
      String escapeXml(String input) :把字符串的”>”,”<”转义!
      int length(Object obj) :可以获取字符串、数组、各种集合的长度

      (9)自定义EL函数库
      1、写一个类,写一个有返回值的静态方法
      2、编写TestEL.tld文件,可以参考fn.tld文件来写,把TestEL.tld文件放入/WEB-INF目录下
      3、在页面 添加taglib指令,导入自定义标签库

      13. JSTL标签库
      1、概述:依赖EL。使用要导入jstl-1.2.jar包
      2、标签库:
      (1)core(重点) :核心标签库
      (2)fmt(只学习两个标签即可) :格式化标签库
      (3)sql(不需要学习,过时了) :数据库标签库
      (4)xml(不需要学习,过时了) :xml标签库

      2、 使用taglib指令导入标签库
      导包
      <%@taglib prfix=”前缀” uri=”路径”%>

      3、 core标签库常用标签(常用c来做前缀)
      a) out :输出
      格式 :
      default : 当要输出的内容为null时,则输出default指定的值
      value : 输出的内容。可以是字符串常量,也可以是EL表达式
      escapeXml : 默认为true,转义’<’,’>’字符。为false,不转义
      代码测试:TestJsp项目 JSTL文件夹out.jsp

      b) set :设置 (创建域属性)
      格式:
      var :变量名
      value : 变量值,可以是EL表达式
      scope : 域范围,默认为page。 可选值:page、session、request、application
      代码测试:TestJsp项目 JSTL文件夹set.jsp

      c) remove : 删除域属性
      格式:
      默认删除所有域中变量名为var指定值的属性。
      var : 变量名
      scope : 域范围,默认为page。 可选值:page、session、request、application

      d) url
      格式 :<>
      value : 指定一个路径。它会在路径前面自动添加项目名
      例如: 输出:/TestJsp/index.jsp
      var :一旦添加这个属性,就会将生成的url保存到域中,不会输出到页面
      scope : 与var属性一起使用,将生成的url保存到域中。
      域范围,默认为page。 可选值:page、session、request、application。

      子标签 :
      name : 参数名
      value : 参数值。 为中文时,自动进行url编码
      代码测试: TestJsp项目 JSTL文件夹里的url.jsp

      e) if :对应java的if语句
      格式 :….
      test : 一定是布尔类型。为true执行if标签内部,否则不执行。
      代码测试: TestJsp项目 JSTL文件夹里的if.jsp

      f) choose :对应java的if/else if/…/else语句
      格式:….
      子标签:
      语句1
      test : 一定是布尔类型。为true时输出语句1,否则不执行。
      语句2
      当前面的标签内的语句都不执行时,则输出语句2。
      代码测试: TestJsp项目 JSTL文件夹里的choose.jsp

      g) forEach :
      (1)用来循环遍历数组、集合!还可以当一般的for循环使用
      格式:
      var : 变量名
      begin : 变量起始值(包含)
      end : 变量结束值(包含)
      step : 变量每次累加的数值。默认为1
      items : 指定要遍历的内容。可以是数组或集合。
      代码测试: TestJsp项目 JSTL文件夹里的forEach.jsp
      (2)循环状态变量 :用varStatus创建
      格式:
      first : boolean类型,是否为第一个元素
      index :int类型,当前元素的下标
      last : boolean类型,是否为最后一个元素
      count : int类型,当前已遍历元素的个数
      current : Object类型,表示当前项目
      4、 fmt标签库常用标签
      作用:通常用来格式化输出的,需要格式化的有时间和数字
      a) formatDate
      格式:
      value : 需要格式化的变量
      pattern :格式化的形式(yyyy-MM-dd HH:mm:ss)
      b) formatNumber
      格式:
      0.00 : 保留小数点后两位,会四舍五入。如果不足2位,补0
      格式:
      #.## : 保留小数点后两位,会四舍五入。如果不足2位,不补0
      5、 自定义标签
      (1)步骤:
      标签处理类(标签也是一个对象,那么就先需要一个类)
      tld文件,它是一个xml
      页面中使用<%@taglib %>来指定tld文件的位置

      代码测试:TestJsp项目 MyJSTL.MyTag1.java MyJSTL.MyTag1.jsp MyJSTL. MyTag.tld
      代码测试:TestJsp项目 MyJSTL.MyTag2.java MyJSTL.MyTag2.jsp MyJSTL.MyTag.tld
      (2)标签处理类
      SimpleTag接口 : (5个方法)
      void doTag() : 每次执行标签时都会调用这个方法
      JspTag getParent() : 返回父标签(自己调,其它方法由Tomcat调用)
      void setParent(JspTag ) : 设置父标签
      void setJspBody(JspFragment ) : 设置标签体
      void setJspContext(JspContext ) : 设置Jsp上下文,JspContext的儿子是pageContext

      其中doTag()方法会在其它三个set方法之后被Tomcat调用。所以在
      doTag()内可以使用JspContext、JspFragment、JspTag。

      (3)配置tld文件
      一般tld文件都放在项目的WEB-INF目录下。

      MyTag1 指定当前标签的名称
      MyJSTL.MyTag1 标签处理类的路径(包名+类名)
      empty 指定标签体的类型。这里是空标签

      (4)在页面导入tld文件
      导入标签库: <%@taglib prefix=”My” uri=”WEB-INF/MyJSTL/tld1.tld”%>
      (5)标签体类型
      empty : 无标签体
      jsp : jsp2.0不支持此类型了!表示标签体内容:java脚本或标签或EL表达式
      scriptless : 只能是EL表达式,也可以是其它标签
      代码测试:TestJsp项目 MyJSTL.MyTag3.java MyJSTL.MyTag3.jsp MyJSTL. MyTag.tld
      tagdependent : 标签体内容不会被执行,而是直接赋值给标签处理类

      (6)不执行标签下面的页面内容
      方法:在doTag()方法最后抛出SkipPageException()
      原理:Tomcat会调用标签处理类的doTag()方法,然后得到SkipPageException,它会跳过本页面的其它内容。
      代码测试:TestJsp项目 MyJSTL.MyTag4.java MyJSTL.MyTag4.jsp MyJSTL. MyTag.tld
      (7)带有属性的自定义标签
      步骤:
      1. 在标签处理类中添加属性
      属性至少要有set方法,这个set方法会在doTag方法之前被tomcat调用,因此可以在doTag方法中使用属性
      2. 在tld文件中对属性进行配置

      属性名
      属性是否一定要赋值。true为是。
      属性的值是否可以是EL

      代码测试:TestJsp项目 MyJSTL.MyTag5.java MyJSTL.MyTag5.jsp MyJSTL. MyTag.tld

      Cookie
      1. HTTP协议与Cookie(了解)
      (1)Cookie是HTTP协议制定的!先由服务器保存Cookie到浏览器中,当浏览器再次请求服务器时会把上一次请求得到Cookie归还给服务器
      (2)由服务器创建保存到客户端浏览器的一个键值对(1键1值)!服务器保存Cookie的响应头:Set-Cookie : aaa=AAA Set-Cookie : bbb=BBB
      (3)当浏览器再次请求服务器时,会把该服务器保存的Cookie随请求发送给服务器。浏览器归还Cookie的请求头: Cookie : aaa=AAA ; bbb=BBB
      (4)HTTP协议规定
      1个Cookie最大4KB
      1个服务器最多向1个浏览器保存30个Cookie
      1个浏览器最多存可以保存300个Cookie
      (5)Cookie是不能跨浏览器的!

      2. Cookie的用途
      a) 服务器使用Cookie来跟踪客户端状态
      b) 保存购物车(购物车中的商品不能使用request保存,因为它是一个用户向服务器发送的多个请求信息)
      c) 显示上次登录名(一个用户多次请求)

      3. JavaWeb中使用Cookie
      a) 原始方式(了解)
      使用response发送Set-Cookie响应头
      使用request获取Cookie请求头
      b) 便捷方式(精通)
      使用response.addCookie()方法向浏览器保存Cookie
      使用request.getCookies()方法获取浏览器归还的Cookie

      案例:在a.jsp中保存Cookie,然后在b.jsp中获取。
      代码实现:TestCookie项目 cookie1文件夹中的a.jsp 、b.jsp

      4. Cookie详解
      a) Cookie不只有name和value属性
      b) Cookie的maxAge : Cookie的最大生命,即Cookie可保存的最大时长,以秒为单位
      i. maxAge>0 : 浏览器会把Cookie保存到客户机的硬盘上,有效时长为 maxAge的值决定
      ii. maxAge<0 : Cookie只在浏览器内存中存在,当用户关闭浏览器时,浏览器进程结束,同时Cookie也就死亡
      iii. maxAge=0 : 浏览器会马上删除这个Cookie

      5. Cookie的path(理解)
      a) Cookie的path并不是设置这个Cookie在客户端的保存路径
      b) Cookie的path由服务器创建Cookie时设置
      c) 当浏览器访问服务器某个路径时,需要归还哪些Cookie给服务器?这由Cookie的path决定
      d) 当浏览器访问服务器的路径,如果包含某个Cookie的路径,那么就会归还这个Cookie
      e) Cookie的默认路径, 当前访问路径!

      6. Cookie的domain(了解)
      domain用来指定Cookie的域名! 当多个二级域中共享Cookie时才有用!


      HttpSession
      1. HttpSession概述
      a) HttpSession由JavaWeb提供,用来会话跟踪的类。Session是服务器端对象,保存在服务器端!!
      b) HttpSession是Servlet三大域对象之一,所以它有setAttribute()、getAttribute()、removeAttribute()
      c) HttpSession底层依赖Cookie,或是URL重写!
      d) 一个请求一个request,一个会话一个session
      2. HttpSession作用
      a) 会话范围(session周期):某个用户从首次访问浏览器开始,到该用户关闭浏 览器结束
      i. 会话:一个用户对服务器的多次连贯性请求! 连贯性请求: 用户多次请求中间没有关闭浏览器!
      b) 服务器会为每个客户端创建一个session对象,session就好比客户在服务器端的账户,它们被服务器保存到一个Map中,这个Map被称为session缓存
      i. Servlet中得到session对象 :HttpSession session=request.getSession()
      ii. Jsp中得到session对象 :session是jsp内置对象,不用创建即可直接使用

      案例1:测试session域
      代码实现: TestSession项目 session1里的a.jsp b.jsp

      案例2:保存用户登录信息(要求如下图所示:)
      代码实现:TestSession session2里的login.jsp succ1.jsp succ2.jsp Test.LoginServlet
      JavaWeb - 图3

      3. HttpSession原理(理解)
      (1)服务器不会马上给你创建session,在第一次获取session时,才会创建!
      (2)request.getSession()方法:
      1、获取Cookie中的JSESSIONID :
      (1)如果sessionId不存在,创建session,把session保存起来,把新创建的sessionId保存到Cookie中
      (2)如果sessionId存在,通过sessionId查找session对象,如果没有查找到,创建session,把session保存起来,把新创建的sessionId保存到Cookie中
      (3)如果sessionId存在,通过sessionId查找到了session对象,那么就不会再创建session对象了。
      (4)返回session

      2、 如果创建了新的session,浏览器会得到一个包含了sessionId的Cookie,这个Cookie的生命为-1,即只在浏览器内存中存在,如果不关闭浏览器,那么Cookie就不会消失!
      3、 下次请求时,再次执行request.getSession()方法时,因为可以通过Cookie中的JSESSIONID找到session对象,所以与上一次请求使用的是同一个session对象!
      (3) getSession(false) : 如果session缓存中(如果Cookie不存在),不存在session,那么返回null,不会创建session对象!

      4. HttpSession的其它方法
      a) String getId() : 获取sessionId
      b) int getMaxInactiveInterval() :获取session可以的最大不活动时间(秒),默认为30分钟,当session在30分钟内没有使用,那么Tomcat会在session池中移除
      c) void invalidate() : 让session失效!当session失效后,客户端再次请求,服务器会给客户端创建一个新的session
      d) Boolean isNew() : 查看session是否为新,当客户端第一次请求时,服务器为客户端创建session,但这是服务器还没有响应客户端,所以没有把JSESSIONID加入Cookie中

      5. 项目中web.xml中配置session的最大不活动时间

      30


      6. URL重写(理解)
      a) Session依赖Cookie,目的是让客户端发出请求时归还sessionId,这样就能找到对应的session
      b) 如果客户端禁用了Cookie,那么就无法得到seesionId,那么session就无用了!
      c) 也可以使用URL重写来代替Cookie
      i. 让所有网站的超链接和表单数据都添加一个特殊的请求参数,即sessionId
      ii. 这样服务器可以通过获取请求参数得到sessionId,从而找到session对象
      d) response.encodeURL(String url)
      该方法会对url进行智能的重写,当请求中没有归还sessionId这个Cookie,那么该方法会重写url,否则不重写!当然url必须是指向本站的url


      MVC
      1. 概述
      MVC不是java独有的,基本所有B/S结构的项目都在使用它!
      M :model 模型(自己写代码)
      V :view 视图(JSP)
      C :Controller 控制器(Servlet)

      2. MVC设计模式

      JavaWeb - 图4

      3. JavaWeb的三层框架
      Web层 :与Web相关的内容(Servlet、JSP、Servlet相关的API)
      业务层 :业务对象(业务需求)
      数据层 :操作数据库(DAO 数据访问对象,所有对数据库的操作,不能跳出DAO之外)

      4. 三层的HelloWorld程序
      WebProject2项目!
      创建四个包:Domain(放实体类) Dao(操作数据库) Service Web(Servlet)
      代码实现: index.jsp show.jsp


      案例:用户注册登录
      要求:三层框架,使用验证码
      1. 功能分析
      注册
      登录
      2. 分析
      JSP:
      login.jsp 登录表单
      regist.jsp 注册表单
      welcome.jsp 主页(只有登录成功才能看到)
      Servlet:
      LoginServelt
      RegistServlet

      Service:
      UserService 与用户相关的业务类
      Dao:
      UserDao 与用户相关的数据类
      Domain:
      User
      username(用户名)
      password(密码)
      verifyCode(验证码)
      数据库设计:
      users.xml





      3. 实现步骤
      1. 创建空项目(WebProject3)
      2. 导包
      commons-beanutils.jar
      commons-logging.jar
      dom4j
      jaxen
      3. 创包
      Domain
      User
      Dao
      UserDao
      Service
      UserService
      Web
      LoginServlet
      RegistServlet
      Utils(CommonUtils类)
      4. 创建users.xml文件
      添加根元素
      保证文件格式为utf-8
      5. 创建Jsp页面
      login.jsp
      regist.jsp
      welcome.jsp


      4. 实现注册功能的具体实现操作
      regist.jsp
      第一步完成regist.jsp的基本功能!
      RegistServlet
      封装表单数据,封装到User对象中
      调用Service的regist()方法
      如果这个方法没有出问题,输出“注册成功”
      如果这个方法抛出了异常,把错误信息保存到request域,转发到regist.jsp(显示错误信息)
      UserService(regist方法)
      没有返回值,但注册失败抛出一个自定义异常,可以在异常中添加异常信息(自定义一个异常类)
      校验用户名是否已被注册(通过用户名查询用户),如果已被注册,抛出异常,异常信息为“用户名已被注册”
      添加用户
      UserDao
      按用户名查询用户对象:User findByUsername(String username)
      插入一个用户到数据库中:void add(User user)
      工作:
      1. 在Service层添加一个UserException
      2. Dao
      a) User findByUsername(String username)
      b) void add(User user)
      3. Service
      void regist(User user)
      4. Web
      封装表单数据到User对象
      使用user调用Service的regist方法
      如果得到异常,那么把异常信息保存到request域中,转发到regist.jsp 如果没有得到异常,输出“注册成功”

      5. 实现登录功能的具体实现操作
      login.jsp 登录表单
      LoginServlet
      获取表单数据,封装到User中
      调用Service的login()方法,传递form过去
      如果login方法没有抛出异常,返回User对象!
      有异常:保存异常信息、表单到request域中,转发到login.jsp
      没异常:保存返回的User对象到session域中。重定向到welcome.jsp(显示用户信息)
      UserService
      Public User login(User form)
      使用用户名查询数据库,得到返回的User对象
      返回null : 抛出异常,异常信息为(用户名不存在)
      不返回null :获取查询出来的User的密码和form的密码比较!
      如果不同,抛出异常,异常信息为(密码错误)
      如果相同,返回查询结果!
      UserDao
      通过用户名查询用户(已经存在此方法,不需要重复写!)

      BaseServlet
      JavaWeb - 图5
      使用if条件判断:
      代码测试:TestBaseServlet项目 Test.AServlet
      使用反射:
      代码测试:TestBaseServlet项目 Test.BServlet
      完成转发和重定向:
      代码测试:TestBaseServlet项目 Test.CServlet Test.BaseServlet

      分页(WebProject4)
      1、什么是分页
      例如:第X页 共X页 1 2 3 4 5 6 上一页 下一页 首页 尾页
      优点:只查询一页,不用查询所有也

      2、分页的数据
      JavaWeb - 图6
      3、数据的传递
      (1)这些分页数据总要在各层之间来回的传递!
      (2)我们把这些数据封装到一个javabean中,它就叫分页Bean,例如:PageBean

      4、分页Bean的设计(Domain.PageBean)
      JavaWeb - 图7
      5、分页在各层中的处理(findAll()方法)
      JavaWeb - 图8
      6、显示分页页码列表
      JavaWeb - 图9
      7、在超链接中要保留参数
      代码实现:
      多条件(模糊)查询:query(User u,int pc,int ps)
      截取Url : getUrl(HttpServletRequest request)






      监听器
      1. JavaWeb的三大组件
      Servlet
      Listener(监听器)
      Filter(过滤器)
      2. 概述:
      (1) 它是一个接口,内容由我们来实现
      (2) 需要注册
      (3) 监听器的方法,会在特殊时间发送时被调用
      3. 观察者
      事件源
      事件
      监听器

      4. JavaWeb中的监听器
      (1) 事件源
      ServletContext
      生命周期监听:ServletContextListener,它有两个方法,一个在出生时调用,一个在死亡时调用
      属性监听:ServletContextAttributeListener,它有三个方法,一个添加属性时调用,一个在替换属性时调用,最后一个在移除属性时调用
      HttpSession
      生命周期监听:HttpSessionListener,它有两个方法,一个在出生时调用,一个在死亡时调用
      属性监听:HttpSessionAttributeListener,它有三个方法,一个添加属性时调用,一个在替换属性时调用,最后一个在移除属性时调用

      ServletRequest
      生命周期监听:ServletRequestListener,它有两个方法,一个在出生时调用,一个在死亡时调用
      属性监听:ServletRequestAttributeListener,它有三个方法,一个添加属性时调用,一个在替换属性时调用,最后一个在移除属性时调用
      (2)监听器
      感知监听器(都与HttpSession有关)
      AHttpSessionBindingListener
      能够监听session是否添加/删除了javabean对象。
      特点:
      它用来添加在javabean上,而不是添加到三大域上
      这两个监听器不需要在web.xml上注册
      HttpSessionActivationListener
      1、session的钝化:
      关闭服务器后,tomcat会把session通过序列化的方式保存到硬盘中去。 Session中保存的对象也会被钝化 。
      2、session的活化:
      打开服务器后,tomcat会把钝化了的session反序列化给内存。Session中保存的对象也会被活化。
      *
      3、废除钝化和活化现象
      在conf/context.xml内加入:


      4、配置钝化和活化现象
      JavaWeb - 图10
      5、作用
      1、向session中保存javabean对象时,超出设置的钝化时间内没有操作,javabean和session会被一起钝化。
      2、Javabean对象必须实现
      HttpSessionActivationListener
      java.io.Serializable两个接口。

      (3)JavaWeb中完成编写监听器
      写一个监听器类,要求必须实现某个监听器接口
      注册,在web.xml中配置来完成注册

      包名+类名

      代码测试 : WebListener项目 Test.Demo01类
      代码测试 : WebListener项目 Test.Demo02类
      (4)事件对象
      1.ServletContextEvent : ServletContext getServletContext()
      2.HttpSessioneEvent : HttpSessionEvent getSession()
      3.ServletRequest :
      ServletContext getServletContext()
      ServletRequest getServletRequest()
      4.ServletContextAttributeEvent :
      ServletContext getServletContext()
      String getName() 获取属性名
      Object getValue() 获取属性值
      5.HttpSessionBindingEvent
      6.ServletRequestAttributeEvent

      5. 国际化
      (1) 概述:就是把网页的中文变成英文
      (2) 语言环境类: Locale
      zh_CN en_US
      new Locale(”zh”, ”CN”);
      Locale.getDefault();
      Locale.US
      (3)
      JavaWeb - 图11

      (4)代码测试: WebListener项目 Test.Demo03类



      过滤器
      1.作用:
      (1) 它会在一组资源(html、css、jsp、servlet等)的前面执行
      (2) 具有拦截请求的能力:它可以让请求得到目标资源,也可以不让请求得到
      (3)
      2.编写
      (1)写一个类,实现Filter接口
      Filter接口(Filter是单例的)
      void init(FilterConfig arg0)
      创建之后,马上执行。Filter会在服务器启动时创建!
      void destroy()
      销毁之前执行。Filter在服务器关闭时销毁!
      void doFilter(ServletRequest,ServletResponse,FilterChain)
      每次过滤时都会执行。

      (2)在web.xml中进行配置

      包名+类名
      xxx


      xxx
      /
      过滤一组资源


      代码测试:WebFilter项目 Test.AServlet Test.AFilter

      3.FilterConfig(与ServletConfig相似)
      获取初始化参数:getInitParamter(String name)
      获取过滤器名称:getFilterName()
      获取application:getServletContext()

      4.FilterChain
      void doFilter(ServletRequest,ServletResponse):放行,不会拦截某资源
      代码测试:WebFilter项目 Test.AFilter,BFilter,AServlet

      5.多个过滤器
      (1)void doFilter(ServletRequest,ServletResponse):
      执行目标资源,或是执行下一个过滤器!如果没有下一个过滤器,那么执行目标资源。如果有下一个过滤器,就执行下一个过滤器。
      (2)执行顺序:在前面的,先执行。

      6.过滤器的四种拦截方式
      内配置。
      (1)请求 REQUEST 默认的
      REQUEST
      (2)转发 FORWARD
      FORWARD
      (3)包含 INCLUDE
      INCLUDE
      (4)错误 ERROR
      ERROR
      代码测试:WebFilter项目 Test.BServlet,AServlet,AFilter,BFilter

      7.过滤器的应用场景
      (1)执行目标资源之前做预处理工作。例如:设置编码
      (2)通过条件判断是否放行。例如:校验当前用户是否登录,用户IP是否被禁用
      (3)在目标资源执行后,做一些后续的特殊处理工作。例如:把目标资源输出的数据进行处理。

      8.案例1:分IP统计网站的访问次数
      代码实现: WebFilter项目 Project1
      JavaWeb - 图12
      9.案例2:粗粒度权限控制(拦截是否登录、拦截用户名admain权限)
      代码实现: WebFilter项目 Project2
      JavaWeb - 图13
      10.案例3:解决全站字符乱码问题(POST和GET中文编码问题)
      代码实现: WebFilter项目 Project3
      JavaWeb - 图14
      11.案例4:页面静态化
      代码实现: WebListener项目 Project4



      上传和下载
      1.上传对表单的限制
      (1)method=”POST”
      (2)enctype=”multipart/form-data”
      (3)表单中需要添加文件表单项:
      代码测试:WebUpload项目 WebContent.form1.jsp

      2.上传对Servlet的限制
      (1)request.getParamter();这个方法在表单为Enctype=”multipart/form-data”时,该方法作废,永远返回为null。
      (2)使用ServletInputStream request.getInputStream();包含整个请求的体

      3.多部件表单的体
      (1)一个表单项()一个部件
      (2)一个部件包含(请求头、空行、请求体)
      (3)普通表单项(除了type=“file”的都是普通表单项)
      一个头:Content-Disposition,包含name=””,即表单项名称
      体: 表单项的值
      (4)文件表单项(type=”file”)
      二个头:1、Content-Disposition,包含name=””,即表单项名称
      filename=”xxx”,即上传文件的名称
      2、Content-Type:它是上传文件的MIME类型。
      例如:image/pjgeg,表示上传的文件是图片,扩展名jpg
      体:上传文件的内容

      4.Servlet获取上传文件的数据
      案例1:获取上传文件的字符串
      导包:commons-io.jar
      代码测试:WebUpload项目 Test.AServlet WebContent/form1.jsp

      5.commons-fileupload介绍
      代码测试:WebUpload项目 Test.BServlet WebContent/form2.jsp
      (1)作用:解析request中的上传数据,解析后的结果是一个表单项数据封装到一个FileItem对象中,我们只需要调用FileItem方法即可!
      (2)相关类:
      工厂类:DiskFileItemFactory
      解析器:ServletFileUpload
      表单项:FileItem
      (3)上传三步:
      1、创建工厂:
      DiskFileItemFactory factory=new DiskFileItemFactory();
      2、创建解析器:
      ServletFileUpload sfu=new ServletFileUpload(factory);
      3、使用解析器来解析request,得到FileItem集合
      List list=sfu.parseRequest(request)

      (4)FileItem
      1、boolean isFormField()
      是否为普通表单项,是返回true。返回false为文件表单项。
      2、String getFieldName()
      返回当前表单项的名称
      3、String getString(String charset)
      返回表单项的值
      4、String getName()
      返回上传文件的名称(文件表单项)
      要不乱码,必须加上:request.setCharacterEncoding(“utf-8”);
      5、long getSize()
      返回上传文件的字节数(文件表单项)
      6、InputStream getInputStream()
      返回上传文件的对应输入流(文件表单项)
      7、void write(File file)
      把上传文件的内容保存到指定的文件中(文件表单项)
      8、String getContentType()
      获取MIME类型 (文件表单项)

      6.上传的细节
      (1)把上传的文件放到WEB-INF目录下
      目的:不让浏览器直接访问到
      (2)文件名称相关问题
      1、有的浏览器上传的文件名是绝对路径,这需要切割。
      例如:D:files/老妈.jpg
      String filename=item.getName();
      int index=filename.lastIndexOf(“\”);
      if(index!=-1){
      filename=filename.subString(index+1);
      }
      2、文件名乱码或者普通表单项乱码:
      a).request.setCharacterEncoding(“utf-8”)
      因为fileUploa内部会调
      用request.getCharacterEncoding()
      b).servletFileUpload.setHeaderEncoding(“utf-8 ”)
      优先级比上一个方法高

      3、文件同名问题:
      我们需要为每个文件添加前缀,这个前缀不能重复,uuid
      filname=CommonUtils.uuid()+”_”+filename;

      (3)目录打散:不能在一个目录下存放过多文件
      a).首字母打散:使用文件名的首字母作为目录名称。例如:abc.txt,那么把文件存放在a目录下。如果a目录不存在,就创建。
      b).时间打散:使用当前日期作为目录
      c).哈希打散:
      通过文件名称得到int值,调用hashCode()
      把int值转换为16进制(0-9,A-F)
      获取16进制的前两位用来生成目录,目录为2层。
      例如:1B2C3D4E5F, 1/B/老妈.jpg
      代码测试:WebUpload项目 Test.CServlet WebContent/form3.jsp

      (4)上传文件的大小限制
      1、单个文件的大小限制
      sfu.setFileSizeMax() 单位:字节
      使用该方法,必须在parseRequest(request)解析开始之前。
      如果上传的文件超过限制,执行parseRequest(request)方法时,会抛出异常。FileUploadBase.FileSizeLimitExceededException
      2、整个请求所有数据大小限制
      sfu.setSizeMax() 单位:字节
      使用该方法,必须在parseRequest(request)解析开始之前。
      如果超过限制,执行parseRequest(request)方法时,会抛出异常。FileUploadBase. SizeLimitExceededException

      (5)缓存大小与临时目录
      概述:默认下,客户端上传文件时,服务器端先保存在内存中而不是硬盘。若文件过大,内存是不够的。
      缓存大小:超出多大,才向硬盘保存。默认10KB
      临时目录:向硬盘的什么目录保存。
      设置缓存大小和临时目录:
      new DiskFileItemFactory(20*1024,newFile(”f:/temp”))

      7.下载的概述
      (1)下载就是向客户端响应字节数据。把一个文件变成字节数组,使用response.getOutputStream()来响应给浏览器
      (2)原来我们响应的都是Html的字符数据

      8.下载的要求
      两个头一个流!(设置响应response的2个头1个流)
      (1) Content-Type:服务器传递给客户端的文件是什么MIME类型。
      ServletContext.getMimeType(String filename);
      (2) Content-Disposition :
      默认值inline,表示在浏览器窗口中打开!
      弹出下载框:attachment;filename=xxx
      (3) 流:要下载的文件的数据
      获取响应流:
      ServletOutputStream out=response.getOutputStream();
      获取文件的输入流:
      FileInputStream in=new FileInputStream(file);
      将输入流的数据写入到输出流中:
      IOUtils.copy(in,out);

      9.下载的代码演示
      代码测试:WebDownload项目 Test.AServlet

      10.下载的细节
      (1)下载的文件名出现中文乱码问题
      Firefox: Base64编码
      其他大部分浏览器使用:URL编码
      解决方法:WebDownload项目 Utils.DownUtils
      通用方法:filename=new String(filename.getBytes(“gbk”),”iso-8859-1”)


      JavaMail
      1.概述:是java提供的一组API,用来发送和接收邮件。
      2.收发邮件
      JavaWeb - 图15
      3.邮件相关的协议
      JavaWeb - 图16


      4.邮件服务器名称
      JavaWeb - 图17
      5.talnet发邮件(使用Base64编码)
      JavaWeb - 图18JavaWeb - 图19
      JavaWeb - 图20

      6.JavaMail发邮件
      代码测试:JavaMail项目 Test.Demo01类
      (1)导包:mail.jar activation.jar
      (2)核心类
      1、Session
      如果你得到了它,表示与服务器连接上了。JavaWeb - 图21

      2.MimeMessage
      它表示一个邮件对象。
      MimeMessage msg=new MimeMessage(session);
      设置收件人:msg.setFrom(new InternetAddress(“XXX@126.com”))
      设置发件人:msg.setRecipients(RecipientType.TO,”XXX@qq.com”);
      设置抄送人:msg.setRecipients(RecipientType.CC,”XXX@qq.com”);
      设置暗送人:msg.setRecipients(RecipientType.BCC,”XXX@qq.com”);
      设置主题:msg.setSubject(“xxx”);
      设置不带附件的正文:msg.setContent(“xx”,”text/html;charset=utf-8”);

      设置带有附件的正文:
      1.创建一个部件集合
      MimeMultipart list=new MimeMultipart();

      2.创建主体部件,并添加内容
      MimeBodyPart part1=new MimeBodyPart();
      part1. setContent(“xx”,”text/html;charset=utf-8”);
      MimeBodyPart part2=new MimeBodyPart();
      part2.attachFile(new File(“xx”));
      设置邮件中显示文件的名称:(并处理乱码问题)
      part2.setFileName(MimeUtility.encodeText(“大美女.jpg”));
      3.将主体部件添加到部件集合中
      list.addBodyPart(part1);
      4.将多部件添加到邮件的正文中
      一个MimeMessage只能有一个MimeMultipart
      msg.setContent(list);
      3.Transport
      它只有一个功能,就是发送邮件。
      Transport.send(msg);

      (3)案例1:发送不带附件的邮件
      代码实现:JavaMail项目 Test.Demo01类
      (4)案例1:发送带有附件的邮件
      代码实现:JavaMail项目 Test.Demo02类


      AJAX(js代码块)
      1.概述:异步的js和xml
      (1)它能使用js访问服务器,而且是异步访问!
      (2)服务器给客户端的响应一般是一个完整的html页面!但在ajax中因为是局部刷新,那么服务器就不用响应整个页面,而只是响应数据
      text:纯文本 xml
      json:它是js提供的数据交互格式。它在ajax中最受欢迎。

      2.异步交互和同步交互:
      同步:
      1、发一个请求,就要等待服务器响应结束,才能发第二个请求。中间的为等待时间。
      2、刷新的是整个页面
      JavaWeb - 图22

      异步:
      1、发一个请求,无需等待服务器的响应,就可以发第二个请求。
      2、可以使用js接收服务器的响应,然后使用js来局部刷新
      JavaWeb - 图23

      3.应用场景
      (1)百度搜索框提示
      (2)用户注册时(光标移开,立刻判断用户名是否被注册过)
      4.优缺点
      优点:
      (1) 异步交互:增强了用户的体验
      (2) 性能:服务器无需再响应整个页面,只需响应部分内容。服务器的压力减轻了。
      缺点:
      (1) Ajax不能应用在所有场景
      (2) 会无端的增加对服务器的访问次数,给服务器带来了压力

      5.AJAX发送异步请求(四步操作)
      AJAX其实只要学习一个对象:XMLHttpRequest,如果掌握了它,就掌握了AJAX
      (1) 第一步(得到XMLHttpRequest)
      大多数浏览器都支持:var xmlHttp=new XMLHttpRequest();
      IE6.0: var xmlHttp=new ActiveXObject(“Msxml2.XMLHTTP”);
      IE5.5以及更早版本的IE:
      var xmlHttp=new ActiveXObjcet(“Microsoft.XMLHTTP”);

      编写创建XMLHttpRequest对象的函数
      Function createXMLHttpRequest(){
      Try{
      return new XMLHttpRequest();
      }catch(e){
      Try{
      return new ActiveXObject(“Msxml2.XMLHTTP”);
      }catch(e){
      Try{
      return new ActiveXObjcet(“Microsoft.XMLHTTP”);
      }catch(e){
      alert(“哥们儿,你用的是什么浏览器?”);
      throw e;
      }
      }
      }
      }
      (2) 第二步(打开与服务器的连接)
      xmlHttp.open(): 用来打开与服务器的连接,需要三个参数:
      请求方式:get或post
      请求的URL: 指定服务器端资源。例如:/TestSession/AServlet
      请求是否为异步:true表示发送异步请求,否则同步请求。
      例如:xmlHttp.open(“GET”,” /TestSession/AServlet”,true);

      (3) 第三步(发送请求)
      xmlHttp.send(参数值) 参数为请求体的内容。
      GET请求: xmlHttp.send(null);
      POST请求:(发送请求时需要带有参数,一般都用POST请求)
      设置请求头(Content-Type)
      xmlHttp.setRequestHeader(“Content-Type”,”application/x-www-form-urlencoded”);
      设置请求体:
      xmlHttp.send(“username=zhangsan&password=123”);

      (4) 第四步:
      对xmlHttp对象的5个状态上注册监听器:onreadystatechange
      xmlHttp对象一共有5个状态:
      0状态:刚创建,还没有调用open()方法
      1状态:请求开始,调用了open()方法,但没有调用send()方法
      2状态:调用完了send()方法了
      3状态:服务器已经开始响应,但不表示响应结束了
      4状态:服务器响应结束(通常只关心这个状态)
      得到xmlHttp对象的状态:
      var state=xmlHttp.readyState //可能是0,1,2,3,4
      得到服务器响应的状态码:
      var status=xmlHttp.status; //可能是200,404,500
      得到服务器响应的内容:
      var content=xmlHttp.responseText;
      //得到服务器响应文本格式的内容
      var content=xmlHttp.responseXML;
      //得到服务器响应xml形式的字符串内容,它是Document对象

      服务器端:
      设置响应类型(ContentType):text/xml;charset=utf-8

      xmlHttp.onreadychange=function(){
      //xmlHttp的5个状态都会本方法
      if(xmlHttp.readyState==4&&xmlHttp.status==200){
      //双重判断;是否为4状态,是否为200

      //获取服务器的响应内容
      var text=xmlHttp.responseText;
      }
      }

      6. 案例1:HelloWord
      代码实现:TestAjax项目 服务器端:Test.AServlet类 客户端:ajax1.jsp

      7. 案例2:发送Post请求(如果发送请求时带有参数,一般用Post请求)
      xmlHttp.send(“POST”,..);
      设置请求头:
      xmlHttp.setRequestHeader(“Content-Type”,”application/x-www-form-urlencoded”);
      设置请求体:
      xmlHttp.send(“username=zhangsan&password=123”);
      代码实现:TestAjax项目 服务器端:Test.BServlet类 客户端:ajax2.jsp

      8. 案例3:注册表单之校验用户名是否已被注册
      代码实现:TestAjax项目 服务器端:Test.CServlet类 客户端:ajax3.jsp

      9.案例4:响应内容为xml
      (1)
      服务器端:
      设置响应类型:ContentType: text/xml;charset=utf-8
      (2)客户端:var doc=xmlHttp.responseXml;
      代码实现:TestAjax项目 服务器端:Test.DServlet类 客户端:ajax4.jsp

      10.案例5:省市联动
      代码实现:TestAjax项目
      服务器端:Test.ProvinceServlet类 Test.CityServlet类
      客户端:ajax5.jsp
      JavaWeb - 图24

      11.Xstream (代码测试: TestAjax项目 Xstream包中所有类)
      (1)作用:可以javabean转换为(序列化为)xml
      (2)使用步骤:
      1、导包:
      核心jar包: xstream-1.4.4.jar(G:/jar包)
      必须依赖包:xpp3_min-1.1.4c.jar(G:/jar包)
      2、创建对象
      XStream xs=new XStream();
      3、将javabean转化为xml类型的字符串
      String xml=xs.toXML(javabean对象);
      方法:
      (1)
      将javabean的成员变量— xml中的属性
      xs.userAttributeFor(javabean.class,”属性名”);
      (2)
      将xml类型的字符串中的部分标签改名
      xs.alias(“新名”,java类.class);
      (3)
      删除无用的javabean的集合类型的成员变量。不会将该变量的子标签也删除了。
      xs.addImplicitCollection(javabean.class,”删除的属性名”)
      (4)
      删除无用的javabean的普通成员变量,就是不想让某些javabean属性出现在xml字符串中。会删除变量的所有子标签
      xs.omitField(javabean.class,”要删除的普通成员变量名”);
      12.JSON
      (1)json是什么?
      它是js提供的数据交换格式!
      (2)json的语法:
      {} :是对象
      属性名:必须使用双引号括起来!单引号不可以!
      属性值的种类:
      数字、
      字符串 : 使用双引号
      null
      数组 :使用[]括起来
      对象 : 使用{}括起来
      Boolean
      (3)json的应用
      案例1:使用json
      代码测试:TestAjax项目 json1.jsp

      案例2:异步请求,响应json给客户端json2.jsp
      代码测试:TestAjax项目 Test.EServlet json2.jsp
      (4)json和xml进行比较
      可读性: xml胜出
      解析对象:json是js自带的对象,简单。
      流行度:在js中json更受欢迎。
      (5)json-lib的使用
      1.导包:
      json-lib.jar commons-logging commons-collections
      commons-beanutils commons-lang xom ezmorph
      2.作用:可以把javabean对象转换成json字符串
      3.核心类
      JSONObject  Map
      1、toString() 输出json
      2、JSONObject map=JSONObject.fromObject(person);
      把javabean对象转换成JSONObjcet对象.
      3、JSONObject map=JSONObject.fromObject(List类型);
      不可以把数组中javabean对象转换成JSONObject对象

      JSONArray  List
      1、toString() 输出json
      2、JSONArray list=JSONArray.fromObject(person);
      把单个对象/List转换成JSONArray对象
      4.演示json-lib小工具
      代码测试: TestAjax项目 JsonLib.Demo01类