JavaWeb

Web应用程序

WEB,在英语中web即表示网页的意思,它用于表示Internet主机上供外界访问的资源。Internet上供外界访问的Web资源分为:

1.静态web资源(如html 页面):指web页面中供人们浏览的数据始终是不变。
静态web资源开发技术:HTML+CSS+Javascript

2.动态web资源:指web页面中供人们浏览的数据是由程序产生的,不同时间点 访问web页面看到的内容各不相同
动态web资源开发技术:JSP/Servlet

在Java中,动态web资源开发技术统称为Javaweb。
学习web开发,需要先安装一台web服务器,然后再在web服务器中开发相应的web资源,供用户使用浏览器访问。

WEB应用程序指供浏览器访问的程序,通常也简称为web应用。一个web应用由多个静态web资源和动态web资源组成。Web应用开发好后,若想供外界访问,需要把web应用所在目录交给web服务器管理。

Web服务器是指驻留于因特网上某种类型计算机的程序,是可以向发出请求的浏览器提供文档的程序。


图片1.png

BC/CS
CS:客户机/服务器 结构 网络游戏客户端,QQ等
BS:浏览器/服务器 结构 百度,淘宝,新浪

Web应用:基于HTTP协议的应用程序
属于 B/S架构
浏览器客户端:通过HTTP协议向服务器发出请求
服务器:通过HTTP协议向客户端响应结果

HTTP协议:
是由W3C制定的一种网络应用层协议,规定了浏览器和web服务器之间如何通信
以及通信的数据格式
特点:一次请求,一次连接
优点:利用有限的连接,为近可能多的请求服务


http.png
Tomcat:开源的Java Web服务器

tomcat目录结构
bin:主要存放一些可执行文件(比如启动startup.bat以及关闭的shutdown.bat)
conf:配置文件;
lib:第三方依赖jar包;
logs:日志目录;
temp:临时文件目录;
work:jsp经过翻译成Servlet再翻译成.class的文件等;
webapps:真正的web应用可以部署的位置;

测试Tomcat服务器是否可以正常运行

配置环境变量
1.名称:JAVA_HOME
变量值: jdk 的路径(例:C:\Program Files (x86)\Java\jdk1.8.0_111)

2.名称:CLASS_PATH
变量值:%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar

3.系统环境变量中有一个path选中后选择编辑
;%JAVA_HOME%\bin;

进入 tomcat 的 bin 目录,然后双击 startup.bat 。

Web项目的创建以及配置Tomcat
c1.gif

填写项目名称 - version 2.5 -Next


c2.gif

目录结构


c3.gif
配置Tomcat

Window - Preferences - Server - Runtime - Add
选择需要配置Tomcat的版本 Tomcat 8.0
点击 Next - Browser
选择相应版本的Tomcat所在本地路径

测试是否配置成果

在WebContent下 创建index.html
将项目部署到Tomcat内
启动Tomcat服务器
通过浏览器访问 localhost:8080/项目名/index.html

Web server只能访问静态资源,为了提高是服务的扩张性,使用Servlet

什么是Servlet:

Java Servlet是和平台无关的服务器端组件,它运行在Servlet容器中。Servlet容器负责Servlet和客户的通信以及调用Servlet的方法,Servlet和客户的通信采用“请求/响应”的模式。

Servlet本质就是一个运行在Servlet容器中的Java类,Servlet容器就是Tomcat

Servlet的作用
创建并返回基于客户请求的动态HTML页面。
与其它服务器资源(如数据库或基于Java的应用程序)进行通信

创建Servlet : 继承HttpServlet,实现doGet( ),doPost( )方法

通过提交表单 访问Servlet

设计表单:文本框,按钮
<form>属性method 表示提交表单的方法
Get: - -doGet( )
采用路径传参,参数在传递过程中可见(地址栏)
隐私性差
传参能力有限,只能传少量参数
所有的请求默认都是GET请求

Post:- - doPost( )
采用实体内容传参,参数在传递过程中不可见
隐私性好
实体内容专门用来传参,大小不受限制
在form上加method="post"

浏览器发送请求后,如何找到Servlet

配置web.xml

2.0 web项目会自动创建该文件
<servlet>
<servlet-name>Servlet1</servlet-name>//指定servlet类的唯一标识
<servlet-class>test.Servlet1</servlet-class>//servlet的全类名(包名.类名)
</servlet>

