第1章B/S与C/S结构

1.1 背景知识介绍

J2EE的13种技术

java->servlet->jsp [技术总是有一个演变过程]

zip粘贴到word设置

1.2 回顾一下我们现有的技术

java 基础(面向对象,集合,界面,线程,文件,网络)

jdbc (java 的数据库编程)

oracle / mysql / sqlserver

html css javascript (web  开发)  ->网页设计

xml

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

java ee 体系的介绍

servlet项目演示

web 开发介绍

① 静态页面 (html)

② 动态页面

1. 用户可以输入数据,和页面交互(注册,购物,发帖子,付款...)

2. 不同时间打开页面,内容是变化.

3. 目前比较流行的左动态页面的技术 ( servlet/jsp , php , asp.net , asp, cgi )

1.3 动态网页技术的比较(了解)
1.3.1 bs 和 cs的比较

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

(2)cs client server客户服务

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

1.3.2 模拟一个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();

}

}

第2章Tomcat的安装与详解

2.1 通过tomcat来讲解BS结构

2.1.1 安装tomcat服务器

解压即可,注意,全英文路径

2.1.2 配置Tomcat

① 在环境变量中添加

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

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

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

2.1.3启动tomcat服务器

到 tomcat 主目录下bin/startup.bat

2.1.4验证是否安装成功

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

2.2 Tomcat安装后问题解决

2.2.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 服务器是启动

2.3 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文件

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

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

现在我们要求:把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应用的信息.

2.3.3 Tomcat如何去管理虚拟目录

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

我在d 盘有一个web应用.

(1)虚拟目录配置步骤:

a)找到server.xml文件

b)编辑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

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

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

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

context  的几个属性的说明

path:

docbase:

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

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

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

②:

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

2.3.4配置域名

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

我们在实际访问网站的过程中,不可能使用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) 重启生效

2.3.5 Tomcat体系的再说明

图:

2.3.6 如何配置默认主机

在tomcat/conf/server.xml 文件

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

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

第3章 为什么需要servlet技术?

3.1 servlet的介绍

① servlet 其实就是java程序(java类)

② 该 java 程序(java类)要遵循servlet开发规范

③ serlvet是运行在服务端

④ serlvet 功能强大,几乎可以完成网站的所有功能

⑤ 是学习jsp基础

3.2 tomcat 和 servlet 在网络中的位置

3.3 Servlet的生命周期

3.3.1 servlet的生命周期是怎样的/servlet究竟是怎样工作的

UML 时序图帮助大家理解

参看execel

u 说明:

当在浏览器内输入URL的时候,浏览器会首先寻找localhost所对应的ip地址,浏览器发现IP地址是127.0.0.1,这个地址指代的是本地机,也就是用于本机和本机之间互相通信的ip地址,一般用来做软件测试,当查到这个ip地址之后,浏览器就会把http请求发送到本地服务器上,这里就是tomcat上,然后web服务器会解析主机,解析web应用,解析资源名(也就是那个URL最后面的.html文件),然后查询web.xml文件里面该资源名所对应的包..

在这种情况下,浏览器不会访问dns(也就是本机ip,本机ip是用来连接外网的,刚才那个叫本地ip),也就是不访问外网。当我们输入外网的URL的时候,比如输入:www.taobao.com

当然这个时候就需要访问外网,浏览器就会找到淘宝的web服务器,返回一个淘宝的web首页面

3.3.2 面试题: 请简述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.退出服务

3.4 开发servlet有三种方法
3.4.1 实现servlet接口的方式

需求如下: 请使用实现 接口的方式,来开发一个Servlet,要求该Servlet可以显示Hello,world,同时显示当前时间.

步骤

1. 在webapps下建立一个web应用hspWeb1

2. 在hspWeb1 下建立WEB-INF->web.xml [web.xml可以从ROOT/WEB-INF/web.xml拷贝]

3. 在WEB-INF 下建立classes 目录(我们的Servlet就要在该目录开发.),建立  lib文件夹

4. 开发MyServlet.java

package com.hsp;

import javax.servlet.*;

import javax.servlet.http.*;  为了能将servlet-api.jar包引入,需要配置环境变量

 

变量值; E:\tomcat\apache-tomcat-6.0.20\lib\servlet-api.jar 记得带上文件名

 

import java.io.*;

class MyFirstServlet implements Servlet

{

//该函数用于初始化servlet,就是把该servlet装载到内存中

//该函数只会被调用一次

public void init(ServletConfig config)

throws ServletException{

}

//得到ServletConfig对象

public ServletConfig getServletConfig(){

return null;

}

//该函数是服务函数,我们的业务逻辑代码就是写在这里

//该函数每次都会被调用

public void service(ServletRequest req,

ServletResponse res)

throws ServletException,

java.io.IOException{

}

//该函数时得到servlet配置信息

public java.lang.String getServletInfo(){

return null;

}

//销毁该servlet,从内存中清除,该函数被调用一次

public void destroy(){

}

}

5. 根据Servlet规范,我们还需要部署Servlet

<?xml version="1.0" encoding="ISO-8859-1"?>

<!--

Licensed to the Apache Software Foundation (ASF) under one or more

contributor license agreements.  See the NOTICE file distributed with

this work for additional information regarding copyright ownership.

The ASF licenses this file to You under the Apache License, Version 2.0

(the "License"); you may not use this file except in compliance with

the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software

distributed under the License is distributed on an "AS IS" BASIS,

WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and

limitations under the License.

-->

<web-app xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

version="2.5">

<!--根据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--->①--->②--->③--->④

6. 在浏览器中测试

在浏览器中输入

http://localhost:8088/hspweb1/ABC

7. 分析一下自己写可能出现的错误

(1) <servlet-name>MyFirstServlet</servlet-name> 名字不一样 (启动tomcat错误)

(2)<servlet-class>com.hsp.MyFirstServlet</servlet-class>  写成 MyFirstServlet.java,会报告500

(3)资源名自己写错

http://localhost:8088/hspweb1/错误的资源url-pattern

404 错误

补充: 如果使用javac去编译一个java文件,则需要带命令参数

javac –d . java文件

补充: 如何不重启tomcat,就指定去reload 一个web应用,方法:

进入到 tomcat 的  manager:

点击reload即可.

课堂练习

自己使用 实现Servlet接口的方法,开发一个Servlet,该servlet可以输出自己的名字

在显示当前日期.

3.4.2 使用GenericServlet开发servlet

了解即可:

案例 :

