Servlet

第一章B/S结构

1.  学习概述

居律 julv@njrst.com.cn

 

教授内容:

servlet+jsp

ajax

strtus2

 

回顾:

HTML CSS JS 运行在浏览器端,即客户端,JS用得比较多

 

Java后台服务器

 

Servlet

B/S    浏览器/服务器

C/S    客户端/服务器  比如魔兽世界客户端

2.  什么是B/S结构

1.1 什么是B/S结构

客户端采用标准的浏览器,服务器端采用标准的web服务器,浏览器与服务器采用标准的Http协议通讯

 

相对C/S结构的优势:

a. 客户不需要单独安装客户端

b. C/S结构比较麻烦的是,用户需要单独安装客户端,并且,当版本升级时,需要再次安装

c. 开发相对简单,C/S结构需要编写通讯模块与自定义协议,而B/S结构使用的是标准的浏览与标准的web服务器,它们都包含了通讯模块,不需要自己编写,而且,浏览器与服务器采用的是标准的HTTP协议通讯

 

3.  什么是Servlet

Sun公司制定的一种用于扩展web服务器功能的组件规范

 

a. 扩展web服务器

早期的服务器只能处理静态资源文件,不能够处理动态资源文件(需要经过计算生成的页面),因此需要扩展。

 

b. 扩展的方式

组件+容器

组件:符合规范,实现特定功能,可以部署在容器上的软件模块。

容器:符合规范,为组件提供运行环境,并且可以管理组件生命周期的软件程序。

 

优势: 容器负责大量的基础服务(浏览器与服务器之间的通讯,参数传递等等) ,而组件只需要处理业务逻辑,并且不依赖于特定的容器。
 


4.  启动容器

tomcat/bin/startup.bat 启动容器

tomcat/bin/shutdown.bat 关闭容器

启动成功之后

localhost:8080 进行访问

localhost: 主机名

127.0.0.1: ip地址

8080: tomcat端口号(安装目录文件夹comf  server.xml可修改端口号)

 

MyEclipse配置

windows-->prefrences-->MyEclipse-->Servers-->Tomcat

 

5.  开发servlet组件步骤

step1. 定义java类,继承HttpServlet

step2. 重写父类Service方法

step3. 在web.xml文件中配置servlet

 

演示:

http://localhost:8080/servlet01/sayHello

 

 6.  实例演示

a. localhost:8080 与tomcat服务建立连接

b. 根据servlet01查找tomcat/webapps目录下对应的文件夹

c. 根据web.xml文件中的配置信息匹配/sayHello

d. 若匹配成功,根据servlet-name查找对应的servlet组件

 

演示 servlet01

1). web.xml配置

 ---------

web.xml 配置

servlet

  servlet-name  

  servlet-class

/servlet

 

servlet mapping

  servlet-name

  uri-pattern

/servlet mapping

 

2). 继承service方法及实现

-----

request.setCharacterEncoding("utf-8")

response.setContentType("text/html;charset=utf-8")

PrintWriter out = response.getWriter()

out.print()

..

out.close();

 

3) 启动tomcat进行访问

localhost://8080/HelloServlet  --> index.jsp的页面,a jsp page

localhost://8080/HelloServlet/sayhello  -->out输出相应的html字符或者单独的String

 

演示:HelloServlet

package com.xms.web;

 

import java.io.IOException;

import java.io.PrintWriter;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

 

public class HelloServlet extends HttpServlet{

  

   publicvoid service(HttpServletRequest req,

        HttpServletResponse res)throws IOException,ServletException{

     

      //通知浏览器服务器返回的数据类型,比如返回的是html

      //告诉服务器以utf-8的格式处理中文

      //默认是ISO8859-1,处理不了中文

      //通知浏览器以utf-8的格式解码

     res.setContentType("text/html;charset=utf-8");

     

      //设置服务器端口的解码方格式,只对post请求管用

     req.setCharacterEncoding("utf-8");

  

  

      //HttpServletRequest:请求对象

      //HttpServletResponse:响应对象

      //获取url地址后面跟着的参数

     String name = req.getParameter("name");


      //获取输出流,输出到页面

     PrintWriter out  =res.getWriter();

     out.print("<span style='color:red'>你好" +name+" </span>"); //给其中需要显示的文字加上相应的颜色

     out.close(); //用完之后关闭流


}

}