<servlet-mapping>//设定servlet与客户端的映射路径
<servlet-name>Servlet1</servlet-name>//与<servlet>中保持一致
<url-pattern>/Servlet1</url-pattern>//用于设定请求路径
</servlet-mapping>
3>关于Servlet路径配置问题详解
<url-pattern>
路径匹配:
/AServlet --http://localhost:8080/项目名/AServlet
/ABC/AServlet --http://localhost:8080/项目名/ABC/AServlet
/ABC/ABC/AServlet http://localhost:8080/项目名/ABC/ABC/AServlet
/ABC/ABC/* --http://localhost:8080/项目名/ABC/ABC/任意
/* -- http://localhost:8080/项目名/任意
/ 相当于 /*

        后缀名匹配:
            *.do ==> struts
            *.action ==> struts2
            *.html ==> 

Servlet的生命周期

①服务器加载Servlet

②创建Servlet实例
--只有第一次请求Servlet时,创建Servlet实例,调用构造器

③初始化init()
--只被调用一次,在创建好实例后立即被调用,用于初始化当前Servlet

④service()处理用户请求
--可以被多次调用,每次请求都会调用service方法,实际用于响应请求的,根据用户请求的类型(get或者post),调用doGet或者doPost方法。

⑤destory()销毁
--只被调用一次,在当前Servlet所在的WEB应用被卸载前调用,用于释放当前Servlet所占用的资源

//设置加载时机,默认访问servlet时加载
//值为1时,启动过程中便开始加载
//多个servlet之间值越小,越优先
<load-on-startup></load-on-startup>

Servlet运行原理
s1.png

request对象

1.提取客户端提交表单的信息
2.提取HTTP请求报头的信息
3.在服务器段保存数据,进行数据传递
4.处理Web资源跳转

HttpServletRequest常用的方法:
String getParameter(String name)
--根据请求参数的名字,返回参数值,特别常用

产生乱码的原因:浏览器的编码格式和服务器的解码格式不同
解决乱码:只要确保编码和解码一致,就绝对没有问题

Get
修改Tomcat配置文件,Server.xml第65行加 URIEncoding="UTF-8"
<Connector port="8080" protocol="HTTP/1.1"  URIEncoding="UTF-8"
        connectionTimeout="20000"   redirectPort="8443" />
    
POST
因为Post解码是在第一次调用getParameter之前,那么解决乱码只需要在调用该方法之前设置编码:
            request.setCharacterEncoding("UTF-8");      

获取HTTP请求头信息

1.请求行
2.请求头
3.请求空行
4.请求数据

    request.getMethod(): 请求方式
    request.getRequestURI(): /项目名/Servlet映射名
    request.getServletPath(): /Servlet映射名
    request.getContextPath(): /项目名
    request.getScheme(): http
封装好的方法.
        request.getContentType(): null
        request.getLocale(): zh_CN
        request.getQueryString(): name=tom&age=18
        request.getRequestURL(): http://localhost:8080/Day08-request/AServlet
        request.getRemotePort(): 52074
        request.getServerName(): localhost
        request.getServerPort(): 8080
        request.getRemoteAddr() :客户端IP

设计用户注册功能
1.获取表单注册信息
2.添加到数据库

设置响应信息 response对象

1.设置响应信息的字符集
2.向客户端响应信息
3.Web资源跳转

response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");//设置响应内容的类型
        PrintWriter pw=response.getWriter();//获取输出流 ,向浏览器响应信息
        String html="<!DOCTYPE html>"
                +"<html>"
                +"<meta charset='UTF-8'>"
                +"<title>Insert title here</title>"
                +"</head>"
                +"<body>"
                +"abc"
                +"</body>"
                +"</html>";
        pw.write(html);//写内容
        pw.close();//关闭流

设计程序
注册成功后,在网页上显示 - - 注册成功

完善用户注册
用户信息符合规定条件 才允许注册
如何注册成功 显示登陆页面

12306项目驱动

软件开发基本流程

需求分析
成果物:页面原型 需求分析文档
相关系统分析员向用户初步了解需求,然后用相关的工具软件列出要开发的系统的大功能模块,每个大功能模块有哪些小功能模块,对于有些需求比较明确相关的界面时,在这一步里面可以初步定义好少量的界面。系统分析员深入了解和分析需求,根据自己的经验和需求用WORD或相关的工具再做出一份文档系统的功能需求文档。这次的文档会清楚列出系统大致的大功能模块,大功能模块有哪些小功能模块,并且还列出相关的界面和界面功能。系统分析员向用户再次确认需求。

数据库设计
基于需求分析的成果进行数据库的设计,包含表,列以及关联关系,初始数据。

概要设计(开发框架的搭建,核心技术的选择)
首先,开发者需要对软件系统进行概要设计,即系统设计。概要设计需要对软件系统的设计进行考虑,包括系统的基本处理流程、系统的组织结构、模块划分、功能分配、接口设计、运行设计、数据结构设计和出错处理设计等,为软件的详细设计提供基础。

详细设计
(通过UML建模实现 类图 时序图)
在概要设计的基础上,开发者需要进行软件系统的详细设计。在详细设计中,描述实现具体模块所
涉及到的主要算法、数据结构、类的层次结构及调用关系,需要说明软件系统各个层次中的每一个
程序(每个模块或子程序)的设计考虑,以便进行编码和测试。应当保证软件的需求完全分配给整个
软件。详细设计应当足够详细,能够根据详细设计报告进行编码。

编码
在软件编码阶段,开发者根据《软件系统详细设计报告》中对数据结构、算法分析和模块实现等方面的设计要求,开始具体的编写程序工作,分别实现各模块的功能,从而实现对目标系统的功能、
性能、接口、界面等方面的要求。在规范化的研发流程中,编码工作在整个项目流程里最多不会
超过1/2,通常在1/3的时间,所谓磨刀不误砍柴功,设计过程完成的好,编码效率就会极大提高
,编码时不同模块之间的进度协调和协作是最需要小心的,也许一个小模块的问题就可能影响了
整体进度,让很多程序员因此被迫停下工作等待,这种问题在很多研发过程中都出现过。

测试
测试编写好的系统。交给用户使用,用户使用后一个一个的确认每个功能。软件测试有很多种:
按照测试执行方,可以分为内部测试和外部测试;按照测试范围,可以分为模块测试和整体联调;
按照测试条件,可以分为正常操作情况测试和异常情况测试;按照测试的输入范围,可以分为全
覆盖测试和抽样测试。以上都很好理解,不再解释。总之,测试同样是项目研发中一个相当重要
的步骤,对于一个大型软件,3个月到1年的外部测试都是正常的,因为永远都会有不可预料的问
题存在。完成测试后,完成验收并完成最后的一些帮助文档,整体项目才算告一段落,当然日后
少不了升级,修补等等工作,只要不是想通过一锤子买卖骗钱,就要不停的跟踪软件的运营状况
并持续修补升级,直到这个软件被彻底淘汰为止。

数据库的范式
消除重复数据,减少冗余数据,进行数据库设计的方式
第一范式:数据表中每一个属性都是不可分的基本数据项,同一个列中不能有多个值
第二范式 :要求数据表中的每个实例或行必须是唯一的,依赖于主键

所有列必须依赖主键(支持联合主键)
第三范式;一个数据表不能包含其他表中非主键的列

MD5字符串加密处理

MD5是一种不可逆的加密算法
网站一般会保存用户密码:
为了不让数据库管理员看到用户的密码。
比如你输入的密码明明是这样的:123456
网站加密后的密码可能是这样的:E10ADC3949BA59ABBE56E057F20F883E

public final static String md5(String s) {
        char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f' };

        try {
            byte[] btInput = s.getBytes();
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            mdInst.update(btInput);
            byte[] md = mdInst.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    

常见错误:
404:服务器依据请求地址找不到相应的资源
1.没有将项目部署到服务器 2.<servlet-name>不一致 3.浏览器中请求地址有误
500:系统出错,程序在运行过程中出现问题
405:方法声明错误

2.request的请求转发和包含功能.
转发:
服务器接到客户端的请求后,将请求转发给WEB应用内的其他资源处理

转发:request.getRequestDispatcher(“url”).forward(req,res);
url中的/可以写,也可以不写,建议写。默认相对于项目名进行跳转

3.request域的应用.
原理:
在request对象中含有一个map.这个map就是request域.
作用:
在将来开发中. 使用请求转发时,servlet处理完数据, 处理结果要交给jsp显示. 可以使用request域将处理结果由servlet带给jsp显示.

操作:
    1.setAttribute  存入一个键值对
    2.getAttribute  通过键取出值
    3.getAttributeNames 获得域中所有键
    4.removeAttribute 跟据键移除一个键值对        
    
request的范围:
    一个request对象对应一个request域(map).
    系统当前有多少个request就有多少request域.

重定向
服务器接收到客户端的请求之后,返回给客户端一个URL,客户端根据URL
重新发出HTTP请求
重定向:response.sendRedirect(“url”);
url:如果不以/开头,表示相对于当前路径进行跳转(localhost:port/项目名/)
response.sendRedirect(“index.html”)
url:如果以/开头,表示相对于服务器域名进行跳转(localhost:port/)
response.sendRedirect(request.getContextPath+“/index.html”)

图片3.png

共同点:都是用来解决web组件(Servlet/JSP) 之间的跳转问题

两种方式的区别:
1.重定向支持项目资源外的跳转(站外跳转),转发只能站内跳转。
2.请求对象个数:重定向2个 ,转发1个。
3.重定向后浏览器地址栏发生改变,转发不变。
4.请求转发性能好于重定向

至于选用哪种方式取决于数据共享的方式。如果采
用请求对象做数据的共享,则必须选用请求转发的方式进行资源的跳转。如果不选用请求对象做数据的共享,都可以。

解决项目中不同的组件(Servlet)之间地跳转(降低耦合度):
一个Servlet只去处理一个功能
使用规律:一般在增加,修改,删除之后转到查询


661d.png

设计程序
注册成功- - 跳转到登陆页面
登陆成功- - 跳转到系统主页
登陆失败- - 重新回到 登陆页面

完善12306项目的注册功能以及登陆功能

JSP
用户输入错误的信息时,做出相应的提示。登录到主页时,显示当前用户的信息
对于这些信息需要在什么时候设置,就是在对一次请求做出响应时,将相应的信息
传递到页面当中

想要共享数据,就需要在后台进行数据的处理。需要将数据封装起来,在网页中来接受后台封装好的数据。对HTML来说,它是一种静态页面,用来制作网页,显示网页内容没有问题,但是想要处理动态的数据时,用来访问后台传递的数据时,是没有这个功能的,需要用JSP来解决这个问题

什么是JSP: JSP:动态网页技术。
如何编写JSP:在WebContent下创建JSP文件 修改字符集,
Eclipse-window - preferences - 搜索 file -JSP files - utf-8 - apply -OK

JSP本质是Servlet,浏览器与服务器连接后,服务器的通信组件会先找到JSP,tomcat将它翻译成servlet(jsp->.java->.class),初始化调用_jspInit(),_jspService(),_jspDestory()之后与servlet原理相同。

JSP的页面元素


JSP脚本元素.png

1.网页内容,HTML编写

2.指令<%@ %> 用来设置JSP的数据项
Page:用于定义和页面相关的属性信息
Language=”java” JSP支持的脚本语言,目前仅支持Java
ContentType:告诉浏览器输出文本的格式及编码
PageEncoding:设置文件的编码,定义输出流的字符集编码,默认iso-8859-1
Charset:设置文本内容的字符集
Import=”java.util.*” 将指定的类引入到JSP上
JSP中page属性可以写多个,但建议每个page中的属性只写一次,import除外。

include指令:引入其他jsp

修改为了使项目默认部署到tomcat安装目录下的webapps中,show view—>servers—>找到需要修改的tomcat—>右击
①停止eclipse内的Tomcat服务器(stop)
②删除该容器中部署的项目(add and remove)
③清除该容器相关数据(clean)
④打开tomcat的修改界面(open)
⑤找到servers location,选择第二个(User tomcat Installation)
⑥修改deploy path为webapps
⑦保存关闭需要说明的是①②③必须操作,否则下面的步骤会被置灰无法操作。

3.嵌套java代码,处理动态数据(脚本元素)
JSP表达式:<%= %>
内容编译后成为变量, 表达式 ,有返回值的方法,会显示结果

需要导入对应的java包 import="java.util.Date" 
<%= new Date() %>

JSP脚本: <% %>
内容编译后成为写在方法里的java代码片段

<%
    for(int i=0;i<=5;i++){

     }
%>

JSP声明:<%! %>
内容编译后成为的成员变量(属性)或成员方法

<%!
        int a;
        public void show(){
            
        }
        
%>

脚本元素之间可以相互嵌套

    <%!
        public void show(){
    %>      
        <%
            for(int i=0;i<=5;i++){
        %>
                <%=i %>
        <%
            }
        %>
    <%!     
        }
    %>
jsp和servlet的区别和联系:

1.jsp经编译后就变成了Servlet.
(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类)

2.jsp更擅长表现于页面显示,servlet更擅长于逻辑控制.

3.Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到.Jsp是Servlet的一种简化,使用Jsp只需要完成程序员需要输出到客户端的内容,Jsp中的Java脚本如何镶嵌到一个类中,由Jsp容器完成。而Servlet则是个完整的Java类,这个类的Service方法用于生成对客户端的响应。

JSP的9大内置对象
JSP内置对象.png

JSP如何处理后台封装的参数
Web层共享数据的范围:
应用对象:ServletContext 整个Web项目都可以使用
会话对象:HttpSession 浏览器从打开到关闭,就是一个会话。
请求对象:HttpServletRequest 在一次请求中公用一个对象
页面对象:PageContext 在当前页面中有效
原则:尽量使用范围小的共享数据对象

利用request作数据共享:
request.setAttribute(数据名,数据值) / request.getAttribute(数据名)
session. setAttribute(数据名,数据值) / session. getAttribute(数据名)
在JSP页面中获取后台传递的数据,默认是Object,需要类型转换

<%
 String error=(String)request.getAttribute("error");
%>

<form action="Servlet1">
    用户名<input type="text" name="username"> 
    <span>
      <%
        if(error!=null){
      %>
        <%=error %>
      <%
        }
      %>
    </span><br>
    用户名<input type="password" name="pwd"> 
    <input type="submit"> 
</form>

设计程序
登陆失败 重新回到登陆页面 在登陆页中显示错误提示

完成12306项目 登陆页错误提示

会话对象HttpSession

指的是一段时间内,单个客户端与服务器之间多次的交互过程

作用范围:浏览器从打开到关闭,都可以使用

会话对象的作用

保证同一个客户端,多次请求之间的联系

创建HttpSession

HttpSession session=request.getSession();

session.setAttribute(key, value);
JSP中获取Session
HttpSession sessions=request.getSession();

sessions.getAttribute("")

设计程序
登陆成功后,在主要显示当前用户名

销毁Session对象
session.invalidate();

设计程序
主页中设计退出按钮,完成退出功能
正常情况 退出之后 跳转到登陆页
这里为了验证是否退出成功,可以重新跳转到主页 查看用户名是否存在
如果不存在 表示session对象已经被销毁 退出成功

完成12306项目 主页退出功能
可以设计退出后重定向到主页,看是否存在用户名
12306项目网页用frame进行嵌套的,则无法使用转发进行页面跳转

验证码
编写验证码工具类
public final class ImageUtil {
    
    // 验证码字符集
    private static final char[] chars = { 
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 
        'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
    // 字符数量
    private static final int SIZE = 4;
    // 干扰线数量
    private static final int LINES = 5;
    // 宽度
    private static final int WIDTH = 80;
    // 高度
    private static final int HEIGHT = 40;
    // 字体大小
    private static final int FONT_SIZE = 30;

    /**
     * 生成随机验证码及图片
     */
    public static Object[] createImage() {
        StringBuffer sb = new StringBuffer();
        // 1.创建空白图片
        BufferedImage image = new BufferedImage(
            WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        // 2.获取图片画笔
        Graphics graphic = image.getGraphics();
        // 3.设置画笔颜色
        graphic.setColor(Color.LIGHT_GRAY);
        // 4.绘制矩形背景
        graphic.fillRect(0, 0, WIDTH, HEIGHT);
        // 5.画随机字符
        Random ran = new Random();
        for (int i = 0; i <SIZE; i++) {
            // 取随机字符索引
            int n = ran.nextInt(chars.length);
            // 设置随机颜色
            graphic.setColor(getRandomColor());
            // 设置字体大小
            graphic.setFont(new Font(
                null, Font.BOLD + Font.ITALIC, FONT_SIZE));
            // 画字符
            graphic.drawString(
                chars[n] + "", i * WIDTH / SIZE, HEIGHT / 2);
            // 记录字符
            sb.append(chars[n]);
        }
        // 6.画干扰线
        for (int i = 0; i < LINES; i++) {
            // 设置随机颜色
            graphic.setColor(getRandomColor());
            // 随机画线
            graphic.drawLine(ran.nextInt(WIDTH), ran.nextInt(HEIGHT),
                    ran.nextInt(WIDTH), ran.nextInt(HEIGHT));
        }
        // 7.返回验证码和图片
        return new Object[]{sb.toString(), image};
    }

    /**
     * 随机取色
     */
    public static Color getRandomColor() {
        Random ran = new Random();
        Color color = new Color(ran.nextInt(256), 
                ran.nextInt(256), ran.nextInt(256));
        return color;
    }
    
}

Servlet中获取验证码
                // 生成验证码图片
                Object[] objs = ImageUtil.createImage();
                // 将验证码存入session
                String imgcode = (String) objs[0];
                request.getSession().setAttribute("imgcode", imgcode);
                // 将图片输出给浏览器
                BufferedImage img = (BufferedImage) objs[1];
                response.setContentType("image/png");
                // tomcat自动创建输出流
                // 目标就是本次访问的浏览器
                OutputStream os = response.getOutputStream();
                ImageIO.write(img, "png", os);
                os.close();
客户端调用验证码
<img src=Servlet映射路径" alt="验证码"
  onclick="this.setAttribute('src','Servlet映射路径?x='+Math.random())"/>
会话对象Cookie

HTTP是无状态协议,服务器无法记住浏览器,cookie和session能够对状态进行管理,让服务器记住浏览器。
状态:用来证明浏览器来过服务器的表示数据
Cookie是在客户端保存信息的技术
Cookie 是一小段文本信息,伴随着用户请求和页面在 Web 服务器和浏览器之间传递。用户每次访问站点时,Web 应用程序都可以读取 Cookie 包含的信息。
cookie原理.
让浏览器记住键值对.是向响应头中添加一下头即可:
set-Cookie:name=tom;
浏览器记住之后,向服务器发送键值对,是在请求头中添加下面的信息:
Cookie: name=tom;