package com.hsp;

import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

public class MyGenericServlet extends GenericServlet

{

public  void service(ServletRequest req,

ServletResponse res)

throws ServletException,

java.io.IOException{

res.getWriter().println("hello,world,i am geneirc servlet");

}

}

将该Servlet部署到web.xml文件中:

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

<servlet>

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

<servlet-name>MyGenericServlet</servlet-name>

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

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

</servlet>

<!--Servlet的映射-->

<servlet-mapping>

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

<servlet-name>MyGenericServlet</servlet-name>

<!--url-pattern 这里就是将来访问该Servlet的资源名部分,默认命名规范:

就是该Servlet的名字-->

<url-pattern>/MyGenericServlet</url-pattern>

</servlet-mapping>

3.4.3 使用继承 HttpServlet 的方法来开发Serlvet

(1)在软件公司 90%都是通过该方法开发.

(2)举例说明; 还是显示 hello,world 当前日期

代码:

package com.hsp;

import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

public class MyHttpServlet extends HttpServlet

{

//在HttpServlet中,设计者对post提交和 get提交分别处理

//回忆 <form action="提交给?" method="post|get"/>,默认是get

protected void doGet(HttpServletRequest req,

HttpServletResponse resp)

throws ServletException,

java.io.IOException{

resp.getWriter().println("i am httpServet doGet()");

}

protected void doPost(HttpServletRequest req,

HttpServletResponse resp)

throws ServletException,

java.io.IOException{

resp.getWriter().println("i am httpServet doPost() post name="+req.getParameter("username"));

}

}

还有一个login.html

<html>

<body>

<form action="/hspWeb1/MyHttpServlet" method="post">

u:<input type="text" name="username"/>

<input type="submit" value="login"/>

</body>

</html>

3.4.4 小结 get 提交 和 post的提交的区别

① 从安全看 get<post 因为get 会把提交的信息显示到地址栏

② 从提交内容看 get<post get 一般不要大于2k, post理论上无限制,但是在实际              开发中,建议不要大于64k

③ 从速度看 get>post

④ Get可以保留uri中的参数,利于收藏

3.4.5 使用ide来开发servlet

使用ide (eclipse[java se]+myeclipse[插件 可以支持jsp/servlet/struts/hibernate/spring..])开发servlet

需求:使用 ide 开发一个servlet ,该servlet显示 hello,world,和当前日期

(1)开发步骤:

1)建立web工程

2)在Src目录下创建了一个包 com.hsp.servlet

3)开发一个Servlet

MySerlvet 的代码:

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

out.println("hello "+new java.util.Date().toString() );

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

this.doGet(request, response);

}

(2)配置tomcat

点击add 选择要发布到那个服务器即可:

(3)启动tomcat

1. 使用我们的老方法

2. 从eclipse 启动 tomcat

(4)在使用eclipse开发servlet可能会出现一个很麻烦事情,版本不一致错误.

java.lang.UnsupportedClassVersionError: Bad version number in .class file (unable to load class com.hsp.servlet.MyServlet1)

原因是因为 tomcat 使用jdk 和servlet 使用的jdk不一样,

解决方法就是统一即可.

请大家使用eclipse 并配置继承 HttpServlet 开发一个servlet,显示hello,和当前日期.

3.4.6 Servlet的细节问题

①一个已经注册的Servlet可以被多次映射即:

<servlet>

<description>This is the description of my J2EE component</description>

<display-name>This is the display name of my J2EE component</display-name>

<!-- servlet的注册名-->

<servlet-name>MyServlet1</servlet-name>

<!-- servlet类的全路径(包名+类名) -->

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

</servlet>

<!-- 对一个已经注册的servlet的映射-->

<servlet-mapping>

<!-- servelt的注册名-->

<servlet-name>MyServlet1</servlet-name>

<!-- servlet的访问路径-->

<url-pattern>/MyServlet1</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>MyServlet1</servlet-name>

<url-pattern>/hsp</url-pattern>

</servlet-mapping>

②当映射一个servlet时候,可以多层 比如

<url-pattern>/servlet/index.html</url-pattern> ok

从这里还可以看出,后缀名是 html不一定就是 html,可能是假象.

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

有两种格式:

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

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

通配符练习题:

l Servlet1 映射到 /abc/*

l Servlet2 映射到 /*

l Servlet3 映射到 /abc

l Servlet4 映射到 *.do

问题(面试题):

l 当请求URL为“/abc/a.html”,“/abc/*”和“/*”都匹配,哪个servlet响应

Servlet引擎将调用Servlet1。

l 当请求URL为“/abc”时,“/abc/*”和“/abc”都匹配,哪个servlet响应

Servlet引擎将调用Servlet3。

l 当请求URL为“/abc/a.do”时,“/abc/*”和“*.do”都匹配,哪个servlet响应

Servlet引擎将调用Servlet1

l 当请求URL为“/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应

Servlet引擎将调用Servlet2。

l 当请求URL为“/xxx/yyy/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应

Servlet引擎将调用Servlet2。

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

(1) 看谁的匹配度高,谁就被选择

(2) *.do 的优先级最低

④Servlet单例问题

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

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

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

这里我给大家一个原则:

(1) 如果一个变量需要多个用户共享,则应当在访问该变量的时候,加同步机制

synchronized (对象){

//同步代码

}

(2)如果一个变量不需要共享,则直接在doGet() 或者doPost()定义.这样不会存在线程安全问题

⑤ servlet 中的<load-on-startup> 配置

需求: 当我们的网站启动的时候,可能会要求初始化一些数据,(比如创建临时表),在比如:

我们的网站有一些要求定时完成的任务[ 定时写日志,定时备份数据.. 定时发送邮件..]

解决方法: 可以通过 <load-on-startup>配合 线程知识搞定.

先说明<load-on-startup>: 通过配置<load-on-startup> 我们可以指定某个Servlet自动创建.

我们来模拟一个定时发送电子邮件的功能:

实现思路:

sendEmailTable

id content sendtime

1 “hello” 2011-11-11 20:11

2 “hello2” 2012-11-11 10:00

看看如何线程去完成任务:

这里的代码请参考项目:

SendMailThread.java

package com.hsp.model;

public class SendEmailThreadextends Thread{

@Override

public void run() {

int i=0;

try {

while(true){

//每休眠一分钟,就去扫表sendmail,看看那份信件应当被发出

Thread.sleep(10*1000);

System.out.println("发出 第"+(++i)+"邮件");//javamail

}

} catch (Exception e) {

e.printStackTrace();

// TODO: handle exception

}

}

}

MyInitServlet1.java

public void init()throws ServletException {

// Put your code here

System.out.println("MyInitServlet1的init被调用..");

//完成一些初始化任务

System.out.println("创建数据库,表,读取参数");

//创建一个线程

SendEmailThread sendEmailThread=new SendEmailThread();

sendEmailThread.start();

}

说明:

<!-- 1表示该servlet被init的顺序 -->

<load-on-startup>1</load-on-startup>

3.5 ServletConfig对象
3.5.1 该对象主要用于读取 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>

-->

3.5.2 如果要把所有的参数都读取,则使用 如下方法

Enumeration<String> names=this.getServletConfig().getInitParameterNames();

while(names.hasMoreElements()){

String name=names.nextElement();

System.out.println(name);

System.out.println(this.getServletConfig().getInitParameter(name));

}

补充,如何去修改Servlet的配置模板.

 编写项目

1. 先完成用户登录

2. 添加在主界面,添加一个超链接,可以返回登录界面重写登录

第4章 http协议详解

① http协议是建立在tcp/ip协议基础上

② http协议全称 超文本传输协议

③ http协议1.0 , 1.1版本 ,目前通用的是1.1版本

http1.0 称为短连接

http1.1 称为长连接.

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

4.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     [消息头格式 (消息名:内容 )

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

空行

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

4.1.1 请求方式get和post

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

常用的有:POST,GET

参看ppt,和以前的笔记

GET News/abc.jsp

4.1.2 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请求的时间]

关于Referer的实际案例:

4.1.3 防盗链

//获取用户浏览器Referer

String referer=request.getHeader("Referer");

if(referer==null||!referer.startsWith("http://localhost:8088/servletPro")){

response.sendRedirect("/servletPro/Error");

return;

}

红色的部分可以根据实际情况来修改.

4.2 http的响应

基本结构:

状态行:

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

举例:HTTP/1.1 200 OK

状态码含义

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

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

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

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

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

4.2.1 http响应的状态行举例说明

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

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

案例:

response.setStatus(302);

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

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

404: 找不到资源

500: 服务器端错误

4.2.2 http响应消息头详解

Location: http://www.baidu.org/index.jsp  【让浏览器重新定位到url】

Server:apache tomcat 【告诉浏览器我是tomcat】

Content-Encoding: gzip 【告诉浏览器我使用 gzip】

Content-Length: 80  【告诉浏览器会送的数据大小80节】

Content-Language: zh-cn 【支持中文】

Content-Type: text/html; charset=GB2312 [内容格式text/html;编码gab2312]

Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT 【告诉浏览器,该资源上次更新时间】

Refresh: 1;url=http://www.baidu.com【过多久去,刷新到 http://www.baidu.com】

Content-Disposition: attachment; filename=aaa.zip【告诉浏览器,有文件下载】

Transfer-Encoding: chunked  [传输的编码]

Set-Cookie:SS=Q0=5Lb_nQ; path=/search[后面详讲]

Expires: -1[告诉浏览器如何缓存页面IE]

Cache-Control: no-cache  [告诉浏览器如何缓存页面火狐]

Pragma: no-cache   [告诉浏览器如何缓存页面]

Connection: close/Keep-Alive   [保持连接1.1是Keep-Alive]

Date: Tue, 11 Jul 2000 18:23:51 GMT

4.2.3 定时刷新Refresh使用

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

4.2.4 文件下载 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();

}

4.2.5 缓存讲解

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

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

代码:

//指定该页面不缓存 Ie

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

//为了保证兼容性.

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

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

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

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

练习:

加入防止盗链下载.

4. 3 HttpServletResponse的再说明
4.3.1 getWriter()和getOutputStream()的区别

3 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

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

Web服务器会自动检查并关闭流

从该图,我们也可以看出. 为什么我们没有主动关闭流,程序也没有问题的原因.

当然:你主动关闭流,更好.

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

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

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

解决思路:

1. 使用java基础static

2. 使用sendRedirect()

代码:

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

3. 使用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”);

上机练习:

1. 实际运用到项目:在wel页面中显示登录用户的姓名,就可以使用该方法.让我们动手一起来做做吧!

2. 请写一篇关于HTTP协议的笔记,要求:

• 描述清楚HTTP请求头、响应头的格式

• 请求头和响应头中各个头字段的含义

l  如果浏览器传递给WEB服务器的参数内容超过1K,应该使用那种方式发送请求消息?

l  请描述200、302、304、404和500等响应状态码所表示的意义。

l  请列举三种禁止浏览器缓存的头字段,并写出相应的

4.4 中文乱码处理

发生中文乱码有三种情况

4.4.1 表单form

(1) post

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

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

(2) get

写一个工具类:

package com.hsp.utils;

public class MyTools {

public static String getNewString(String str) {

String newString="";

try {

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

} catch (Exception e) {

e.printStackTrace();

// 把iso-8859-1 转换成 utf-8

}

return newString;

}

}

4.4.2 超链接

<a href=”http://www.sohu.com?name=函数后”>测试</a>

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

4.4.3 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);

4.5 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服务器的主机名

4.5.1 url 和 uri 的区别

比如:

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

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

练习题:

请在服务器这端,给浏览器回送该浏览器发送的具体请求内容是什么?

韩顺平

http://localhost:8088/web名/GetInfoServlet?abc=123&uu=90&iio=中国

大龙

http://localhost:8088/web名/GetInfoServlet?kkk=你好&email=dalong@sohu.com

你的请求是

kkk=你好

email=dalong@sohu.com

4.5.2 如何获取用户提交的内容(通过表单提交的内容)

代码:

界面:

package com.hsp;

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class MyInfoForm extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

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

PrintWriter out = response.getWriter();

out.println("<form action='/servletPro3/RegisterCl' method='post'><br/>");

out.println("<input type='hidden' value='abc' name='hidden1'/>");

out.println("用户名:<input type='text' name='username'/><br/>");

out.println("密 码:<input type='password' name='pwd'/><br/>");

out.println("性 别:<input type='radio' name='sex' value='男'/>男<input type='radio' name='sex' value='女'/>女<br/>");

out.println("你的爱好:<input type='checkbox' name='hobby' value='音乐'>音乐<input type='checkbox' name='hobby' value='体育'>体育<input type='checkbox' name='hobby' value=\"旅游\">旅游<br/>");

out.println("所在城市:<select name='city'><option value='bj'>北京</option><option value='cq'>重庆</option></select><br/>");

out.println("你的介绍:<textarea cols='20' rows='10' name='intro' >请输入介绍..</textarea><br/>");

out.println("提交照片:<input type='file' name='photo'><br/>");

//什么时候使用hidden传输数据1.不希望用户看到该数据2. 不希望影响节目,同时使用该数据

out.println("<input type='submit' value='提交信息'/>");

out.println("</form>");

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

this.doGet(request, response);

}

}

接受信息的Servlet:

package com.hsp;

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class RegisterClextends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

request.setCharacterEncoding("utf-8");

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

PrintWriter out = response.getWriter();

String u=request.getParameter("username");

String p=request.getParameter("pwd");

String sex=request.getParameter("sex");

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

String [] hobbies=request.getParameterValues("hobby");

String city=request.getParameter("city");

String intro=request.getParameter("intro");

String hidden1=request.getParameter("hidden1");

out.println("用户名="+u+"<br/>");

out.println("密 码="+p+"<br/>");

out.println("性  别="+sex+"<br/>");

if(hobbies!=null){

for(int i=0;i<hobbies.length;i++){

out.println("爱好:"+hobbies[i]);

}

}else{

out.println("你没有爱好");

}

out.println("<br/>所在城市:"+city);

out.println("<br/>个人介绍:"+intro);

out.println("<br/>隐藏控件数据:"+hidden1);

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

this.doGet(request, response);

}

}

练习题:请大家自己写一个表单,提交数据(个人名字:电子邮件:性别:你喜欢的城市 select(可以选多个):  你的特长(checkbox) 你的个人签名,用hidden传输重要数据)

4.5.3 requeset.getRequestDispatcher(资源地址).forward(request,response)

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

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

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

使用 request提供的转发方法.

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

◆请求转发的的(uml)图

这里我们画图说明(uml)

1. 使用 forward不能转发到 该web应用的 url

2. 因为 forward是发生在web服务器,所以Servlet1 和Servlet 2使用的是用一个request和response.

●使用sendRedirect() 方法不能通过request.setAttribute()把 属性传递给下一个Servlet

4.5.4 比较sendRedirect()和forward(request,response)

请问  sendRedirect() 和 forward 的区别是什么

答:

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

(2) 实际发生的位置不一样

sendRedirect 发生 浏览器

forward 发生 web服务器

(3) 用法不一样

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

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

(4) 能够去URL 范围不一样

sendRedirect 可以去 外边URL

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

☞ 什么是一次 http请求:

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

比如;

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

第5章 用户管理系统的概要

5.1 登录验证

◆用户管理系统的继续开发

◆用户管理系统的框架图

① 增加到数据库去验证用户功能

(1) 在oracle 数据库中创建一张表

users

create table users

(id number primary key,

username varchar2(32) not null,

email varchar2(64) not null,

grade number default 1,

passwd varchar2(32) not null)

初始化一些数据

insert into users values(1,’aaaaa1’,’aaaa1@sohu.com’,1,’123’);

insert into users values(2,’aaaaa2’,’aaaa2@sohu.com’,1,’123’);

insert into users values(3,’aaaaa3’,’aaaa3@sohu.com’,1,’123’);

insert into users values(4,’aaaaa4’,’aaaa4@sohu.com’,1,’123’);

insert into users values(5,’aaaaa5’,’aaaa5@sohu.com’,5,’123’);

(2) 在LoginClServlet 中添加到数据库验证用户的功能.

ok:

//到数据库中取验证

Connection ct=null;

ResultSet rs=null;

PreparedStatement ps=null;

try {

//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) {

e.printStackTrace();

}

rs=null;

}

if(ps!=null){

try {

ps.close();

} catch (SQLException e) {

e.printStackTrace();

}

ps=null;

}

if(ct!=null){

try {

ct.close();

} catch (SQLException e) {

e.printStackTrace();

}

ct=null;

}

}

② 如果输入的用户id 密码不正确,则给出提示.

课后练习; 参看给出的用户管理开发文档,完成1, 2, 3 页面功能[分页和安全性暂时不考虑.]

③ 用户管理系统的界面添加图片

5.2 分页功能的实现
5.2.1 分页算法

思路:

定义四个分页变量

pageNow   表示第几页,该变量是由用户来决定,因此变化

pageSize    每页显示几条记录,由程序指定,也可以由用户定制

pageCount  表示共有多少页,该变量是计算出来->思考 怎样确定

rowCount   共有多少条记录,该变量是查询数据库得到

如何确定pageCount

(1)

if(rowCount% pageSize==0){

pageCount=rowCount/pageSize;

}else{

pageCount= rowCount/pageSize+1;

}

试试: 比如 users表9 条记录pageSize=3  =>pageCount=3

比如 users表10 条记录pageSize=3  =>pageCount=4

(2)

上面的算法等价于

pageCount=rowCount% pageSize==0 ? rowCount/pageSize: rowCount/pageSize+1;

该运算称为三目运算

(3)

更简单的算法是:

pageCount=(rowCount-1)/pageSize+1;

试试: 比如 users表9 条记录pageSize=3  =>pageCount=3

比如 users表11 条记录pageSize=3  =>pageCount=4

回忆: oracle 分页的select

取出4,5,6条记录

select * from (select t.*,rownum rn from (select * from t_users order by id) t where rownum<=6) where rn>=4

5.2.2 功能实现

public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {

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

response.setCharacterEncoding("utf-8");

PrintWriter out = response.getWriter();

out.println("<script type='text/javascript' language='javascript'>");

out.println("function gotoPageNow(){ " +

"var pageNow=document.getElementById('pageNow'); " +

"window.open('/UserManager2/ManageUser?pageNow='+pageNow.value,'_self');}");

out.println("</script>");

//到数据库中去验证

Connection ct=null;

ResultSet rs=null;

PreparedStatement ps=null;

int pageNow=1;    //表示第几页,该变量是由用户来决定,因此变化

//得到用户选择显示的页面

String pageNowStr=request.getParameter("pageNow");

if(pageNowStr!=null)

{

pageNow=Integer.parseInt(pageNowStr);

}

int pageSize=3;  //每页显示几条记录,由程序指定,也可以由用户定制

int pageCount=1; //表示共有多少页,该变量是计算出来->思考 怎样确定

int rowCount=1;  //共有多少条记录,该变量是查询数据库得到

try {

//1.加载驱动

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

//2.得到链接

ct=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:XE","system","leemllian");

//算出总共有多少页

//1.查询rowCount

ps=ct.prepareStatement("select count(*) from t_users");

rs=ps.executeQuery();

rs.next(); //把游标下移

rowCount=rs.getInt(1);

//计算pageCount

if(rowCount% pageSize==0)

{

pageCount=rowCount/pageSize;

}

else

{

pageCount= rowCount/pageSize+1;

}

//3.创建PreparedStatement

//如果给出的条件是 pageNow=3 pageSize=3

ps=ct.prepareStatement("select * from (select t.*,rownum rn from (select * from t_users order by id) t where rownum<="+pageNow*pageSize+") where rn>="+(pageSize*(pageNow-1)+1));

//4.执行操作

rs=ps.executeQuery();

//5.根据结果做处理

out.println("<table border=1 cellspacing=0 bordercolor=green width=600px>");

out.println("<tr><th>用户ID</th><th>用户名</th><th>Email</th><th>级别</th></tr>");

while(rs.next())

{

out.println("<tr align=center><td>"+rs.getInt(1)+"</td><td>"+rs.getString(2)+"</td><td>"+rs.getString(3)+"</td><td>"+rs.getInt(4)+"</td></tr>");

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

}

out.println("</table>");

if(pageNow!=1)

{

out.println("<br/><a href='/UserManager2/ManageUser?pageNow="+(pageNow-1)+"'>上一页</a>");

}

for(int i=1;i<=pageCount;i++)

{

out.println("<a href='/UserManager2/ManageUser?pageNow="+i+"'><"+i+"></a>  ");

}

if(pageNow!=pageCount)

{

out.println("<a href='/UserManager2/ManageUser?pageNow="+(pageNow+1)+"'>下一页</a>");

}

out.println("当前页"+pageNow+"/总页数"+pageCount);

out.println("<br/>跳转到:<input type='text' id='pageNow' name='pageNow' size=10 /><input type='button' value='跳转' onClick='gotoPageNow()'/> ");

} catch (Exception e) {

System.out.println(e);

}finally{

try {

if(rs!=null){

rs.close();

}

} catch (Exception e) {

System.out.println(e);

}

rs=null;

try {

if(ps!=null){

ps.close();

}

} catch (Exception e) {

System.out.println(e);

}

ps=null;

try {

if(ct!=null){

ct.close();

}

} catch (Exception e) {

System.out.println(e);

}

ct=null;

}

}

5.2.3 练习

特别说明: 如果某个web应用你不需要,请把该web应用从webapps目录下移走,否则tomcat启动的速度会越来越慢.

上机练习题:

1. 完成自己项目的分页

2. 再做一个  上一页 1 2 3 4 5 6  下一页   当前页/总页数

跳转到 [ ] 页 跳  【如何在servlet中使用js技术】

3. 思考题:

如何控制我们的超链接只显示10页,    <<  1 2 3 4 5 6 7 8 9 10   >>

>> 显示后面的10页  <<显示前10页

如何控制直接输入跳转页的时候,pageNow的值过大的问题?

5.3 MVC模式修改用户管理系统
5.3.1 对当前网站结构的问题分析

1.在LoginCl.java 文件和ManageUser.java文件中都去操作了数据库,它们的逻辑相似,有重复代码

2.整个框架没有清晰的层次关系,显得非常乱.

3.代码一点也不优雅, 可读性差,可维护性差.

解决方法:

指导思想:

① 业务逻辑代码和界面分离

② 把常用的代码(对数据库的连接和操作)封装到工具类

具体的方法

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

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

上机练习:

包登录部分改成mvc模式,建议先保存一份项目,再改.

④ 完成分页的mvc模式改写

首先在UsersService 类中添加方法

//? 为什么要返回ArrayList ,而不是我们想到ResultSet

//1. ArrayList 中封装 User对象,更加符合面向对象的编程方式  OOP

//2.我们通过 Resulst->User对象->ArrayList这样ArrayList和 Resultset没有关系,就可以及时关闭数据库资源.

public ArrayList getUsresByPage(int pageNow,int pageSize){

reutrn al;

}

练习: 把我们的用户管理系统出了  cookie和 session相关的功能不做,其它都做了.

5.3.2 完成用户管理系统的crud操作

1. 一个请求对应一个控制器

优点: 逻辑清晰

缺点: 会造成控制器过多

可以这样考虑:一类事务请求,我们做一个控制器,即让该控制器可以处理多个请求,为了让一个控制器去区分,不同的请求,我们可以这样做:

在发出请求的同时,在带一个type=del 或者 type=add 或者  type=update...,  在控制器中我们接收type的值,从而判断用户希望做什么事情!

关于跳转到修改用户界面有两种思路:

(1) 传递用户id号的同时,把用户的其它信息一并传递,这样可以减少数据库查询的次数(缺点:增加网络开销 100字节*1000000*2 ,优点:减少对数据库的一次操作)

(2) 只传递用户id好,控制器接收到id后,再查询数据库,从而显示.

添加用户

(1) 用户id号,我们做成子增长

在oracle中先建立一个sequece

create sequence users_seq

start with 11

increment by 1

minvalue 11

nomaxvalue

nocycle

nocache

课堂练习

添加查询用户功能:按照老师给出网站结构写.

第6章 会话技术 cookie和session

◆ 什么是会话

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

6.1 Cookie详解
6.1.1 为什么需要cookie技术

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

如何显示用户浏览历史?

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

u 解决之道—cookie

6.1.2 cookie的原理图
6.1.3 cookie小结

① cookie 是在服务端创建

② cookie 是保存在浏览器这端

③ cookie 的生命周期可以通过

cookie.setMaxAge(2000);

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

④ cookie 可以被多个浏览器共享(与session的区别)

⑤ 怎么理解

我们可以把cookie 想成一张表

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

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

⑥ 一个web应用可以保存多个cookie,但保存在同一个cookie文本在客户端浏览器下

⑦ cookie存放的时候是以明文方式存放,因此安全较低.,我们可以通过加密后保存.

6.1.4 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("韩顺平"));

}

}

6.1.5 保存上次登录的时间

public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {

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

PrintWriter out = response.getWriter();

//先获取cookie

// 假设我们 保存上次登录时间的cookie "lasttime" "2011-11-11 12:12:12";

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

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自动保存用户密码

打开登录页面的时候,自动填写该用户的用户名和密码【这个要求学员课堂练习(最好单开一个项目)】

◆cookie保存浏览商品

请自己作为作业考虑实现

6.1.6 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没有。

6.1.7 cookie的细节

① 一个浏览器最多放入 300cookie,一个web站点,最多20cookie,而且一个cookie大小限制子4k

② 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);

6.2 session详解

◆session为什么有?

问题1: 如何实现在不同的页面,可以去查看信息(比如说购物车),同时还要实现不同的用户看到的信息是自己.

6.2.1 session工作原理图
6.2.2 session生命周期

系统默认是30分钟。

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应用优先级高

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

对session和cookie生命周期小结:

6.2.3 session小结

① session是存在服务器的内存中

② 一个用户浏览器,独享一个session域对象

③ session中的属性的默认生命周期是30min,你可以通过 web.xml来修改

④ session中可以存放多个属性

⑤ session 可以存放对象

⑥ 如果 session.setAttribute(“name”,val) , 如果名字重复,则会替换该属性.

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

结论: 会替换该对象值

6.2.4 session的更深入理解

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

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

6.2.5 生成验证码案例

使用(原理是使用到java的绘图技术.)

这里最重要的就是生成验证码的servlet

package com.hsp;

import java.awt.*;

import java.awt.image.BufferedImage;

import java.io.*;

import java.util.Random;

import javax.imageio.ImageIO;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class CreateCodeextends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {

// 7.禁止浏览器缓存随机图片

response.setDateHeader("Expires", -1);

response.setHeader("Cache-Control","no-cache");

response.setHeader("Pragma","no-cache");

// 6.通知客户机以图片方式打开发送过去的数据

response.setHeader("Content-Type","image/jpeg");

// 1.在内存中创建一副图片

BufferedImage image = new BufferedImage(60, 30,

BufferedImage.TYPE_INT_RGB);

// 2.向图片上写数据

Graphics g = image.getGraphics();

// 设背景色

g.setColor(Color.BLACK);

g.fillRect(0, 0, 60, 30);

// 3.设置写入数据的颜色和字体

g.setColor(Color.RED);

g.setFont(new Font(null, Font.BOLD, 20));

// 4.向图片上写数据

String num = makeNum();

//这句话就是把随机生成的数值,保存到session,

//通过session就可以直接去到随即生成的验证码了

request.getSession().setAttribute("checkcode", num);g.drawString(num, 0, 20);

// 5.把写好数据的图片输出给浏览器

ImageIO.write(image,"jpg", response.getOutputStream());

}

//该函数时随机生成7位数字

public String makeNum() {

Random r = new Random();

//9999999 可以生成7位

String num = r.nextInt(9999) + "";

StringBuffer sb = new StringBuffer();

//如果不够4位,前面补零

for (int i = 0; i < 4 - num.length(); i++) {

sb.append("0");

}

num = sb.toString() + num;

return num;

}

public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {

doGet(request, response);

}

}

如何适用

Login.java

<img src=”/验证码的url”/>

练习,请大家把 验证码功能加入到用户管理系统.

6.2.6 JSESSIONID控制session的销毁时间(关掉IE后,再开IE)

对session的销毁时间的讨论—借助一个案例:

面试题: (应用:关掉IE后,再开IE,上次购买的商品还在。->涉及到session销毁时间)

分析

l 我们的session 生命周期如果是30min,该session不会随浏览器的关闭,而自动销毁.而会到30min后,才会被服务器销毁.

l 我们使用代码来实现该功能(session + cookie结合使用)

分析实现的思路:

public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {

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

PrintWriter out = response.getWriter();

HttpSession session = request.getSession();

session.setAttribute("name","张辉胤");

out.println("创一个session并放入姓名属性");

//把该session id保存cookie,在id时,一定要按照规范命名,这里区分大小写

Cookie cookie = new Cookie("JSESSIONID", session.getId());

cookie.setMaxAge(60*30);

response.addCookie(cookie);

}

public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {

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

PrintWriter out = response.getWriter();

HttpSession httpSession = request.getSession();

String name = (String) httpSession.getAttribute("name");

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

}

6.2.7 URL重写 浏览器禁用cookie后使用session的方法

禁用Cookie后Servlet不能共享数据

◆ 解决方案:URL重写

■response.encodeRedirectURL(java.lang.String url)

■用于对sendRedirect方法后的url地址进行重写

■response.encodeURL(java.lang.String url)

■用于对表单action和超链接的url地址进行重写

encodeURL (String url)方法的实现机制为:

● 先判断当前的 Web 组件是否启用 Session,如果没有启用Session,直接返回参数url。

● 再判断客户端浏览器是否支持 Cookie,如果支持Cookie,直接返回参数url;如果不支持Cookie,就在参数url 中加入Session ID 信息,然后返回修改后的url

//购物大厅

request.getSession();

for(Book book:mydb){

String url=response.encodeURL("/myCart/BuyBookCl?id="+book.getId());

out.println(book.getName()+"<a href='"+url+"'>点击购买</a><br/>");

}

//购物车这里我们也需要url地址重写

String url=response.encodeURL("/myCart/ShowBook");

out.println("<a href='"+url+"'>返回购物大厅<a/>");

6.2.8 cookie与session的比较

① 存在的位置

cookie:存在客户端的临时文件夹

session:存在服务器内存中,一个session域对象为一个用户浏览器服务

②  安全性

cookie:是以明文的方式放在客户端的,安全性弱,可以通过(MD5)加密再存放。

session:是存放在服务器内存中,所有安全性好

③  网络传输

cookie:会传递信息给服务器

session的属性值不会给客户端

④  生命周期

cookie的生命周期:是累计时间,即如果我们给cookie设置setMaxAge(30),则30秒后失效。

session的生命周期:是间隔时间,如我们设置session 20min,指在20min内,如果没有访问session,则session失效(session失效是指无法读取session属性),

在以下情况session也会失效

(1)关闭tomcat  (2)reload  web应用  (3)时间到  (4) 调用invalidate方法

⑤ 访问范围

cookie:为多个用户浏览器共享。

session:为一个用户浏览器独享。

⑥ 使用原则

因为session会占用服务器的内存,因此不要向session中存放过多过大的对象,会影响性能。

6.3 过滤器Filter
6.3.1 开发过滤器的步骤

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>

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

package com.hsp.filter;

import java.io.*;

import javax.servlet.*;

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 MyFilter1extends HttpServlet implements Filter {

public void doGet(HttpServletRequest request, HttpServletResponse response)hrows 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

}

}

6.3.2 过滤器链

实现方式 :

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

2. 配置过滤器

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

6.4 简易购物车

简易购物车的实例:

思路:

当用户点击购买商品时,我们把该商品保存到session中,该session的结构是

name val

mybookds    hashMap对象

而hashmap的结构是

key val

书号   书对象.

Book.java类;

具体的实现,参看myCart项目

总节我们使用到的相关知识

(1) java基础的集合 ArrayList HashMap  LinkedHashmap(有序的)

(2) session技术

(3) servlet

(4) 单态

(5) 如何选择不同的集合

list 集合都是有序

map 集合是无序

list和map集合都可以放入null

list可以放入相同的对象,而map也可以放相同对象, 但是key不能重复.

6.5 Servlet上下文ServletContext
6.5.1 为什么需要servletContext

需求1

需求2

u 解决之道—ServletContext

6.5.2 ServletContext原理图

原理图:

u 快速入门

ServletContext

1. ServletContext 是在服务器

2. ServletContext 是被所有客户端共享

3. ServletContext 是当web应用启动的时候,自动创建

4. ServletContext 当web应用关闭/tomcat关闭/对web应用reload会造成servletContext销毁.

6.5.3 ServletContext用法小结

获取:

this.getServletContext();  this.getServletConfig().getServletContext();

添加属性:

servletcontext.setAttribute(string,object);

取出属性

servletcontext.getAttribute(“属性名”)

删除

setvletContext.removeAttribute(“属性名”);

6.5.4 ServletContext的应用

(1) 获取WEB应用的初始化参数

<!-- 如果希望所有的servlet都可以访问该配置. -->

<context-param>

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

<param-value>scott</param-value>

</context-param>

如何获取

String val= this.getServletContext().getInitParameter("name");

(2) 使用ServletContext实现跳转

//目前我们跳转到下一个页面

//1 response.sendRedirect("/web应用名/资源名");

//2 request.getRequestDispatcher("/资源名").forward(request, response);

/*

* 区别1. getRequestDispatcher一个跳转发生在web服务器sendRedirect发生在浏览器

*     2.如果request.setAttribute("name","顺平")希望下一个页面可以使用 属性值,则使用 getRequestDispatcher

*   3.如果session.setAttribute("name2","顺平3"),希望下一个页面可以使用 属性值,则两个方法均可使用,但是建议使用getRequestDispatcher

*    4. 如果我们希望跳转到本web应用外的一个url,应使用sendRedirect

*/