7. servlet运行原理

a. 根据ip及端口号与服务器建立连接

b. 在发送请求之前通讯模块将数据根据http协议打包向服务器发送请求

c. 浏览器向服务器发送请求

d. 服务器端通讯模块将数据根据http协议拆包

e. 容器创建request与response对象

f.  容器实例化servlet组件

g. 容器调用servlet当中的service方法处理数据

h. 服务器端的通讯模块打包数据,并发送响应

i. 浏览器拆包,生成新的页面返回

 

 

数据htpp打包发送请求 -->服务器接收拆包  处理 打包 发出响应 -->生成新页面

 

 

8. get请求与post请求

get请求:

a. 在浏览器输入url地址访问

b. 点击链接<ahref="http://www.baidu.com"></a>

c. 表单的默认提交方式<formmethod="get"> </form>

 

post请求:

<formmethod="post"></form>

 

 9.  如何通过servlet输出中文

输出中文,响应中设置下文本 test/html;charset=utf-8

response.setContentType("text/html;charset=utf-8");

 

如何获取中文参数,对request记性设置

request.setCharacterEncoding("utf-8");

 

 

request.setCharacterEncoding("utf-8");只对post请求有用

如果是get请求需要,需要在server.xml文件中设置URIEncoding = "utf-8"

 

 

此处需要重启运行 tomcat

 

练习1:写一个DateServlet输出当前日期 now:2017-06-30

 

 

练习 ShowDate

 

写一个DateServlet输出当前日期now:2017-06-30

 

package com.xms.web;

 

import java.io.IOException;

import java.io.PrintWriter;

import java.util.Date;  //sql.Date包中的date出来后的格式是 2017-6-30 这种,而util下的是格林威治的时间格式,需要用SimpleDateFormat进行转换

import java.text.SimpleDateFormat;

import java.util.Arrays;

import java.util.logging.SimpleFormatter;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

 

//写一个DateServlet输出当前日期 now:2017-06-30

 

public class ShowDate extends HttpServlet{

 

   publicvoid service(HttpServletRequest req,HttpServletResponse res)

      throwsIOException,ServletException{

     

     res.setContentType("text/html;charset=utf-8");

     req.setCharacterEncoding("utf-8");

     

      //创建输出流

     PrintWriter out = res.getWriter(); // printWriter输出流

      longnow = System.currentTimeMillis();

     Date d = new Date(now);

     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

     String s = sdf.format(d);

     

     out.println("now:"+s);

     out.close();

      

     

   }

  

  

  

}

 10.  常见错误

a. servlet组件需要继承HttpServlet  页面500错误

b. 在web.xml文件中servlet-class路径要写对 500

c. service方法的方法名、参数以及异常要写对  405

d. url地址要写对 404

e. servlet与servlet-mapping中的servlet-name需要保持一致

 

 

 

 

 11. http协议

hypertext transfer protocol(超文本传输协议)

定义了浏览器与服务器的通讯过程及数据格式

通讯过程

step1. 建立连接

step2. 浏览器向服务器发送请求

step3. 服务器向浏览器发送响应

step4. 服务器关闭连接

特点:一次请求,一次连接,一次响应

优势:可以使用有限的连接资源为更多的用户服务,效率比较高。

如果需要再次发送请求必须重新建立连接

 

数据格式

请求数据包

   第一部分:请求行

                    请求方法 get/post

                    请求资源路径 /appname/...

                    协议类型及版本 HTTP/1.1

   第二部分:若干消息头

                     是一些特殊含义的键值对,由w3c指定

                     浏览器可以通过消息头的方式发送一些特定的信息,比如user-agent

                     它会告诉服务器浏览器的版本号等信息

   第三部分:实体内容

                     如果是post请求,浏览器才会将参数存放在实体上面,如果是get请求,参数是跟在url地址后。

 

响应数据包

 

请求行: get/post 路径  协议版本

消息头:user-agent 浏览器版本号 键值对等

实体:post在实体上,get在url后

 

 

第二章Http协议

1.  知识点回顾

知识点回顾

1. 什么servlet?

用于扩展web服务器功能的组件规范

2. 为什么要扩展web服务器