创建 Cookie
创建Cookie对象 设置存储的内容
Cookie cookie=new Cookie("username","chen");
设定cookie的保存时长,单位 秒
cookie.setMaxAge(60*60*5);
将cookie添加到response对象中
response.addCookie(cookie);

cookie细节问题:
1.浏览器记多久?
默认是在会话期间有效.(关闭浏览器,cookie就被删除).(有效时间-1)
2.有效时间如何设置?
//设置cookie的最大有效时间
1>设置一个正数,标示最大有效时间.单位是秒
//cookie.setMaxAge(60*60);
2>设置为-1 , 就是相当于默认有效时间, 浏览器关闭就消失.
//cookie.setMaxAge(-1);
3> 标示cookie的有效时间为0.发送到浏览器就消失了.

JSP中获取Cookie
<%
    String name="";
    Cookie[] cookies=request.getCookies();
    /* 通过cookie中的key 获取需要的cookie元素    */
    for(Cookie cookie:cookies){
        if(cookie.getValue().equals("chen")){
            name=cookie.getValue();
        }
    }
%>
Cookie的原理
图片6.png

Cookie的特点:
存储在浏览器端,隐私性差,安全性较低。
保存在本地磁盘中,临时存储。
用于数据的传递

设计程序
登陆成功的用户,关闭浏览器后。下一次打开浏览器时
登陆页自动显示用户名和密码

