📄 11. servlet note.txt
字号:
Servlet环境配置
JAVA_HOME=/XXX/XXX/(JDK路径,bin的上一层目录)
CATALINA_HOME=/XXXX/XXX(tomcat的绝对路径 windows中 X:\xxx\xxx)
Tomcat使用
在启动Tomcat时,是运行Tomcat的bin目录下的startup.sh(windows中使用startup.bat)
Linux中要显示后台的具体信息,则用catalina.sh run 代替startup.sh命令。
判断Tomcat是否启动成功,可以在浏览器的地址栏中使用 http://localhost:8080/ 或 http://127.0.0.1:8080/ 可以访问到tomcat的主页就表示启动成功。
要想停止tomcat服务器,可使用shutdown.sh(windows中使用shutdown.bat),如果直接关闭启动窗口,就会造成8080端口占用错误,这时可以再使用shutdown.sh关闭一下服务器。
Servlet开发步骤
编写servlet源代码,注意servlet的结构。
编译servlet,需要servlet-api.jar文件(位于$Tomcat\common\lib\目录下;加入classpath环境变量中)
部署servlet
编写配置文件web.xml:其中包括servlet burl与 servlet name的映射,
以及servlet name 与 servlet class name的映射。
构造web应用程序目录结构如下:
└─MyWebApp 应用程序名
└─WEB-INF
└─classes
└─lib
└─*.html/*.jsp
配置文件web.xml放在WEB-INF目录下
servlet类文件放在classes目录下
将整个应用程序目录拷贝到 $Tomcat\webapps\ 目录下
使用此结构的优点
一个Web容器中可以共存多个Web应用程序。
Web容器知道该到何处寻找装入Web应用程序所需的类。
web.xml文件的写法
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd version="2.4">
<servlet>
<servlet-name>IpLogServlet</servlet-name>
<servlet-class>tarena.servlet.lc.IpLogServlet</servlet-class>
<init-param>
<param-name>filename</param-name> //getServletConfig().getInitParameter();
<param-value>c:/iplog.txt</param-value>
</init-param>
<load-on-startup>2</ load-on-startup > //启动服务器时就创建该servlet实例,必须是正数,小的数先加载
</servlet>
<servlet-mapping>
<servlet-name>IpLogServlet</servlet-name> //要和servlet标签中的相同
<url-pattern>/lc/iplog</url-pattern> //指定servlet相对于应用目录的虚拟路径
</servlet-mapping> /xxx/xxx(绝对路径),xxx(相对路径)
</web-app>
绝对路径开头的“/”代表 http://localhost:8080/
测试应用
在tomcat服务器中,访问应用下的资源可以在端口号后加上web应用文件夹的名字,就可以看到资源
http://localhost:8080/应用文件夹名/url-pattern
静态页面只能放在web应用的文件夹下,不能够放在WEB-INF文件夹下,WEB-INF文件夹中的资源是受保护的,不能够通过网络访问到。
Servlet的调用过程
用户通过浏览器向web服务器发送请求
http://serverip:port/appname
服务器为用户定位资源
静态资源:/a.html /a/b.html (这里的路径是针对web应用文件夹目录)读文件并把内容发送到客户端。
动态资源:解析web.xml定位Servlet类的名字。
装载类(WEB-INF/classes | WEB-INF/lib/*.jar)
创建该对象的实例
Servlet ser=(Servlet)(Class.forName("servle的类名")).newInstance();
//我们写的Servlet一定要实现Servlet接口或者继承实现了Servlet接口的类
ser.service(request,response);
用Servlet处理表单数据
FORM元素的属性
action: 用来指定要处理FORM数据的Servlet的URL
method: 指定数据传送给HTTP服务器的方法
解析请求
getParameterNames:可以获得一个迭代器Enumeration,通过这个迭代器,来获得form表单中参数的名字。
getParameter: 返回表单中参数名(区分大小写)对应的值(没有这样的参数,返回null; 没有任何值,返回空String);多参数同名时,只取一个。
getParametervalues: 返回表单中参数名(区分大小写)对应的字符串数组(没有这样的参数,返回null;只有一个值,返回值为单一元素组);
get & post
在浏览器的地址栏操作按回车键,或者是热连接,都是get请求,form的method属性如果不指定,默认为get请求(传的数据不能太大,且表现为明文)。
get请求,会将参数显示在浏览器的地址栏上,其显示格式,在地址之后会以?开始,以'&'分隔参数,可以通过HttpServletRequest对象的getQueryString()方法来获得get请求的参数值。
post请求:ServletRequest对象的getInputStream()方法可以获得一个由Socket得来的输入流,可以使用这个流来实现文件的上传。getReader()方法可以直接获取post请求的参数。
Servlet的生命周期
创建Servlet对象,通过服务器反射机制创建Servlet实例,默认第一次请求时才会创建。
调用Servlet对象的init()方法,初始化Servlet的信息,init()方法只会在创建后被调用一次。
响应请求,调用service()或者是doGet(),doPost()方法来处理请求,这些方法是运行的在多线程状态下的。
在长时间没有被调用或者是服务器关闭时,会调用destroy()方法来销毁Servlet对象。
Servlet对客户端提供服务的时序图(插图见Servlet_Note.pdf,P16)
Servlet生命周期状态图(插图见Servlet_Note.pdf,P17)
init方法
当首次创建Servlet时就会调用init方法, 而不是每个用户请求都会调用该方法。
我们可以在init方法中完成类似于构造方法的初始化功能。
init方法一结束,servlet即可接受客户端请求;
init方法实例
覆盖init(ServletConfig conf)方法时,应该总是在首行调用super.init();或者直接覆盖init();
init方法接受ServletConfig作为参数, 用以下方法获得参数值:
getInitParameter: 返回指定参数名称对应的值,如果参数不存在,返回null;
getInitParameterNames: 返回所有初始化参数的名字 ;
service方法
每当服务器接收到对Servlet的请求时,服务器就会产生一个新线程, 并调用service。
service方法检查HTTP请求类型,并相应地调用doGet、doPost、doPut、doDelete。
被container调用去响应(ServletResponse)来自客户端的请求(ServletRequest);
Servlets的多线程安全
多线程占用资源少,处理速度快,提高了效率。
一些编码建议:
对变量和方法定义适当的访问方式, 例如单纯取值操作不会有多线程安全问题;
同步化所有访问重要数据的实例变量; 多线程下,如果操作的是一个变量,且兼有读写操作,
就要考虑加上同步,但同步不能乱加,否则会造成死锁问题。
并发需要注意的
并发的环境:资源处于一个并发的环境
共享资源:多个线程共享一个临界资源
全面同步:如有n个变量访问同一个资源,这n个变量都得同步。即多个锁一把钥匙,钥匙放在一个共享区域内
sychronized(this):粗粒度的锁。是将所有的路都加锁;
sychronized(object o1):细粒度的锁。只对对象中的变量加锁。效率较前面的高,但是较难控制。
读写需要互斥。
sychronized(this):this不能是基本数据类型,必须是Object.不锁对象的引用,而是对象的内存空间。
servlet中需要同步的:成员变量、文件、静态变量、数据库连接
destroy方法
服务器决定删除已经加载的Servlet实例之前将调用Servlet的destroy方法;
该方法允许Servlet:
关闭数据库连接;
中止后台线程;
将Cookie程序清单或访问计数写到磁盘以及执行其他类似的收尾工作。
在Servlet终止时处理Service线程
在destroy()方法中:如有服务(通过一个同步化的实例方法取得当前线程数大于0),则置关闭状态为false(通过一个同步化的实例方法实现)。然后循环等待服务线程数为0,则置关闭状态为true.
在Service()方法中: 如见关闭状态为true,便不执行具体逻辑方法,直接退出。
HTTP servlet类的基本结构
继承HttpServlet
实现至少一个service方法,如:doGet(...)和doPost(...)
service方法有两个参数,HttpServletRequest 和HttpServletResponse:
HttpServletRequest代表经过容器加工的用户的请求
HttpServletResponse代表需要容器进一步加工的对用户的响应
我们写的servlet需要引入javax.servlet.* 和javax.servlet.http.* 两个命名空间
servlet继承关系
servlet主要数据结构:
Servlet 接口:主要定义了servlet的生命周期方法
ServletConfig接口:为servlet提供了使用容器服务的若干重要对象和方法。
ServletContext接口:是Servlet的上下文对象,这个对象是在服务器启动时创建的,为servlet提供了使用容器服务的若干重要方法。
GenericServlet抽象类:为servlet提供了一般的实现(包括实现了servlet和ServletConfig两个接口),保存了容器通过init方法传递给servlet的一个ServletConfig类型的重要对象。
HttpServlet抽象类:为处理http请求的servlet提供了一般实现,主要是定义和实现了若干service方法。
继承关系:GenericServlet继承了Servlet和ServletConfig接口;HttpServlet继承了GenericServlet;
我们写的servlet继承了HttpServlet
Servlet访问DB(一个servlet完成整个功能)
获取client端信息 ---> entity -------v
调用相应的处理方法 ---> controller |
连接数据库 ---> util ------------v
操作信息数据 ---> biz -------> model
返回给client端相应的结果页面 ---> view
将一个servlet按功能细分
将一个完成所有功能的servlet分解成多个,
分别完成自己的功能,即形成了mvc。
MVC框架 (组件的各司其职)
Model,模型层(封装数据 ),这一层一般是进行数据库访问,并且封装对象,这一层中也存放在访问数据库取出信息封装成对象的类,也就是实体类的信息,可以使用JDBC或者Hibernate实现这一层的功能。
Ctrl,控制层(改变数据,改变模型的状态 ),用来相应请求和调用写好的相应的访问数据库的方法,这一层是用来控制请求的响应的,现在我们是使用Servlet来实现这一层,不过一般是会用开源的MVC框架来实现这层,例如struts,或者是Spring的MVC框架。
View,表现层(显示数据和收集数据),收集数据的一般是form表单,不过要保证数据的正确性要是用JavaScript验证信息,以后我们会学到的JSP(java server page)就是用来表现、显示数据的。
Servlet之间的怎么互相调用在上述基础上需要解决servlet之间的调用:可以利用servletContext解决每一个servlet都可能和上下文交互,则每个servlet中都应该保存一个servletContext对象,去访问整个应用的上下文, 步骤如下:
getServletContext()::application
application.getRequestDispatcher(“/res/students/list”)::dis
patcher dispatcher.forward(request,response)
每个JVM中的每一个应用程序里都存在一个上下文
servletContext在servletConfig的对象中;
ServletContext.getRequestDispatcher(String path):返回一个RequestDispatcher
通过RequestDispatcher的forward()或include()方法传送请求。
如何在一个servlet中调用另外一个
servlet:
ServletContext类的getRequestDispatcher(Stringpath)方法获得一个RequestDispatcher对象,并且跳转到指定的Servlet,getRequestDispatcher(String path)方法中的参数就是path,就是指定跳转的Servlet的url-pattern。
RequestDispatcher类的forward(ServletRequestrequest, ServletResponse response) 方法,可以把请求对象转发给其他的Servlet。
在多个servlet中传递信息:
HttpServletRequest对象中的方法
setAttribute(String name,Object o),可以使用HttpServletRequest对象来携带信息,并且可以通过getAttribute(String name)方法来获得携带的信息,这两个方法类似于map中的存取方法,setAttribute方法给数据加上标识,getAttribute方法则是通过这个标识来获取数据,可以使用这一对方法的前提就是要保证是同一个请求对象(HttpServletRequest)
转发请求至新的资源
request dispatcher的二种传送请求方式
Forward: 将请求从一个servlet传到服务器上的其他资源
(servlet、JSP、HTML);
Include: 将静态或动态内容包含在当前servlet中;
获得request dispatcher的二种方式:
ServletRequest.getRequestDispatcher() // 相对路径
ServletContext.getRequestDispatcher() // 绝对路径
Response.sendRedirect(/servapp/state/login); //要写绝对路径,产生新的请求,
Forward(req,resp);//在当前路径基础上跳转
两个页面之间跳转的时侯如果需要数据传递,则只能用
forward();因为sendRedirect()会产生一个新的请求。
servlet中使用数据源访问数据库
在服务器中配置数据源(使用admin管理界面)
再servlet中使用JNDI语法获取数据源
Context context = new InitalContext();
DataSource ds =(DataSource)
context.lookup("java:comp/env/"+dsName);
Connection con = ds.getConnection();
新建一个配置文件myapp.xml(假设web应用程序名称为:myapp),将xml文件的头部和一对<Context>标签写入该文件,将server.xml中有关数据源配置的<Resource>标签内容拷贝到myapp.xml中的<context>标签之间。server.xml位于$tomcat\conf\文件夹下,myapp.xml放在$tomcat\conf\catalina\localhost\文件夹下。
数据源配置Server.xml
<Resource
name="jdbc/oracle" 配置JDNI的名字
type="javax.sql.DataSource" 绑定资源的类型
password=“openlab"
driverClassName="oracle.jdbc.driver.OracleDriver" 驱动名
maxIdle=“1”最大空闲连接数
maxWait="-1"等待时间,配置为-1就是无限等待,直到有空闲连接为止
username=“open123"
url="jdbc:oracle:thin:@192.168.0.39:1521:TARENADB"
maxActive="3" 最大活动连接数/>
会话管理
为什么要使用session?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -