Servlet 及相关知识详细解说

本文详细介绍了Servlet的背景、在J2EE中的地位以及在BS和CS架构中的角色。通过示例展示了如何搭建简单的web服务器,解释了Tomcat的工作原理和配置。探讨了Servlet的生命周期、服务流程以及在开发中的注意事项,包括Servlet的单例问题和安全性。还讨论了HTTP协议、状态码、请求头和响应头的关键概念。此外,文章提到了会话技术Cookie和Session的使用场景和实现方式,以及过滤器和JSP的基础知识。
摘要由CSDN通过智能技术生成

Servlet背景介绍

      J2EE的13种技术之一

       EJB、CORBA、RMI、JSP、Java Servlet、JavaBean、JDBC、XML、……

       serlvet+jsp ->java web开发[使用java技术做 web开发]

bs 和 cs的比较

   (1)BS:browser server 浏览器服务器

   (2)cs client server 客户服务

为什么需要的web服务器/web究竟是干什么的?

      我们先模拟一个web服务器  MyWebServer.java

import java.io.*;

import java.net.*;

public class MyWebServer

{

public static void main(String []args) throws Exception{

ServerSocket ss=new ServerSocket(80);

Socket s=ss.accept();

//提示一句话

System.out.println("在 9999 上等待连接...");

OutputStream os=s.getOutputStream();

BufferedReader br=new BufferedReader(new FileReader("d:\\hello.html"));

String buf="";

while((buf=br.readLine())!=null){

os.write(buf.getBytes());

}

//关闭流

br.close();

os.close();

s.close();

}

}

Tomcat介绍

  1. 通过tomcat来讲解BS结构
  2. 安装tomcat服务器
  3. 配置

①在环境变量中添加

JAVA_HOME= 指向你的jdk的主目录(并不是bin文件目录

        • 在不配置JAVAHOME的前提下启动tomcat

startup.bat的第25行中添加set JAVA_HOME=JKD

  1. 启动tomcat服务器

到 tomcat 主目录下 bin/startup.bat

  1. 验证是否安装成功

http://localhost:8080(8080是默认端口如果该端口已经被占用需要修改端口)

 

  1. tomcat安装后问题解决

(1)tomcat无法正常启动的原因分析

  1. JAVA_HOME 配置错误,或者没有配置 
  2. 如果你的机器已经占有了8080 端口,则无法启动, 

解决方法

(1) 你可以8080 先关闭

netstat –an

netstat –anb 来查看谁占用该8080

(2) 主动改变tomcat的端口.

到 conf/server.xml 文件中修改

<Connector connectionTimeout="20000" port="8088" (去修给config->server.xml的端口号)protocol="org.apache.coyote.http11.Http11NioProtocol" redirectPort="8443"/>

(3) 能够正常启动,但是会导航到另外一个页面.

去修改工具->管理加载项,把默认的导航给禁用即可.

(4) 在访问 tomcat时候,一定保证 tomcat 服务器是启动

tomcat的目录结构文件

bin: 启动和关闭tomcat的bat文件

conf: 配置文件 

-->server.xml : 该文件用于配置和 server 相关的信息, 比如 tomcat启动端口后,配置Host,  配置Context 即web应用 

-->web.xml : 该文件配置与 web应用(web应用就相当于是一个 web站点)

-->tomcat-users.xml: 该文件用户配置tomcat 的用户密码 和 权限

lib 目录: 该目录放置运行tomcat 运行需要的jar包

logs 目录:存放日志, 当我们需要去查看日志的时候,很有用!,当我们启动tomcat错误时候,可以查询信息.

webapps 目录: 该目录下,放置我们的web应用(web 站点), 比如:

建立  web1 目录  下面放置我们的html 文件 jsp 文件..图片... 则 web1就被当做一个web应用管理起来(☞ 特别说明tomcat 6.0 以后支持 tomcat 5 版本 还有别的设置)

 work: 工作目录: 该目录用于存放jsp被访问后 生成的对应的 server文件 和.class文件

如何去访问一个 web 应用的某个文件

将项目布置在tomcat上,启动tomcat,访问本地ip和事先设置好的端口号(这里默认是8080)

http://localhost:8080/web

  1. 首页面设置及目录规范结构

现在我们要求:hello.html文件设置成  web应用的首页,则需要把web应用的目录格式做的更加规范

①在web文件夹下配置WEB-INF文件夹

②在 web.xml 文件中添加配置的代码:

  <welcome-file-list>

    <welcome-file>hello1.html</welcome-file>

  </welcome-file-list>

③通过http://localhost:8088/web1来访问hello1.html

web-inf目录下的 classes目录将来是存放  class文件

lib 目录将来时存放 jar文件

web.xml 配置当前这个web应用的信息.

tomcat如何去管理虚拟目录

需求: 当我们把 web 应用放到 webapps目录,tomcat会自动管理,如果我们希望tomcat可以管理其它目录下的web应用?->虚拟目录配置

我在d 盘有一个web应用.

  1. 虚拟目录配置步骤:
    • 找到server.xml文件
    • 编辑host节点 添加Context path

在server.xml中添加:<Context path="/myweb2" docBase="d:\web2"/>

myweb2:是访问时输入的web名,实际取出的是web2中的资源

"d:\web2"绝对路径下web2中存放资源如:hello2.html

实际访问时输入的地址:http://localhost:8088/myweb2/hello2.html

绝对路径:从根分区找某个文件

相对路径:从该文件位置去找另一个文件

③ 需要重启tomcat,才能生效.(因为是采用的dom技术讲信息加载到内存中)

 

context  的几个属性的说明

path:

docbase:

reloadable  ;如果设为ture ,表示 tomcat 会自动更新 web应用,这个开销大,建议在开发过程中,可以设为true, 但是一旦真的发布了,则应当设为false;

upackWAR: 如果设为 ture ,则自动解压,否则不自动解压.

①:打war包 cd:d/web2 然后jar –cvf web2.war *

②:

浏览打好的war包 Deploy发布后会在webapps中自动生存改文件

  1. 配置域名

我们看和一个如何配置自己的主机名:

我们在实际访问网站的过程中,不可能使用http://localhost:8080/web应用/资源名  的方式去访问网站,实际上使用类似

http://www.sina.com.cn 或者

http://news.sina.com.cn 的方式去访问网站,这个又是怎么实现的呢?

看看ie浏览器访问一个web站点的流程.

实现的步骤如下:

(1) C:\WINDOWS\system32\drivers\etc 下的host文件 添加127.0.0.1 www.sina.com.cn

(2) 在tomcat 的server.xml文件添加主机名 

<Host name="www.sina.com" appBase="d:\web3”>

<Context path="/" docBase="d:\web3" />

</Host>

(3) 在d:\web3 加入了一个 /WEB-INF/web.xml 把 hello2.html设为首页面

如果连端口都不希望带,则可以吧tomcat的启动端口设为80即可.

(4) 重启生效

这里就不介绍Tomcat的体系了

如何配置默认主机:

在tomcat/conf/server.xml 文件

<Engine name="Catalina" defaultHost="主机名">

如:<Engine name="Catalina" defaultHost="www.show.com">

Servlet常用技术注意点

  1. 为什么需要servlet技术?

比如需求:我们希望用户可以贴,用户还可以回复 ....这样一些和用户可以交互的功能,用普通的java技术就完成不了,  sun 就开发了 servlet技术供程序员使用.

  1. servlet的介绍
  • servlet 其实就是java程序(java类)
  • 该 java 程序(java 类)要遵循servlet开发规范
  • serlvet是运行在服务端
  • serlvet 功能强大,几乎可以完成网站的所有功能
  • 是学习jsp基础

servlet的生命周期(工作流程)

WEB服务器首先会检查是否已经装载并创建了该servlet实例对象。如果是直接进行第④步,否则执行第②步。

装载并创建该Servlet的一个实例对象。

调用Servlet实例对象的init()方法。

创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用service()方法并将请求和响应作为参数传递进去。

WEB应用被停止或重启之前,Servlet引擎将卸载Servlet,在卸载之前调用Servlet的destroy()方法

 

  1. 当serlvet 第一次被调用的时候,会触发init函数,该函数会servlet实例装载到内存.init函数只会被调用一次
  2. 然后去调用servlet  的 service 函数
  3. 当第二次后访问该servlet 就直接调用 service 函数.
  4. 当 web应用 reload 或者 关闭 tomcat 或者 关机 都会去调用destroy函数,该函数就会去销毁serlvet
  5. Servlet的生命周期

当客户端第一次向web服务器发出一个servlet请求时,web服务器将会创建一个该servlet的实例,并且调用servlet的init()方法;如果当服务器已经存在了一个servlet实例,那么,将直接使用此实例;然后再调用service()方法,service()方法将根据客户端的请求方式来决定调用对应的doXXX()方法;当 web应用 reload 或者 关闭 tomcat 或者 关机,web服务器将调用destroy()方法,将该servlet从服务器内存中删除。

生命全过程:

1.加载

2.实例化

 3.初始化

 4.处理请求

 5.退出服务

 

  1. 开发servlet有三种方法 
  1. 实现 Servlet接口
  2. 通过继承 GenericServlet
  3. 通过继承 HttpServlet

<!--根据serlvet规范,需要将Servlet部署到web.xml文件,该部署配置可以从examples下拷贝-->

 <servlet>

<!--servlet-name 给该Servlet取名, 该名字可以自己定义:默认就使用该Servlet的名字-->

      <servlet-name>MyFirstServlet</servlet-name>

  <!--servlet-class要指明该Servlet 放在哪个包下 的,形式是 包/包/../类-->

      <servlet-class>com.hsp.MyFirstServlet</servlet-class> 注意:后面不要带.java

    </servlet>

<!--Servlet的映射-->

 <servlet-mapping>

<!--这个Servlet-name要和上面的servlet-name名字一样-->

        <servlet-name>MyFirstServlet</servlet-name>

<!--url-pattern 这里就是将来访问该Servlet的资源名部分-->

        <url-pattern>/ABC</url-pattern>

    </servlet-mapping>

</web-app>

服务器调用流程:http://localhost:8088/ABC--->--->--->--->

  1.  get 提交 和 post的提交的区别
  • 从安全看 get<post 因为get 会把提交的信息显示到地址栏
  • 从提交内容看 get<post get 一般不要大于1k, post理论上无限制,但是在实际              开发中,建议不要大于64k
  • 从速度看 get>post
  • Get可以保留uri中的参数,利于收藏

 

     2.使用通配符在servlet映射到URL中

有两种格式:

第一种格式  *.扩展名  比如 *.do  *.ss

第二种格式  以 / 开头 同时以 /* 结尾  比如  /*   /news/*

在匹配的时候,要参考的标准:

  1. 看谁的匹配度高,谁就被选择
  2. *.do 的优先级最低
  • Servlet单例问题

当Servlet被第一次访问后,就被加载到内存,以后该实例对各个请求服务.即在使用中是单例.

因为 Servlet是单例,因此会出现线程安全问题: 比如:

售票系统. 如果不加同步机制,则会出现问题:

  1. ServletConfig对象

该对象主要用于 读取 servlet的配置信息.

<servlet>

    <servlet-name>ServletConfigTest</servlet-name>

    <servlet-class>com.hsp.servlet.ServletConfigTest</servlet-class>

    <!-- 这里可以给servlet配置信息,这里配置的信息,只能被该servlet 读取 -->

    <init-param>

    <param-name>encoding</param-name>

    <param-value>utf-8</param-value>

    </init-param>

  </servlet>

如何使用

String encoding=this.getServletConfig().getInitParameter("encoding");

补充说明:这种配置参数的方式,只能被某个Servlet独立使用.如希望让所有的Servlet都去读取某个参数,这样配置:

<!-- 如果这里配置参数,可被所有servlet读取 -->

 <!--  

 <context-param>

 <param-name></param-name>

 <param-value></param-value>

 </context-param>

-->

http协议介绍

  • http协议是建立在tcp/ip协议基础上
  • http协议全称 超文本传输协议
  • http协议1.0 , 1.1版本 ,目前通用的是1.1版本

http1.0 称为短连接

http1.1 称为长连接.

所谓长,和短指的是  持续时间的 长连接 1.1 30s ,短连接是发送完数据就断掉.

  1. http的请求部分:

基本结构:

GET /test/hello.html HTTP/1.1 [请求行]

Accept: */*  [消息名]  消息名:内容

Referer: http://localhost:8080/test/abc.html  

Accept-Language: zh-cn

User-Agent: Mozilla/4.0

Accept-Encoding: gzip, deflate  

Host: http://www.sohu.com:80

Connection: Keep-Alive     [消息头格式 (消息名: 内容 )

特别说明: 并不是每一次请求的消息头都一样.]

空行

发送的内容 [格式 : 内容名字=内容体]

  1. 请求方式

请求行中的GET称之为请求方式,请求方式有:POST,GET,HEAD,OPTIONS,DELETE,TRACE,PUT

常用的有:POST,GET

  1. get和post

之前说过

GET News/abc.jsp

  1. http请求消息头
    1.  Accept: text/html,image/*   [告诉服务器,我可以接受 文本,网页,图片]
  1. Accept-Charset: ISO-8859-1 [接受字符编码 iso-8859-1]
  2. Accept-Encoding: gzip,compress [可以接受 gzip,compress压缩后数据.]
  3. Accept-Language: en-us,zh-cn [浏览器支持中,英文]
  4. Host: www.sohu.com:80 [我要找主机是 www.sohu.com:80]
  5. If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT [ 告诉服务器,我的缓冲中有这个资源文件,该文件的时间是 。。。]
  6. Referer: http://www.sohu.com/index.jsp  [告诉服务器,我来自哪里,该消息头,常用于防止盗链]
  7. User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)[告诉服务器,浏览器内核]
  8. Cookie [cookie??]
  9. Connection: close/Keep-Alive   [保持连接,发完数据后,我不关闭连接]
  10. Date: Tue, 11 Jul 2000 18:23:51 GMT [浏览器发送该http请求的时间]
  11. http的响应

格式:HTTP版本号 状态码 原因叙述

举例:HTTP/1.1 200 OK

状态码 含义

100-199 表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程

200-299 表示成功接收请求并完成整个处理过程,常用200

300-399 为完成请求,客户需要进行一步细化请求。例如:请求的资源已经移动一个新的地址,常用302,307

400-499 客户端的请求有错误 404

500-599 服务器端出现错误,常用500

  1. http响应的状态行举例说明

200 就是整个请求和响应过程没有发生错误,这个最常见.

302: 表示当你请求一个资源的时候,服务器返回302 表示,让浏览器转向到另外一个资源,比如: response.sendRedirect(“/web应用/资源名”)

 

案例:

response.setStatus(302);

response.setHeader("Location", "/servletPro/Servlet2");

// 上面两句话等价 response.sendRedirect("/servletPro/Servlet2");

 

404: 找不到资源

500: 服务器端错误

  1. http响应消息头详解
    1. Location: http://www.baidu.org/index.jsp  【让浏览器重新定位到url
    2. Server:apache tomcat 【告诉浏览器我是tomcat
    3. Content-Encoding: gzip 【告诉浏览器我使用 gzip
    4. Content-Length: 80  【告诉浏览器会送的数据大小80节】
    5. Content-Language: zh-cn 【支持中文】
    6. Content-Type: text/html; charset=GB2312 [内容格式text/html; 编码gab2312]
    7. Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT 【告诉浏览器,该资源上次更新时间】
    8. Refresh: 1;url=http://www.baidu.com 【过多久去,刷新到 http://www.baidu.com
    9. Content-Disposition: attachment; filename=aaa.zip 【告诉浏览器,有文件下载】
    10. Transfer-Encoding: chunked  [传输的编码]
    11. Set-Cookie:SS=Q0=5Lb_nQ; path=/search[后面详讲]
    12. Expires: -1[告诉浏览器如何缓存页面IE]
    13. Cache-Control: no-cache  [告诉浏览器如何缓存页面火狐]
    14. Pragma: no-cache   [告诉浏览器如何缓存页面]
    15. Connection: close/Keep-Alive   [保持连接 1.1Keep-Alive]
    16. Date: Tue, 11 Jul 2000 18:23:51 GMT

①定时刷新Refresh使用

 response.setHeader("Refresh", "5;url=/servletPro/Servlet2");

②文件下载 Content-Disposition 

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

//PrintWriter out = response.getWriter();

//演示下载文件

response.setHeader("Content-Disposition", "attachment; filename=winter.jpg");

//打开文件.说明一下web 站点下载文件的原理

//1.获取到要下载文件的全路径

String path=this.getServletContext().getRealPath("/images/Winter.jpg");

//System.out.println("path="+path);

//2创建文件输入流

FileInputStream fis=new FileInputStream(path);

//做一个缓冲字节数组

byte buff[]=new byte[1024];

int len=0;//表示实际每次读取了多个个字节

OutputStream os=response.getOutputStream();

while((len=fis.read(buff))>0){

os.write(buff, 0, len);

}

//缺点: 没有进度条./图标/

//关闭

os.close();

fis.close();

}

 

③缓存讲解

提出问题:浏览器默认情况下,会缓存我们的页面,这样出现一个问题:如果我们的用户习惯把光标停留在地址栏,然后回车来取页面,就会默认调用cache中取数据。

      1. 有些网站要求及时性很高,因此要求我们不缓存页面

代码:

//指定该页面不缓存 Ie

response.setDateHeader("Expires", -1);【针对IE浏览器设置不缓存】

//为了保证兼容性.

response.setHeader("Cache-Control", "no-cache");【针对火狐浏览器等】

response.setHeader("Pragma", "no-cache");【其他浏览器】

      1. 有些网站要求网页缓存一定时间,比如缓存一个小时

response.setDateHeader("Expires", System.currentTimeMillis()+3600*1000*24);后面一个参数表示设置的缓存保持时间,-1表示永远缓存

加入防止盗链下载.

  1. HttpServletResponse的再说明

getWriter()

getOutputStream();

 

区别

  1. getWriter() 用于向客户机回送字符数据
  2. getOutputStream() 返回的对象,可以回送字符数据,也可以回送字节数据(二进制数据)

OutputStream os=response.getOutputStream();

os.write("hello,world".getBytes());

 

如何选择:

如果我们是回送字符数据,则使用  PrintWriter对象 ,效率高

如果我们是回送字节数据(binary date) ,则只能使用 OutputStream

☞ 这两个流不能同时使用.

比如:

OutputStream os=response.getOutputStream();

os.write("hello,world".getBytes());

PrintWriter out=response.getWriter();

out.println("abc");

就会报错:

java.lang.IllegalStateException: getOutputStream() has already been called for this response

 

不能同时使用printWriter和outputstream的原因

  1. 参数的传递方式sendRedirect()和session()

需求: 当用户登录成功后,把该用户名字显示在登录成功页面;

①使用sendRedirect()来传递字符参数

解决思路:

  1. 使用java基础 static
  2. 使用sendRedirect()

代码:

response.sendRedirect("/UsersManager/MainFrame?uname="+username+"&pwd="+password);

  1. 使用session 传递

这里,我们先预热.

 

说明:

基本格式:

response.sendRedirect(“servlet的地址?参数名=参数值&参数名=参数值...”);

 

☞ 参照值是String , 参数名应当使用 字母组合

 

在接受数据的Servlet中:

 

String 参数=request.getParameter(“参数名”);

②使用session()来传递字符参数和对象

A.传递字符串

放入session   request.getSession.setAttribute("loginUser",username);

取出session  在JSP中通过session取出 request.getSession.getAttribute("loginUser");

B.传递对象

User user= new User();

user.setName(“xiaoli”);

user.setPassWord(“123”);

放入session   request.getSession.setAttribute("userObj",userObj);

取出session  User user=(User)request.getSession.getAttribute(“userObj”);

 

中文乱码处理

发生中文乱码有三种情况

 

  • 表单form
  1. post

   在服务器端设置成浏览器端的编码方式。

解决方法:  request.setCharacterEncoding("utf-8"); //gbk gb2312 big5

  1. get

newString=new String(str.getBytes("iso-8859-1"),"utf-8");

该方法和get处理方法一样.

  • sendRedirect() 发生乱码

response.sendRedirect(“servlet地址?username=顺平”);

版本低导致的乱码 

特别说明,如果你的浏览器是 ie6 或以下版本,则我们的 ② 和 ③中情况会出现乱码(当中文是奇数的时候)

解决方法是 :

String info=java.net.URLEncoder.encode("你好吗.jpg", "utf-8");

<a href=”http://www.sohu.com?name=”+ info >测试</a>

response.sendRedirect(“servlet地址?username=”+info);

说明: 我们应当尽量使用post 方式提交;

返回浏览器显示乱码 

在服务端是中文,在response的时候,也要考虑浏览器显示是否正确,一般我们通过

response.setContentType(“text/html;charset=utf-8”); ok

下载提示框中文乱码

补充一个知识点: 当我们下载文件的时候,可能提示框是中文乱码 

String temp=java.net.URLEncoder.encode("传奇.mp3","utf-8");

response.setHeader("Content-Disposition","attachment; filename="+temp);

HttpServletRequest对象的详解

该对象表示浏览器的请求(http请求), 当web 服务器得到该请求后,会把请求信息封装成一个HttpServletRequest 对象

    • getRequestURL方法返回客户端发出请求时的完整URL。
    • getRequestURI方法返回请求行中的资源名部分。
    • getQueryString 方法返回请求行中的参数部分(参数名+值)。

该函数可以获取请求部分的数据 比如

http://localhost/web名?username=abc&pwd=123

request.getQueryString(); 就会得到  username=abc&pwd=123

getRemoteAddr方法返回发出请求的客户机的IP地址

getRemoteHost方法返回发出请求的客户机的完整主机名

getRemotePort方法返回客户机所使用的网络端口号

客户机的端口号是随机选择的,web服务器的端口号是一定的

getLocalPort方法返回web服务器所使用的网络端口号

getLocalAddr方法返回WEB服务器的IP地址。

getLocalName方法返回WEB服务器的主机名

url 和 uri 的区别

比如:

Url=http://localhost:8088/servletPort3/GetinfoServlet 完整的请求

Uri=/servletPort3/GetinfoServlet web应用的名称+资源的名称

//如果接受复选框的内容,则使用getparameterValues

String [] xxxx=request.getParameterValues("xxx");

//如果接受的单选框或input 等等

String xx=request.getParameter("xxx");

 

  1. 请求转发requeset.getRequestDispatcher(资源地址).forward(request,response);

资源地址:不需要项目名。因为它只是在WEB服务器内部转发。

Request.getRequestDispatcher(资源地址).forward(request,response);

我们现在使用 请求转发的方法来实现上次我们使用 response.sendRedirect() 实现效果

使用 request提供的转发方法.

Request中的Attribute在一次请求有效。一次请求:没有返回到浏览器,就为一次请求。

  1. 使用 forward 不能转发到 web应用 url
  2. 因为 forward 是发生在web服务器,所以 Servlet1  Servlet 2使用的是用一个request response.

 

  1. 使用sendRedirect() 方法不能通过request.setAttribute() 把 属性传递给下一个Servlet
  2. 比较sendRedirect()和request.getRequestDispatcher().forward(request,response)

sendRedirect() 和 forward 的区别是什么

          叫法 sendRedirect() 重定向,转发  forward() 叫转向

1、实际发生的位置不一样

sendRedirect 发生 浏览器

forward 发生 web服务器

2、用法不一样

request.getRequestDispatcher(“/资源URI”).forward(request,response)

response.sendRedirect(“/web应用/资源URI”);

3、能够去URL 范围不一样

sendRedirect 可以去 外边URL

forward 只能去当前的WEB应用的资源

  •  什么是一次 http请求:

只要没有停止,也没有回到浏览器重定向,就算一次

  • 如果转发多次,我们的浏览器地址栏,保留的是第一次 转向的那个Servlet Url

 

Jdbc 、Oracle

//1加载驱动

Class.forName("oracle.jdbc.driver.OracleDriver");

//2.得到连接

ct=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:ORCLHSP","scott","tiger");

//3.创建PreparedSatement

ps=ct.prepareStatement("select * from users where id=? and passwd=?");

//? 赋值

ps.setObject(1, id);

ps.setObject(2, password);

 

//4.执行操作

rs=ps.executeQuery();

//5.根据结果左处理

if(rs.next()){

//说明该用户合法

request.getRequestDispatcher("/MainFrame").forward(request, response);

}else{

request.getRequestDispatcher("/LoginServlet").forward(request, response);

}

 

} catch (Exception e) {

e.printStackTrace();

// TODO: handle exception

}finally{

//关闭资源

if(rs!=null){

try {

rs.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

rs=null;

}

if(ps!=null){

try {

ps.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

ps=null;

}

if(ct!=null){

try {

ct.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

ct=null;

}

 

}

注意点

  • 业务逻辑代码和界面分离
  • 把常用的代码(对数据库的连接和操作) 封装到工具类

具体的方法

  • 每一张表对应 一个 domain类(表示数据) 还要对应一个 Service 类

比如 users 表 对应 Users 类(domain 类) UserService类(该类会封装对users表的各种操作) ,实际上这里体现出 数据 和 操作分离的思想

会话技术cookie和session

  1. 什么是会话

基本概念: 指用户开一个浏览器,访问一个网站,只要不关闭该浏览器,不管该用户点击多少个超链接,访问多少资源,直到用户关闭浏览器,整个这个过程我们称为一次会话.

比如打电话.

  1. 为什么需要cookie技术(会话技术)

如何保存用户上次登录时间

如何显示用户浏览历史?

如何把登录的用户名和密码电脑,下次登录,不需要重新输入

解决之道—cookie

  1. cookie的小结
  • cookie 是在服务端创建
  • cookie 是保存在浏览器这端
  • cookie 的生命周期可以通过 

cookie.setMaxAge(2000);

   如果不设置setMaxAge则该cookie的生命周期当浏览器关闭时,就消亡.

  • cookie 可以被多个浏览器共享(与session的区别)
  • 怎么理解

我们可以把cookie 想成一张表

?如果cookie重名会有什么问题?

如果重名就会替换存在的cookie值.

  • 一个web应用可以保存多个cookie,但保存在同一个cookie文本在客户端浏览器下
  • cookie存放的时候是以明文方式存放,因此安全较低.,我们可以通过加密后保存.md5加密算法 :

请大家注意,以后我们的密码都要使用加密存放,在验证密码的时候,对用户输入密码,进行md5加密,然后该到数据库去验证

md5算法

package com.hsp;

import java.security.*;      

import java.security.spec.*;      

     

class MD5_test {      

 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[] strTemp = s.getBytes();      

   MessageDigest mdTemp = MessageDigest.getInstance("MD5");      

   mdTemp.update(strTemp);      

   byte[] md = mdTemp.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) {      

   return null;      

  }      

 }      

 public static void main(String[] args) {      

  // MD5_Test aa = new MD5_Test();      

  System.out.print(MD5_test.MD5("疯狂的逗妇乳"));      

 }      

}    

 

  1. 保存上次登录时间

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

 

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

PrintWriter out = response.getWriter();

//先获取cookie

// 假设我们 保存上次登录时间的cookie "lasttime" 

// 这里我们要考虑一个情况: 用户第一次登录 '您是第一次登录..'

Cookie []cookies=request.getCookies();

boolean b=false;//假设没有lasttime cookie

if(cookies!=null){ //保证有cookie,取遍历

for(Cookie cookie: cookies){

//取出名

String name=cookie.getName();

if("lasttime".equals(name)){

//显示

out.println("您上次登录时间是 "+cookie.getValue());

//更新时间

//把当前日期保存cookie

SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String nowTime=simpleDateFormat.format(new java.util.Date());

Cookie mycookie=new Cookie("lasttime",nowTime);

mycookie.setMaxAge(7*3600*24);//保存一周

response.addCookie(mycookie);

b=true;

break;

}

}

}

 

if(!b){

//没有找到

out.println("您是第一次登录..");

//把当前日期保存cookie

SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String nowTime=simpleDateFormat.format(new java.util.Date());

Cookie cookie=new Cookie("lasttime",nowTime);

cookie.setMaxAge(7*3600*24);//保存一周

response.addCookie(cookie);

}

 

 

 

 

 

}

cookie的细节

  • 一个浏览器最多放入 300cookie,一个web站点,最多 20cookie,而且一个cookie大小限制子4k
  • cookie生命周期的再说明:
  1. cookie默认生命周期是会话级别
  2. 通过setMaxAge() 可以设置生命周期

setMaxAge(正数) , 即多少秒后该cookie失效

setMaxAge(0) ,删除该cookie

setMaxAge(负数), 相当于该cookie生命周期是会话级别.

 

案例 :

//先得到该cookie

Cookie cookies[]=request.getCookies();

for(Cookie cookie: cookies){

if(cookie.getName().equals("id")){

System.out.println("id");

//删除

cookie.setMaxAge(0);

response.addCookie(cookie);//一定带上这句话,否则不能删除

}

}

 

特别说明: 如果该web应用只有一个cookie ,则删除该cookie后,在浏览器的临时文件夹下没有该cookie文件,如果该web应用有多个cookie,则删除一个cookie后,文件还在,只是该cookie没有

 

 

  • cookie存放中文,怎么处理

存放:

String val=java.net.URLEncoder.encode("逗妇乳","utf-8");

Cookie cookie=new Cookie("name",val);

取出:

String val=java.net.URLDecoder.decode(cookie.getValue(), "utf-8");

out.println("name ="+val);

session 

  • session是存在服务器的内存中
  • 一个用户浏览器,独享一个session域对象
  • session中的属性的默认生命周期是30min ,你可以通过 web.xml来修改
  •  
  1. 3种session生命周期的设置

1一个地方是 tomcat/conf/web.xml

  <session-config>

        <session-timeout>30</session-timeout>//表示30分钟的意思

</session-config>

对所有的web应用生效

2另外一个地方,就是在单个web应用的下去修改 web.xml

<session-config>

  <session-timeout>30</session-timeout>session精确到分钟,cookie精确到秒

  </session-config>

如果发生冲突,则以自己的web应用优先级高

3session.setMaxInactiveinterval(60)发呆六十秒后session失效

 

  • session中可以存放多个属性
  • session 可以存放对象
  • 如果 session.setAttribute(“name”,val) , 如果名字重复,则会替换该属性.

如果同一个用户浏览器,向session设置一个属性的时候,如果名字相同了,会出现什么情况?

结论: 会替换该对象值.

  1. session的更深入理解:

为什么服务器能够为不同的浏览器提供不同session?

因为每个浏览器去访问web站点的时候,如果发出的http请求头没有带JSESSIONID头就会自动给你创建一个并返回

过滤器(filter)

①开发过滤器的步骤:

  1. 创建 继承HttpServlet 同时实现Filter接口
  2. 默认filter不生效,需要配置.

<!-- 自己配置的一个filter -->  

  <filter>

   <filter-name>MyFilter</filter-name>

   <filter-class>com.zhy.filter.MyFilter</filter-class>

  </filter>

<filter-mapping>

<filter-name>MyFilter</filter-name>

<url-pattern>/*</url-pattern>  /*表示对该WEB的所有网页都过滤 

</filter-mapping>

  1. 在filter的方法中添加业务逻辑.

package com.hsp.filter;

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

import com.hsp.domain.User;

public class MyFilter1 extends HttpServlet implements Filter {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

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

PrintWriter out = response.getWriter();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

this.doGet(request, response);

}

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

System.out.print("myfilter1...");

//获取session

HttpServletRequest httpServletRequest=

(HttpServletRequest)request;

//看看请求的资源是什么

String uri=httpServletRequest.getRequestURI();

if(uri.startsWith("/UsersManager3/imgs")||uri.startsWith("/UsersManager3/Login")){

//直接放行.

chain.doFilter(request, response);

}else{

HttpSession session=httpServletRequest.getSession();

User user=(User) session.getAttribute("loginuser");

if(user!=null){

//该用户合法,放行

chain.doFilter(request, response);

}else{

request.setAttribute("err", "请好好登陆");

httpServletRequest.getRequestDispatcher("/LoginServlet")

.forward(request, response);

}

}

}

public void init(FilterConfig arg0) throws ServletException {

// TODO Auto-generated method stub

}

}

 

过滤器链

实现方式 :

  1. 在创建一个过滤器 (继承HttpServlet 同时还要实现Filter接口)
  2. 配置过滤器

配置过滤器的顺序就可以决定调用过滤器的顺序.

jsp

jsp为什么会出现?

因为在开发web网站时候,发现servlet做界面比较麻烦,于是又有一个新的技术jsp

jsp是什么?

  1. jsp运行在服务器
  2. jsp(java server page)
  3. jsp的基础是servlet(相当于对servlet进行一个包装)
  4. jsp是综合技术 jsp=html+css+javascript+java代码+jsp标签(servlet)
  5. jsp无需配置.直接使用,如果你修改了jsp文件,不需要重新reload web应用.
  6. jsp如何方法 http://ip:8088/web应用名/jsp路径
  7. jsp是一种动态网页技术.
  1. 就是有多个<% %> 
  2. 在<% %> 中定义的变量,会成为service函数的局部变量.
  3.  Web服务器在调用jsp时,会给jsp提供一些什么java对象

供提供了九个

JSP的9个内置对象

对象名 类型 作用域

request:请求对象  javax.servlet.ServletRequest的子类 Request

response:响应对象 javax.servlet.ServletResponse的子类   Page

pageContext:页面上下文对象 javax.servlet.jsp.PageContext Page

session:会话对象 javax.servlet.http.HttpSession Session

application:应用程序对象 javax.servlet.ServletContext  Application

out:输出对象 javax.servlet.jsp.JspWriter     Page

config:配置对象 javax.servlet.ServletConfig Page

page:页面对象  java.lang.Object Page

exception:异常对象 java.lang.Throwable Page

 

jsp的语法

  • 指令元素

概念: 用于从jsp发送一个信息到容器,比如设置全局变量,文字编码,引入包

  1. page指令

<%@ page contentType="text/html;charset=gb2312"%>

常用的属性:

contentType 和 pageEncoding的区别

contentType=text/html;charset=utf-8 指定网页以什么方式显示页面

pageEncoding=utf-8 指定Servlet引擎以什么方法翻译jsp->servlet  指定网页以什么方式显示页面

  1. include指令

用法:<%@ include file=”文件路径” %>

  1. taglib指令 

<mytag:xx 属性 />

  • 脚本元素

java片段:<% java 代码 %>

表达式:<%=表达式 %>

定义变量:<%! int i=90; %>

定义函数:<%! public int getResult(int a,int b){return a+b;}%>

函数不能在<% %> 定义.

  • 动作元素

<jsp:forward file=””> 的作用

在开发jsp的过程中,我们通常把jsp放入WEB-INF目录,目的是为了防止用户直接访问这些jsp文件.

在WebRoot下我们有一个入口页面,它的主要转发

<jsp:forword file=”/WEB-INF/xx.jsp”></jsp:forword> 写.

<jsp:incluce file=””></jsp:inclcue>

动态引入:

<%@ include file=””%> 静态引入

<jsp:incluce  file=””></jsp:incule> 动态引入

相同点: 把一个文件引入到另外一个文件

区别:静态引入 把两个jsp翻译成一个Servlet,所以被引入的文件不要包含<body><html>..

动态引入 把两个jsp分别翻译,所以被引入的jsp包含有<html><body>也可以.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值