解决自动登录问题:Cookie

图片5.png

当用户访问到一在创建这个SESSION的时候,服务器首先检查这个用户发来的请求里是否包含了一个SESSION ID,如果包含了一个SESSION ID则说明之前该用户已经登陆过并为此用户创建过SESSION,那服务器就按照这个SESSION ID把这个SESSION在服务器的内存中查找出来(如果查找不到,就有可个服务器,如果服务器启用Session,服务器就要为该用户创建一个SESSION,能为他新创建一个),如果客户端请求里不包含有SESSION ID,则为该客户端创建一个SESSION并生成一个与此SESSION相关的SESSION ID。这个SESSION ID是唯一的、不重复的、不容易找到规律的字符串,这个SESSION ID将被在本次响应中返回到客户端保存,而保存这个SESSION ID的正是COOKIE,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。

3.原理
浏览器第一次访问服务器,服务器会在内存中开辟一个空间(session),并把session对应的ID发送给浏览器.
那么下次浏览器再去访问服务器,会把sessionID 交给服务器,服务器通过sessionID 找到刚才开辟的空间.
以上就是session的原理.
4.session细节问题
1> 服务器让浏览器记住sessionID的cookie 默认过期时间是 (-1)==> 关闭浏览器 cookie就丢失 ==> cookie丢失 sessionID就丢失 ==> 找不到服务器的session
2> session中除了 4个操作 map的方法之外,还有哪些方法.
long getCreationTime() 获得创建时间
String getId() 获得sessionID
long getLastAccessedTime() 获得最后一次访问时间
int getMaxInactiveInterval() 获得session的寿命
void setMaxInactiveInterval(int interval) 设置session的过期时间
void invalidate() 让session立即失效
boolean isNew()
3> 关于设置session的最大有效时间
默认是30分钟. ==> 在tomcat的web.xml中 <session-config> 配置的.
如何修改session的过期时间?
1.修改在tomcat的web.xml中 <session-config> ==> 影响服务器中的所有项目
2.在项目的web.xml中 加入<session-config> 配置.==> 影响的是当前项目
3.通过setMaxInactiveInterval(int interval)方法设置.==> 当前操作的session