早期的web服务器只能处理静态资源文件,希望能处理生成动态页面

3. 扩展的方式

组件+容器的扩展方式 

组件:servlet

容器:tomcat 或其他容器

4. servlet的运行原理图

5. 如何获取请求参数

单个参数:url?name=zs  

多个参数:url?name=zs&age=12

固定格式: url? + 参数名=参数值

String :request.getParameter("name");

 

6. 如何通过servlet输出中文?

out.print("你");

res.setContentType("text/html;charset=utf-8");

告诉浏览器返回的是html文件,解码方式是utf-8的格式

 

7. 如何正确获取参数中的中文

name=张三

req.setCharacterEncoding("utf-8");

xml文件中的需要设置  URIEncoding="utf-8"

tomcat的server.xml 中设置(针对get方式中带中文的情况)

 

8. Http协议通讯过程

 

9. 数据格式

请求数据包

1) 请求行

2) 若干消息头

3) 实体内容

 

 

 2.  http协议

响应数据包

1) 响应行

a. 协议类型及版本号

b. 状态码

c. 状态码描述信息

2) 若干消息头

一些键值对,由w3c指定,具有特定含义,比如content-type,告诉浏览器服务器返回的数据类型及编码格式

3) 实体内容

程序处理之后的数据

 

响应行

消息行

实体内容

 

 3.  get与post请求的区别

a. get请求的参数是跟在请求地址之后,不能够提交大量的数据(不同的浏览器对url数据大小的限制不同,大约2K-8K之间,为了兼容所有的浏览器,最好不要超过2K),而post请求的参数是存放在实体内容中,理论上没有限制。

b. post请求相对于get更安全,但是post请求也不是绝对性的安全,对于敏感的数据建议加密。

 

 

 

 4.  如何获取请求参数

String request.getParameter("参数名");

如果有多个参数名一样的情况:

String[] request.getParameterValues("参数名")

url?name=zs&city=n&city=sz&city=hf

 

 

5. mysql数据库

1. 查看所有的库

show databases;

 

(密码1234 登录后,输入show databases , 输入一个";" 分号)

 

2. 创建库

create datebase jsd1704 default character setutf8;

 

3. 使用库

use java1704

 

4. 显示库里所有的表格

show tables;

 

5. 创建表

create table emp(

id int primary key auto_increment,

name varchar(30),

salary double,

age int

);

 

6. insert into empvalues(null,'jack',1000,10);

 

7. 查询

select * from emp;

 

8. 删除

select from emp where id=?;

 

9. 更新

update emp set name=? where id=?;

 

set names gbk; //设置编码格式为gbk 是的运行窗口能正常访问中文字符

 

 

  练习 ListEmpServlet

写一个ListEmpServlet查询数据库,并且以表格的形式展示所有的emp信息

 

localhost:8080/appname/list

 

创建数据库

Class.forName("com.mysql.jdbc.Driver");

Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/jsd1704","root","1234");

String sql=""

PrepareStatement ps =con.perpareStatement(sql);

ResultSet rs = ps.executeQuery();

out.println("<table>")
out.print("<tr><th>...")

while(rs.next()){

int id = rs.getInt("id");

...

 

out....

}

 

exception...

 

out.close;

 

 