//3.这种方法和2一样

this.getServletContext().getRequestDispatcher("/资源url").forward(request, response);

(3) 读取文件,和获取文件全路径

//首先读取到文件

InputStream inputStream=this.getServletContext().getResourceAsStream("dbinfo.properties");

//创建Properties

Properties pp=new Properties();

pp.load(inputStream);

out.println("name="+pp.getProperty("username"));

*如果文件放在src目录下;则使用类加载器

//如果文件放在src目录下,我们应该使用类加载器来读取

InputStream is=Servlet5.class.getClassLoader().getResourceAsStream("dbinfo.properties")

//获取文件全路径

//如果读取到一个文件的全路径

String path=this.getServletContext().getRealPath("/imgs/Sunset.jpg");

out.println("paht = "+path);

6.5.5 网站计数器的实现

分析 :

代码:

我们建立一个文件recoder.txt文件,用于保存访问量,可以可以保证稳定增长.

实现方法

建立InitServlet ,用于初始化我的Servletcontext,和在关闭tomcat时保存访问量

package com.hsp;

import java.io.*;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class InitServletextends HttpServlet {

/**

* Destruction of the servlet. <br>

*/

public void destroy() {

System.out.println("init servlet destory()被调用..");

//把ServletContext值重新保存到文件.

//从record.txt文件中,读取浏览量

//1.首先得到该文件真实路径

String filePath=this.getServletContext().getRealPath("record.text");

//2.打开文件

try {

FileWriter filewriter=new FileWriter(filePath);

//为了读取我们转为BufferedReader

BufferedWriter bufferedWriter=new BufferedWriter(filewriter);

//从ServletContext读取访问量

String nums=(String) this.getServletContext().getAttribute("nums");

//重新写会文件

bufferedWriter.write(nums);

//一定要关闭流

bufferedWriter.close();

filewriter.close();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}finally{

//关闭...

}

}

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

this.doGet(request, response);

}