4>(了解内容)URL重写
    如果浏览器 禁用cookie功能不能保存任何cookie.那么session技术要是用 cookie来保存sessionID. 没有cookie怎么保存?
        使用url重写解决该问题.
        将页面中所有的连接 末尾全都加上 cookieid的参数. 这样用户点击连接访问网站,通过url把SeesionID带到了服务器.这样就解决了.
        但是 互联网行业没有这么干的.

当用户长时间没有做出任何指令和动作时,自动退出。
解决方式:修改session的超时时间,默认30分钟。当服务器(tomcat)检查到用户超过这个时间没有任何动作时,将session销毁。从session不活动的时候开始计算,如果session一直活动,session就总不会过期。从该Session未被访问,开始计时; 一旦Session被访问,计时清0;在web.xml配置<session-config> <session-timeout></~></session-config>

EL表达式:代替JSP中的JAVA代码,作为动态数据的输出。
JSP表达式如果为空值时,会报空指针异常,在代码上需要做判断处理
而EL表达式则不会有这样的问题
语法:${表达式}
可以访问req和res中的数据,可以访问cookie和其他请求报文中的信息

EL表达式默认从4个内置对象中取值,并且是依次取值。(page,request ,session,appliction)
从小的作用域开始查找对应的数据对象,找到为止。
在实际开发中,不同的作用域不建议起相同的数据名

Cookie不是EL的内置对象,取值 ${cookie.参数名.value}

练习:用EL表达式获取bean(实体类)中的属性和方法 ${user.username}

数据库连接池

数据库连接的建立和资源的关闭都是消耗巨大的
每次操作数据库都要打开,关闭物理连接,系统的性能严重受损

解决方案:
系统初始运行的时候,主动建立足够的连接,组成一个连接池。
每次程序请求数据库连接时,无需重新打开数据库连接,而是从连接池
中获取已有的连接。使用完后,不再关闭,而是归还给连接池。