--------------------------------

 publicclass ListEmpServlet extends HttpServlet {

 

 

    protectedvoid service(HttpServletRequest req, HttpServletResponse res)

            throws ServletException, IOException {

        

   

        req.setCharacterEncoding("utf-8");

        res.setContentType("text/html;charset=utf-8");

        

        PrintWriter out = res.getWriter();

        

//     String name = req.getParameter("name");

//     double  sal=Double.parseDouble("salary");

//     int age = Integer.parseInt("age");

        

        Connection con  = null;

        try {

            Class.forName("com.mysql.jdbc.Driver");

            con = DriverManager.getConnection("jdbc:mysql://localhost:3306/jsd1704","root","1234");

            String sql ="select * from emp";

            PreparedStatement ps = con.prepareStatement(sql);

            ResultSet rs = ps.executeQuery();

            out.print("<table border='1' cellpading='0'cellspacing='0'>");

            out.print("<tr>"+"<td>ID</td>"+

                      "<td>姓名</td>"+

                      "<td>薪资</td>"+

                      "<td>年龄</td>"+

                      "<td>操作</td>" +

                      "<td>更新</td></tr>"

                      );

            while(rs.next()){

                 int id = rs.getInt("id");

                 String name = rs.getString("name");

                 double sal = rs.getDouble("salary");

                 int age = rs.getInt("age");

                 out.print("<tr>"+

                          "<td>"+id+"</td>"+

                          "<td>"+name+"</td>"+                        

                          "<td>"+sal+"</td>"+

                          "<td>"+age+"</td>"+

                          "<td><ahref='delemp?id="+id+"'>删除</a></td>"+

                          "<td><ahref='updateemp?id="+id+"'>升级</a></td></tr>"

                          );

            }

            out.print("<table>");

            out.print("<a href='addEmp.html'>添加员工</a>");

        

        } catch (Exception e) {

            e.printStackTrace();

            out.print("系统繁忙,请稍候重试");

            

        }finally{

            try {

                 if(con!=null){

                      con.close();

                 }

   

            } catch (Exception e) {

                 e.printStackTrace();

            }

        }

        out.close();

    }

}

------------------------------

}

 6.  重定向

服务器向浏览器发送302的状态码以及一个location的消息头,当浏览器收到之后,会立即向location所指向的地址发送请求。

如何重定向

resposne.sendRedirect(String url)

url:重定向地址

 

注意点:

a. 重定向之前,会清空reponse响应对象中的缓存数据

b. 重定向之前,不能调用out.close()或者 out.flush()方法

 

特点:

a. 重定向的地址是任意的,比如百度地址

b. 重定向之后,浏览器地址栏的地址会发生改变

 

 

第三章容器如何处理请求资源路径

a. 什么是请求资源路径

localhost:8080/appname/list

端口号之后的部分

 

b. 如何处理

容器会先根据ip:8080与服务器建立连接,根据应用名取webapps文件夹下查找对应的文件夹,如果找到,那么容器会先假设访问的是servlet,根据url-pattern 当中的配置匹配应用名之后的地址,如果匹配成功调用相应的servlet处理请求,如果匹配失败,容器会认为访问的是静态资源文件,比如(abc.html),容器会查找该文件,如果找到,返回该文件,反之,返回404。

 

 

匹配规则:

1) 精确匹配,以"/"开头,比如/some