public void init()throws ServletException {

// Put your code here

//从record.txt文件中,读取浏览量

//1.首先得到该文件真实路径

String filePath=this.getServletContext().getRealPath("record.text");

//2.打开文件

try {

FileReader fileReader=new FileReader(filePath);

//为了读取我们转为BufferedReader

BufferedReader bufferedReader=new BufferedReader(fileReader);

String nums=bufferedReader.readLine();

//把nums添加到Servletcontext

this.getServletContext().setAttribute("nums", nums);

//一定要关闭流

bufferedReader.close();

fileReader.close();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

当用户登录一次我们取出ServletContext取出,并+1,

//向servletContext中添加属性

//1.先取出

String nums=(String) this.getServletContext().getAttribute("nums");

//如果有,则取出+1

this.getServletContext().setAttribute("nums", (Integer.parseInt(nums)+1)+"");

//在Mange页面显示

String nums=this.getServletContext().getAttribute("nums").toString();

out.println("该管理页面被访问了"+nums+"次");

思考:

问:如果我们的tomcat异常退出,怎么办.

使用线程,定时把ServletContext的值,刷新到recorder.txt比如10min.

第7章 JSP部分

7.1 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是一种动态网页技术.

u 快如入门案例

7.2 jsp的运行原理

n Web服务器是如何调用并执行一个jsp页面的?

看上面的原理图

n  Jsp页面中的html排版标签是如何被发送到客户端的?

out.write("   <table border=1>\r\n");

out.write("   <tr><td>apple</td><td>melon</td><td>orange</td></tr>\r\n");

out.write("    <tr><td>apple</td><td>melon</td><td>orange</td></tr>\r\n");

out.write("     <tr><td>apple</td><td>melon</td><td>orange</td></tr>\r\n");

out.write("      <tr><td>apple</td><td>melon</td><td>orange</td></tr>\r\n");

out.write("   </table>\r\n");

n  Jsp页面中的java代码服务器是如何执行的?

比如jsp是:

<%

int i=90;

int j=i+90;

%>

<h1>测试.</h1>

<%

out.println("j="+j);

%>

当被翻译成jsp后:java文件

public jspService(){

int i=90;

int j=i+90;

}

1. 就是有多个<% %> 其实相当于是一个大的 <% %>

2. 在<% %> 中定义的变量,会成为service函数的局部变量.

n  Web服务器在调用jsp时,会给jsp提供一些什么java对象

供提供了九个: 我们使用了  out对象 --->Servlet的 PrintWriter

说 jsp=html+css+js+java代码+jsp语法(标签)

7.3 jsp的语法
7.3.1 指令元素

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

1. page指令

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

常用的属性:

contentType 和 pageEncoding的区别

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

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

2. include指令

用法:

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

3. taglib指令

<mytag:xx 属性 />

7.3.2 脚本元素

java片段:

<% java 代码 %>

表达式:

<%=表达式 %>

<%

int i=90;

%>

<h1>显示</h1>

<%

out.println("i="+i);

%>

<%=i*78-23 %>

定义变量

<%! int i=90; %>

定义函数

<%! public int getResult(int a,int b){return a+b;}%>

函数不能在

<% %> 定义.

面试题:

7.3.3 动作元素

<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>也可以.

修改jsp的模板:

mvc (m(model模型) v (view视图) c(controller控制器)

mvc 它要求程序员做开发把 数据的输入(使用jsp视图),数据的处理(使用Servlet即 Controller调用model完成.),数据的显示(使用jsp),分开.

iso9001

作业:

改写项目成mvc

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

getParameter

getParameterNames

getParameterValues

servlet 技术详解相关推荐

  1. 深度好文之Servlet技术详解(九)

    目录 一.自启动Servlet 1.自启动Servlet特点 2.通过自启动Servlet实现配置信息的读取 二.Servlet线程安全问题 三.Servlet的url-pattern配置 1.URL ...

  2. 【H.264/AVC视频编解码技术详解】十九:熵编码算法(5)——H.264的CABAC(上):语法元素的二值化方法...

    <H.264/AVC视频编解码技术详解>视频教程已经在"CSDN学院"上线,视频中详述了H.264的背景.标准协议和实现,并通过一个实战工程的形式对H.264的标准进行 ...

  3. Linux磁盘阵列技术详解(二)--raid 1创建

    我在Linux磁盘阵列技术详解(一)里已经详细介绍了几种RAID磁盘阵列方式,原理以及创建raid 0 的详细步骤.那么这篇文档就着重讲解如何创建raid 1的技术: 步骤如下: ① 分区 同样我们还 ...

  4. 《Hadoop技术详解》一导读

    前 言 Hadoop技术详解 本书采用的约定 本书采用以下排版约定. 斜体 用于表明新的术语.URL.电子邮件地址.文件名和文件扩展名. 等宽字体 用于程序清单,正文段落中有关的程序元素,如变量及函数 ...

  5. 科普:5G网络关键技术详解

    不久前,中国华为公司主推的Polar Code(极化码)方案,成为5G控制信道eMBB场景编码方案.消息一出,在网络上就炸开了锅,甚至有媒体用"华为碾压高通,拿下5G时代"来形容这 ...

  6. zookeeper 分布式过程协同技术详解.pdf_阿里大牛耗时18个月整理这份ZooKeeper分布式详解文档...

    前言 摩尔定律揭示了集成电路每18个月计算性能就会增加一倍.随着信息的飞速膨胀,很多应用都无法依赖单个服务器的性能升级来处理如此庞大的数据量,分布式系统和应用越来越受到人们的青睐.分布式系统和应用不仅 ...

  7. Qtum量子链研究院:Plasma技术详解(下篇)

    Plasma的设计模型有两个主要的分支:Plasma MVP(Minimal Viable Plasma,最小可行的Plasma)和Plasma Cash.Plasma MVP的目标是为最基本的可用的 ...

  8. Python数据科学-技术详解与商业实践视频教程

    Python数据科学-技术详解与商业实践(八大案例) 网盘地址:https://pan.baidu.com/s/13QrR_5Er6LgWCWzSb7qOrQ 提取码:s7vw 备用地址(腾讯微云): ...

  9. Java Servlet关键点详解

    Java Servlet关键点详解 1.理解Servlet的生命周期 Servlet引擎控制着Servlet的生命周期 Servlet的生命周期由以下三个方法进行描述(五个生命周期阶段) 1)初始化 ...

  10. 视频直播技术详解(8)直播云 SDK 性能测试模型

    <视频直播技术详解>系列之八:直播云 SDK 性能测试模型 牛小七2016年10月12日发布在 视频直播技术详解 七牛云于 6 月底发布了一个针对视频直播的实时流网络 LiveNet 和完 ...

最新文章

  1. CentOS7 设置用户密码规则
  2. 网站服务器安全维护,网站服务器安全维护
  3. java 的xml_详解Java解析XML的四种方法
  4. 搞懂 SynchronizationContext
  5. oracle备份集注册,OracleRMAN将备份集重新注册到控制文件说明
  6. cf246E. Blood Cousins Return
  7. 惊呼!JavaScript基本数据类型和引用数据类型详解
  8. input内强制保留小数点后两位 位数不足时自动补0
  9. python Image
  10. ajax要不要入口函数,Ajax - SegmentFault 思否
  11. poj 1125 Stockbroker Grapevine 代码及分析
  12. Matlab数学建模(五):优化模型之标准模型
  13. 口布杯花的60种叠法_10种餐巾折花杯花的步骤用文字解说怎么折
  14. 计算机如何切换显卡,Win7系统双显卡怎么切换独立显卡?电脑双显卡切换方法...
  15. 物联网(IoT)行业的决策管理应用
  16. java 空格 separater_Java随手记
  17. python 认证机构_利用Python爬了SIG官网BQB认证公司清单,我有一些重大发现..
  18. unity应用实例——从头撸一个全新的FPS游戏(5)
  19. D3D中2D图片的绘制
  20. 如果你决定离职,请把这五样东西留下,要不然你必身败名裂

热门文章

  1. 浅析Secondary NameNode与namenode
  2. 'System.Data.SqlClient' could not be loaded解决办法
  3. java ssh 框架下 利用junit4 spring-test进行单元测试
  4. 二手青春——代码之路1
  5. ubuntu 修改IP,网关等
  6. SQL Server 版本变更检查
  7. 102 模拟ssh远程执行命令
  8. 066 模块的搜索路径
  9. 剑指offer---数组中重复的数字
  10. Spring静态资源解决方案