private static BasicDataSource ds;// 数据库连接池

    static {

            ds = new BasicDataSource();
            ds.setDriverClassName("com.mysql.jdbc.Driver");// Class.forName(...)
            ds.setUrl("jdbc:mysql://localhost:3306/mysql");
            ds.setUsername("root");
            ds.setPassword("root");
            ds.setInitialSize(5);
            System.out.println(ds.getInitialSize());
    }

    /**
     * 获取数据库连接
     */
    public static Connection getConnection() throws Exception {

        return ds.getConnection();
    }

    public static void closeConnection(Connection conn) {

        try {
            conn.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

功能显示查询数据 (组合查询)
由于查询的条件不同,所有显示的数据也会有所不同(内容和数量)
HTML本身的标签无法实现,需要使用自定义标签JSTL

jstl.jar在jsp中通过taglib指令引入,才可以使用.<%@ taglib uri=”” prefix=”” %>
uri:是自定义标签库的地址 prefix:标签库的别名


jstl.png

<c:foreach items=”” var =””> </> 循环遍历


foreach.png

分页查询


复合查询.png

删除功能

ServletConfig对象是什么?
封装了servlet在web.xml中的配置.
方法:
1>getServletName ==> 获得配置文件中 <servlet-name> 元素的内容
2>getInitParameter ==> 根据 <init-param>中的 <param-name> 获得 </param-value>
<init-param>
<param-name>name</param-name>
<param-value>tom</param-value>
</init-param>
3>getInitParameterNames 返回所有<param-name> .

HTTPServlet:
1.因为我们web项目基于HTTP协议,所以Service方法中传过来的request,response对象都是 基于HTTP协议的.
也就是HttpServletReueqst,也就是HttpServletResponse. 它帮我们进行了强转.
2.我们有可能在不同的请求方式时做不同的事情. 根据请求方式不同,调用不同的方法
例如 GET --> doGet()
POST ==> doPost();

相关对象之 ---- ServletContext
1.获得: servletConfig ==> getServletContext
2.servletContext 的作用
1> servletContext 封装了web.xml 中的配置
<context-param>
<param-name>name</param-name>
<param-value>jerry</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>1234</param-value>
</context-param>

                getInitParameterNames();  ==> 获得所有键
                getInitParameter(key);  ==> 根据键获得对应的值
    2> servlet技术中3大域对象之一. 
        ServletContext对应着Application(应用)域.利用了一个项目中只有一个ServletContext实例的特点.
在servletContext中放置了一个map用作数据通信.
        这个Map就是所谓域.
            关于域的操作,有4个.
                放入键值对 setAttribute(key,value)
                通过键取值 getAttribute(key)
                通过键删除 removeAttribute(key)
                遍历所有键 getAttributeNames()
            application ==> servletContext
            session ==> 
            request ==> 
    3>获得项目中资源.  
        所有servletContext中关于路径的获得,相对路径都是相对的 WebRoot(项目根)下
            getRealPath  ==> 通过相对路径获得绝对路径
            getResourceAsStream ==> 根据相对路径获得指定资源流
    
3.servlet技术中对象的范围
    servlet ==> 项目启动期间一个servlet只有一个servlet实例
    request ==> 项目启动期间,request对象的数量,要看当前有多少个请求正在处理.
    response ==> 同上.
    servletConfig ==> 一个servlet实例对应一个servletConfig对象
    servletContext ==> 整个项目中,永远只有一个servletContext实例存在

在web.xml中配置错误页面拦截(报错后跳转到错误页面)

正常情况系统不应该将报错的页面显示给用户,或者说不应该让用户看到。对于一些懂技术的人来说,看到报错信息,可能会找到系统的漏洞,造成不必要的麻烦。
解决:系统报错时,根据错误类型,跳转到相应的页面
通过配置web.xml文件,让tomcat统一处理异常,即告诉tomcat在发生异常时,转发到什么错误页面
1.通过异常类型声明
<error-page>
<exception-type>java.langException</ exception-type>
<location>错误网页的url</location>
</error-page>
2.通过错误编码声明(405,500写法相同)
<error-page>
<error-code>404< /error-code>
<location>错误网页的url</location>
</ error-page>

由于任何地方都可能报错,所以无法确定相对路径,所以JSP访问路径应该为绝对路径
并且该路径不能写项目名,tomcat会自动补充。

过滤器
解决项目中的一些共性需求,如日志,过滤敏感词,登录检查等。

创建一个过滤器:该类实现了Filter接口,重写了三个方法 init(),destroy(),doFilter()
init() 初始化方法,destroy( ) 销毁方法 ,通常不写内容
doFilter():在tomcat启动时,会自动调用该方法,传入ServletRequest,ServletResponse
由于需要获取session和servlet中的访问路径,需要对参数进行强转为HttpServletRequest
HttpServletResponse

配置webxml
<filter>
<filter-name></filter-name>
<filter-class></filter-class>
</filter>
<filter-mapping>
<filter-name></filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

过滤器原理:

1.通过过滤器统一解决乱码问题

在过滤器的doFilter方法中设置编码的转换,在执行chain.doFilter(request, response);之前
将编码设置成utf-8
chain.doFilter(request, response);表示将请求交给下一个Filter或者Servlet处理
如果不调用该方法则请求结束。

2.通过Filter进行系统校验,用户只能通过登录页面进入系统
设置了过滤器之后,所有的请求都会被拦截,也就是登录的请求也会被拦截
那么就需要将该请求排除拦截的范围。其他的请求不变。
登录的用户会把信息保存在session中,若sesion中没有数据 则该用户没有登录,进行拦截
跳转到登录页面。

FileUpload实现文件上传

boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        System.out.println(isMultipart);
        //1、创建一个DiskFileItemFactory工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //2、创建一个文件上传解析器
        ServletFileUpload upload = new ServletFileUpload(factory);
        //解决上传文件名的中文乱码
        upload.setHeaderEncoding("UTF-8"); 
        upload.setSizeMax(1024 * 1024 * 5);//设置上传的文件总的大小不能超过5M
        try {
            //解析请求对象
            List<FileItem> fileList= upload.parseRequest(request);
            //遍历请求结果
            Iterator<FileItem> iter = fileList.iterator();
            while(iter.hasNext()){
                FileItem item = iter.next();
                //判断当前遍历到的元素是否为普通的表单
                if(item.isFormField()){
                    String name = new String(item.getFieldName().getBytes("iso8859-1"),"utf-8");
                    String value = new String(item.getString().getBytes("iso8859-1"),"utf-8");
                    System.out.println(name);
                    System.out.println(value);
                }else{
                    //图片的上传
                    //获取文件名
                    String fileName = item.getName();
                    System.out.println(fileName);
                    //重命名
                    String newFileName = new Date().getTime()+fileName.substring(fileName.indexOf('.'));
                    //构建File对象
                    System.out.println(getServletContext().getRealPath("/images/photo"));
                    File file = new File( getServletContext().getRealPath("/images/photo"),newFileName);
                    item.write(file);

                }
            }
            
        } catch (FileUploadException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
文件上传的问题

上传的图片保存在tomcat下的webapps中,并不是本地的项目空间。如果平时测试代码时需要重新部署项目,这将导致webapps下的项目被项目空间的所替换,之前上传到服务器中的文件也就消失了。

测试临时解决办法:将文件上传路径,设置为项目空间

归根到底这些问题其实还是因为我们是在调试的工程中,发布后肯定是不会出现这些问题的。发布了之后你的tomcat服务器只有关闭和打开,而不会对工程重新部署,自然也就不会出现这些问题

上传图片文件(图像)时如何立即显示
<script type="text/javascript">
  //判断浏览器是否支持FileReader接口
  if (typeof FileReader == 'undefined') {
    alert("<h1>当前浏览器不支持FileReader接口</h1>");
  } 
  //选择图片,马上预览
  function xmTanUploadImg(obj) {
    var file = obj.files[0];
    var reader = new FileReader();
    reader.onload = function(e) {
      var img = document.getElementById("img1");
      console.log(e.target.result);//Date url格式
      img.src = e.target.result;
    }
    reader.readAsDataURL(file);
  }
  </script>
<form action="FileUpdateServlet" method="post" enctype="multipart/form-data">
        <input type="file" name="headr"  onchange="xmTanUploadImg(this)">
        <input type="submit">
        <img alt=""  id="img1">
</form>

Ajax是一种用来改善用户体验的技术。其实质是利用浏览器提供的ajax对象(XMLHttpRequest) 异步的向服务器发送请求,服务器响返回数据,浏览器利用这些数据进行页面的局部更新
整个过程,页面无刷新效果,不打断用户的操作。
异步:指的是当ajax对象发送请求时,浏览器不会销毁当前页面
提交表单请求时,会销毁当前页面(刷新)

获取ajax对象
function getXhr(){
    var xhr;
    if(window.XMLHttpRequest){
        非IE
     xhr=new XMLHttpRequest();
    }else{
           IE浏览器下获取方式
        xhr=new ActiveXObject("Microsoft.XMLHttp");
    }
    return xhr;
}

触发ajax的事件函数
onreadystatechange:绑定事件的处理函数
当readyState属性值发生改变时,会触发readystatechange事件
readyState:有5个值(0,1,2,3,4),表示ajax对象与服务器的通信进度
            当值为4的时候,表示已经获得了服务器返回的数据
status:表示服务器返回的状态码 200表示成功
responseText:表示服务器返回的文本数据
xhr.send():将请求发送给服务器,必须写

 function sendHttpReq(){
    获取ajax对象
    var xhr=getXhr();
      通过ajax向服务器发送请求
    xhr.open("get","servlet映射路径",true);
    xhr.onreadystatechange=function(){
        if(xhr.readyState==4&&xhr.status==200){
            var msg=xhr.responseText;
        }
    };
    
    xhr.send();
}
服务器相应ajax
 PrintWriter pw= response.getWriter();
 pw.print(响应信息);
 pw.close();
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,999评论 4 368
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,102评论 1 302
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,709评论 0 250
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,439评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,846评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,881评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,062评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,783评论 0 205
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,517评论 1 248
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,762评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,241评论 1 264
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,568评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,236评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,145评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,941评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,965评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,802评论 2 275

推荐阅读更多精彩内容

  • Java web笔记 一、HTTP协议 HTTP(超文本传输协议),它是一种主流B/S架构中应用的通信协议。具有以...
    默羊的笔记本阅读 495评论 0 0
  • 1.1 Servlet 1.1.1 什么是Servlet Servlet是JavaWeb三大组件之一(Servle...
    海若Hero阅读 2,000评论 0 5
  • Web服务器 Weblogic(Oracle) WebSphere(IBM) JBoss(Redhat) 以上产品...
    Levi_wen阅读 299评论 0 0
  • 一 . Tomcat 1.对Tomcat的理解 Tomcat是一个运行JAVA的网络服务器,提供能够让别人访问自己...
    Vegetable蔬菜阅读 794评论 2 1
  • Servlet:Sun公司制订的一种用来扩展Web服务器功能的组件规范。当浏览器将请求发送给Web服务器(比如:a...
    南山伐木阅读 570评论 0 4