2) 通配符匹配,以"/"开头,比如/* (*表示任意长度的字符)      <url-pattern>/*</url-pattern>

  如:http://localhost:8080/servlet04/aaaa/bbbb/cccc

 

3) 后缀匹配,不能以"/"开头,一般以.do .action等结尾,比如 *.do   <url-pattern>*.do</url-pattern>

   如: http://localhost:8080/servlet04/aaaaa.do

 

 

 

 第四章一个servlet如何处理多个请求

/list.do /del.do   /add.do  ...

 

step1. 采用后缀匹配

step2. 在servlet当中获取请求资源路径request.getRequestURI() 分析请求资源路径

step3. 

 

后缀匹配 *.do

 

通过request对象获得url地址,然后对url地址进行截取,然后再进去匹配

 

 Stringaction = request.getRequestURI();

action =action.subString(action.lastIndexOf("/"),action.lastIndexOf("."));

 

 

 

 

第五章 servlet生命周期

1) 概念:servlet如何实例化,如何分配其资源,如何调用service方法,以及如何销毁的整个过程。

2)

第一阶段:实例化

情况1:默认情况,当请求到达容器时,才会实例化servlet,并且只会实例化一次

情况2:容器启动或者重新部署时,就已经实例化servlet。需要在web.xml文件中添加<load-on-startup>1</load-on-startup> 值为>=0的整数,值越小,优先级越高

所以这里有时候调试的时候重新加载就需要再实例化一次,这样的话就不用频繁的重启tomcat了

 

 

第二阶段:初始化

容器为servlet分配资源,调用init(ServletConfigconfig)方法

config:容器创建,通过config可以获取web.xml文件中配置的初始化参数值

 

String: config.getInitParameter(String name);

在service方法中如何获取config?

GenericeServlet getServletConfig()

 

可以重写init() 或者init(ServletConfig)

 

阶段三 就绪

容器在初始化servlet之后,会调用service方法

父类HttpServlet覆盖了service方法,在该方法中,先获取请求方式,如果是get请求,底层会调用doGet(req,res),如果是post请求,底层会调用doPost(req,res)方法。

作为HttpServlet的子类,可以重写service方法,也可以重写doGet(req,res)或者doPost(reql,res)

建议重写service方法

 

阶段四 销毁

容器在删除Servlet之前,会先调用destory的方法。可以在destroy方法中,尽快回收资源空间。

总结:在生命周期的整个过程当中,init() 与destroy() 只会被执行一次,service()会被执行多次

 

Servlet相关的抽象类类与接口

Servlet

   init

  service(ServletRequest ServletResponse)

  destory

GenericServlet

   initdestory

HttpServlet

  service(HttpServletRequest,HttpServletResponse)

 

 

过程就是

默认情况请求到达容器 

servlet 实例化

实例化后config根据web.xml得到的参数进行初始化(类,名字等等)

初始化后,servlet调用service方法来处理相应的请求数据

在容器删除servlet之前调用一次destroy方法销毁

 

第六章servlet相关的抽象类及接口

a. Servlet

init(ServletConfig config)  初始化

service(ServletRequest,ServletResponse)   service

destroy() 销毁

 

b. GenericeServlet 抽象类

实现Servlet接口,重写了 

init(ServletConfig config) 初始化

destory() 销毁

 

c. HttpServlet

重写了service方法  service

 

d.

 

 

第七章 路径

1.  路径问题

1. 路径问题

      表单<form action=""></form>

      链接<a href=""></a>

      重定向response.sendRedirect(String url)

      转发request.getRequestDispatcher(String url)

 

      相对路径

        不以"/"开头的路径

        比如<a href = "del.do"></a>

      绝对路径

        以"/"开头的路径

        链接、表单、重定向,从应用名开始写,而转发是从应用名之后开始写(因为转发只能在应用内)

        应用名 :request.getContextPath()

        建议在真实的开发环境中,用绝对路径

 

重定向由response.sendRedirect("del.do") 发到相应的地址

也有发绝对路径,request.getContextURI+

 

 练习 注册表

注册:

   收集用户在表单中的信息,并且将其保存在数据库中,保存前,判断用户名是否被占用,如果被占用,在注册页面提示

   “用户名被占用”,若可以使用,保存数据,跳转到登录页面

  

step1: 设计表,

           create table user(

                 id int primary keyauto_increment,

                 username varchar(20),

                 name varchar(20),

                 pwd varchar(20),

                 sex char(1)

           )

step2: 定义一个实体类User

             属性与user表字段一一对应,并且提供get、set方法

step3: 定义DAO接口

           User findByUsername(String username)throws Ecxeption;

           void add(User user ) throws Exception;

           insert into user values(null,?,?,?)

step4: 根据具体的技术写实现类DAOImpl

             重写父接口方法

step5: tegist.jsp

step6: ActionServlet

            接受表单中的数据  request.getParameter(***);

            调用dao.findByUsername()

            dao.add(User user)

            跳转到登录页面

            

            若用户名被占用,回到注册页面,回到注册页面

 

 

 

 

第八章 session验证

知识点回顾

知识点回顾

 

1. 让容器处理异常

2. 状态管理

 cookie

 newCookie(String name, String value);

 response.addCookie(c);

 Cookie[] :request.getCookies();

 URLEncoder.encode(String str,String bm);  编码

 URLDecoder.decode(String str,String bm);  解码

 setMaxAge(int seconds)

  >0(保存在硬盘中,超过时间就删除)<0(保存在内存中) =0(表示删除)

 newCookie("name","");

 setMaxAge(0);

 response.addCookie(c);

 

cookie的缺点:不安全,

 

session

HttpSession:request.getSession();

session.getId();

session.setAttribute(String name,Object obj)

session.getAttribute(String name)

默认是保存30min

可以通过如下方式设置相应的时间:

setMaxInactiveInterval(秒)

 

 

 

8.1 session验证

对于需要登录成功之后才能访问的页面,需要进行保护

step1. 登录成功之后,将用户的信息绑定到session上

step2. 在访问一些需要保护的页面时,先访问session对象上是否有绑定用户的相关信息

 

session删除

session.invalidate()

清空session对象中的数据,包括sessionId

8.2 购物车

1) 商品列表页面展示

step1. 设计表

create table computer(

id int primary key auto_increment,

model varchar(20),

pic varchar(20),

proDesc text,

price double

);

 

insert into computervalues(null,'x200','x200.jpg','比较便宜',2000);

insert into computervalues(null,'x200','x500.jpg','性价比不错',5000);

insert into computer values(null,'x200','x600.jpg','适合玩游戏',6000);

 

以上其中需要对name 进行设置  

set names gbk;

 

step2. 实体类computer

step3. DAO接口

step4. 实现类DAOImpl

step5. ActionServletstep

step6. computerList.jsp
 

响应的js css img文件夹需要放在WebRoot目录下

 

使用一个新对象cart  来执行查看、修改数量、添加、删除、计价、清空、返回列表  等方法

间接控制session

直接把数据绑定在session上,N个操作上,这样会比较有弊端。


练习购物车 shoppingcart

 

第一版购物车

 

存在问题,关闭浏览器后,其购物车的内容不见了。

 

第二版购物车

 

使用cookie保存相应的信息,解决以上问题


第九章cookie

9.1 购物车第二版

第一版问题:当浏览器关闭之后,购买的商品数据消失(浏览器关闭,sessionId消失,找不到之前的session对象)

 

第二版:将购买的商品数据保存到cookie中,设置cookie的保存时间,而cookie只能保存少量字符串,所以需要将之前的集合list<CartItem>中的数据转成字符串,比如"1:3,2:4";

 

 

9.2 cookie和session的区别

cookie:将数据保存在客户端的一种技术

session: 将数据保存在服务器端的一种技术

 

session的优点:

a. session保存的数据类型比cookie更广泛

b. session 保存在服务器端,相对于cookie更安全

c. session保存的数据量比cookie更大

 

session的缺点:

a. session是借助于cookie的机制保存在内存当中,当浏览器关闭,sessionId关闭

b. 服务器会为每一个用户分配一个session对象,对服务器的资源消耗比较大,而cookie的数据是保存在客户端上,理论上对服务器没有压力

 

 

9.3 cookie被禁止之后

3. cookie 被禁止后,如何继续使用session

解决方案: URL重写

因为sessionId是依赖于cookie的机制返回给浏览器,如果用户在客户端禁止使用cookie,那么浏览器将不再保存sessionId,没有了sessionId,就找不到服务器端对应的session对象,因为需要URL重写

 

如何URL重写?

如果浏览器不再保存sessionId,需要通过编程的方式跟踪sessionId

a. 链接<ahref="<%=response.encodeURL("url")%"</a>

b. 表单提交 <formaction=""><form>

c. 重定向

  response.sendRedirect(response.encodeRedirectURL("url"));

d. 转发不需要

9.4 过滤器

servlet定义的一个特殊的类,可以对servlet的请求进行拦截并处理。

 

如何写一个过滤器

step1. 定义一个java类,实现Filter

step2. 重写父接口的方法

step3. 在web.xml文件中配置过滤器

step4.

  

第十章监听器

10.1 知识点回顾

知识点回顾:

过滤器:

1. java类实现Filter

2. 重写

3. web.xml

 

1. 给comment请求再添加一个过滤器,判断评论的长度是否超过指定的范围,其中指定的长度通过初始化配置参数。

 

优先级:

当有多个过滤器符合要求时,过滤的顺序与<filter-mapping>配置的顺序有关。

 

优点:

a. 当有多个web组件有相同的功能的代码需要实现时,可以通过过滤器封装

b. 可实现代码的"插拔性",给一个软件模块增加或者减少一个功能时,不会影响已经存在的功能。

 

 

10.2 监听器

servlet规范当中定义的一个特殊类,可以对某些对象和事件进行监听

对某些对象和事件进行监听

监听的对象分为两个大类:

a. 与生命周期相关的事件,比如容器创建或者销毁的request、session、servletContext对象

b. 与绑定事件相关的,比如当调用了request、session、servletContext对象的setAttribute() 或者removeAttribute() 时也会触发一些监听器

 

servletContext:上下文对象

容器在启动的时候,会为每一个应用创建唯一的一个servletContext对象,当容器关闭或者应用被移除时,该对象才会被销毁。

 

生命周期:

request:一次请求,一次响应期间

session : 一次会话期间,只要浏览器不关闭并且session并未超时

servletContext : 只要应用存在,就一直能访问

 

如何获取上下文对象:

a. GenericServlet提供了getServletContext()

b. HttpSession提供了getServletContext();

c. ServletConfig提供了getServletContext();

 

相关方法

a. setAttribute(String name, Object obj);

  getAttribute(String name);

  removeAttribute(String name);

b. 获取全局参数getInitParameter(String name)

c. 根据逻辑路径获取物理路径getRealPath(String Path)

 

如何写一个监听器

step1. 定义一个java类实现特定的接口

step2. 重写父类的方法

step3. 配置监听器

练习:购物车第二版(11:40-12:00)

10.3 上传文件

step1. form表单传递数据,其中提交方式 method="post" ,enctype="multipart/form-data" ,该属性用来设置表单的编码方式

step2. 如果上传的是文件,不能用request.getParameter()获取,需要改成request.getInputStream(),然后分析流信息,自己分析比较复杂,可以借助于一些工具包分析。

演示:servlet10

10.4 servlet线程安全问题

因为servlet声明周期整个过程中,servlet对象只有一个,当请求到达容器时,容器启动一个线程访问servlet,那么就会发生多个线程访问同一个servlet对象,此时需要考虑线程安全问题,比如在service方法中,修改成员变量的值

a. 加锁

可以给整个方法加锁,也可以给其中部分代码块加锁,建议使用后者

b. servlet实现一个接口SingleThreadMode

c. 在service方法当中尽量不要去修改成员变量的值(将成员变量的值设置成可读的)

 

 

10.5 jsp

1) 服务器端动态生成页面的技术规范

2) 组成

   html+css+js

  <%java代码块%>

  <%=jsp表达式%>

  <%!jsp声明%>

 

3) 执行

   a.jsp文件会被容器转成java文件(servlet类)

      html--> 在service方法里,out.write()

     <%%>--> 在service方法里,照搬

     <%=%>--> 在service方法里,out.print() 输出

     <%!%>--> 相当于给servlet添加了新的成员变量以及方法

   b. 容器负责实例化、初始化、就绪以及销毁的调用

 

4) 指令:容器将jsp文件转成java文件时做的一些额外的处理。

语法:<%@指令名 属性名=属性值%>

page:pageEncoding

           contentType

           import

           session; true(缺省值)/false

           errorPage: 配置错误页面

           isErrorPage: true/false(缺省值)

include:

        file

 

5) 隐含对象

out  输出

request 请求

response 响应

session 会话

application 上下文

exception 异常对象:当jsp页面发生异常,容器会将异常信息封装到exception当中,通过调用exception.getMessage() 可以获取异常信息,只有当isErrorPage="true",容器才会创建该对象

config:相当于servletConfig,通过该对象可以获取给jsp页面配置初始参数值

pageContext:容器为每一个jsp页面创建一个符合pageContext接口要求的对象,该对象一直存在,除非jsp实例被销毁、

   作用1:绑定数据 setAttribute(String name, Objectobj);

      获取数据 getAttribute(String name);

   作用2:通过pageContext可以获取其他8个隐含对象

        

page:jsp实例

 

jsp隐含对象声明周期排序

pageContext<request<session<application

 

6) 注释符

<!--注释内容-->  页面不显示,底层会运行   查看网页源代码看是否运行

<%--注释内容--%> 页面不显示,底层不运行

 

第十一章 状态管理

1)什么是状态管理

将浏览器与服务器的多次交互看作一个整体,把这多次交互所涉及到的数据保存下来,就是状态管理。

状态:数据

管理:保存

 

2) 如何进行状态管理

a. 将数据保存在客户端  cookie

b. 将数据保存在服务器端 session

 

3) 什么是cookie

浏览器在访问服务器时,服务器会将少量的数据以set-cookie消息头的方式发送给浏览器,浏览器会将这些数据保存下来,当浏览器再次向服务器发送请求时,会将这些数据以cookie消息头的方式发送给服务器,通过这种方式,可以实现状态管理的目的。

 

4) 创建cookie

// name:cookie的名字  value:cookie的值

Cookie c = new Cookie(String name,Stringvalue);

response.addCookie(c);

 

5) 查找cookie

Cookie[]:request.getCookies();

String:cookie.getName();查找cookie名称

String : cookie.getValue(); 查找cookie值

 

练习: 查找名字为city的cookie,如果找到了,输出该cookie的值,如果未找到,则创建该cookie(city=nj)

 

6) cookie保存中文

默认情况下,cookie只能保存合法的ascii码字符。

URLEncoder.encode(String str,String bm);

先将中文按照指定的格式编码,再将编码之后的字节数组转换成ascii字符串。

 

解码:

URLDecoder.doceode(String str,String bm);

注: 编码与解码格式必须保持一致

 

7) cookie的保存时间

默认情况下,浏览器会将数据保存在内存当中(打开浏览器,操作系统会为其分配一块内存空间),当浏览器关闭之后,内存空间被释放,那么之前保存的数据随之消失。

 

cookie.setMaxAge(int seconds) 单位:秒

seconds>0 cookie的数据保存在硬盘当中,当超过指定的时间,cookie被删除

seconds<0, 默认情况,cookie保存在内存当中,只要浏览器不关闭,cookie的数据就一直存在

seconds=0 立即删除

 

8) cookie的路径问题

默认情况下,浏览器向服务器发送请求时,会先比较cookie的路径与访问组件的路径是否匹配,只有匹配的cookie,才会发送,匹配规则:

访问组件的路径必须与cookied的路径相等或者是其子路径

 

http://localhost:8080/servlet07/jsp1/addCookie.jsp

 

9) cookie的限制

a. cookie可以被用户禁止

b. cookie保存的数据量大小有限制(4k左右)

c. cookie保存的个数有限制(300个左右)

d. cookie只能保存字符串

e. 不安全,敏感的数据需要加密

 

练习: 写一个CookieUntil工具类

// 添加cookie

public static void addCookie(Stringname,String value,int age){}

// 查找cookie

public static StringfindCookie(HttpServletRequest req,String name){}

// 删除cookie

public static void delCookie(){}

 

10) session:将数据保存在服务器端

浏览器在向服务器发送请求时,服务器会先创建session对象,该对象对应着一个唯一的sessionId,服务器会将sessionId以set-cookie消息头的方式发送给浏览器,浏览器将sessionId保存在内存中,当浏览器再次向服务器发送请求时,会将sessionId以cookie消息头的方式发送给服务器,服务器根据sessionId可以查找之前的session,通过这种方式可以实现状态管理的目的。

 

11)如何获得session

方式一: HttpSession session =request.getSession(boolean flag);

flag=true:

浏览器向服务器发送请求时,服务器会先查看请求数据包中是否包含sessionId,如果没有,则创建一个新的session对象,如果有,那么服务器会根据sessionId查找对应的session,如果找到,则返回该session,反之,创建一个新的session对象。

flag =false:

浏览器在向服务器发送请求时,服务器会先查看请求数据包中是否包含sessionId,如果没有返回null;如果找到,则返回session,反之,返回null。

 

方法二:

HttpSession session = request.getSession()

 

12) session的相关方法

获取sessionId: session.getId();

绑定数据:sessionId:session.setAttribute(Stringname,Object obj);

根据绑定名查找数据:

Pbject:session.getAttribute(Stringname);

 

13) 服务器会将超过指定时间的session对象删除(在制定的时间内,一直为使用的session)

修改默认超时时间(30分钟)

a. 修改tomcat/web.xml 文件中的配置

<session-config>

<session-timeout>30</session-timeout>

</session-config>

b. 修改某一个应用的web.xml文件

c. 在servlet当中添加session.setMaxInactiveInterval(int seconds);

单位:秒

 

 

练习

练习: 查找名字为city的cookie,如果找到了,输出该cookie的值,如果未找到,则创建该cookie(city=nj)

 

第十二章处理异常

让容器处理异常

step1. 抛出异常 throw newServletException(e);

step2. 默认情况下,容器不会处理异常,会直接将异常信息返回给客户端,需要在web.xml文件中配置错误页面,通知容器发生异常时去指定的页面。

也可以用转发的方式来处理异常,根据实际情况进行选择处理方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值