个人java学习路线-Servlet初入
如何创建运行WebApp
1.创建一个文件夹这里命名为FirstServletWebApp
在FirstServletWebApp下创建WEB-INF文件夹(注意:必须是WEB-INF)和一个html文件,这里命名为welcome.html
2.在WEB-INF下继续创建文件
其中:
classes是用来放java字节码文件的
lib是用来放库的(现在用不到)
web.xml:
一个webapp只有一个web.xml文件
web.xml文件主要配置请求路径和Servlet类名之间的绑定关系
web.xml文件在Tomcat服务器启动阶段被解析
web.xml文件解析失败,会导致webapp启动失败
web.xml文件中的标签不能随意编写,因为Tomcat服务器早就知道该文件中编写了哪些标签
web.xml文件中的标签也是SUN公司制定的Servlet规范
3.随便找个地方创建HelloServlet.java 实现Servlet接口
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
public class HelloServlet implements Servlet{
public void init(ServletConfig config)throws ServletException{
}
public void service(ServletRequest request,ServletResponse response)throws IOException,ServletException{
System.out.println("Hello World!");
}
public void destroy(){
}
public String getServletInfo(){
return null;
}
public ServletConfig getServletConfig(){
return null;
}
}
4.在cmd中输入javac *.java
编译生成字节码文件HelloServlet.class
然后放入到WEB-INF下的classes里
5 . 编写web.xml文件
除了下面这些,其它的在tomcat根目录下conf中,idea或者myeclipse中生成的项目自带的web.xml里应该都有,复制就行
<servlet>
<servlet-name>thisIsServletName</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>thisIsServletName</servlet-name>
<url-pattern>/abc/ss</url-pattern>
<url-pattern>/a</url-pattern>
</servlet-mapping>
填写规范
web.xml中:(?:待填写的意思)
<servlet-class>是字节码文件的名称
<url-pattern>?<url-pattern>
?--->路径随意编写,但必须以"/"开始(?=/a/b)
这个路径是一个虚拟的路径,只是代表一个资源的名称
可以编写多个url-patter,但必须以"/"开始
?不需要带项目名称
xml写完应该是下面
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>thisIsServletName</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>thisIsServletName</servlet-name>
<url-pattern>/abc/ss</url-pattern>
<url-pattern>/a</url-pattern>
</servlet-mapping>
</web-app>
6.写html文件–就是上面一开始创建的welcome.html
<html>
<head>
<title>Welcome page</title>
</head>
<body>
<a href="http://local:9527/FirstServletWebApp/a">HelloServlet</a>
</body>
</html>
到此一个webapp就完成了
接下来就是部署了
7.把FirstServletWebApp文件复制到tomcat根目录\webapps目录下,部署完成
8.到这就可以启动看看效果
启动tomcat根目录\bin\startup.bat
然后打开浏览器输入:http://localhost:9527/FirstServletWebApp/welcome.html
点击HelloServlet,tomcat控制台显示:
到此完成
myeclipse创建第一个webapp
myeclipse第一次用配置啥的会很懵,自己找视频,百度看看,像配置tomcat,部署,创建web工程可能都会有问题,总之问题多多。
myeclipse部署webapp其实就是放在tomcat根目录下\webapps里的
我们可以给工程的 Web Context Root 起别名
可以右键工程选择properties,打开Project Faces 下的Web查看别名
1.
在src下建包firstweb.test1
新建HelloServlet类实现Servlet接口implements Servlet
代码:
package firstweb.test1;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloServlet implements Servlet {
@Override
public void init(ServletConfig config) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {//service:主要写代码的方法,现在不用管其它方法
res.setContentType("text/html;charset=UTF-8"); //设置字符集编码,防止乱码
PrintWriter out=res.getWriter(); //自动行刷新的缓冲字符输出流,可以往网页上写html代码
out.print("<html>");
out.print("<head>");
out.print("<title>hello servlet</title>");
out.print("</head>");
out.print("<body>");
out.print("hello servlet!<br>");
out.print("你好!");
out.print("</body>");
out.print("</html>");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
其中的其它方法后面再说
然后配置xml文件
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>firstweb.test1.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
firstweb.test1.HelloServlet : java文件地址,建议复制过来
3.
新建html文件:
welcome.html
<!DOCTYPE html>
<html>
<head>
<title>welcome.html</title>
</head>
<body>
<a href="/jd/hello">hello</a>
</body>
</html>
配置完成后启动tomcat
打开浏览器输入http://localhost:9527/jd/welcome.html
Servlet连接数据库,查询所有员工信息,在网页上显示一个员工列表[table]
1.新建com.personal.javaweb.servlet包
在包下新建ListEmpServlet类实现Servelt接口
com.personal.javaweb.servlet.ListEmpServlet.java
service代码如下(其它不变)
ps:当然数据库是要导包的,包放在web-inf的lib下
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
res.setContentType("text/html;charset=UTF-8");
PrintWriter out = res.getWriter();
out.print("<html> ");
out.print(" <head> ");
out.print(" <title>员工信息</title> ");
out.print(" </head> ");
out.print(" <h3 align='center'>员工列表</h3> ");
out.print(" <hr width='60%'></hr> ");
out.print(" <body > ");
out.print(" <table border='1' align='center'> ");
out.print(" <tr align='center'> ");
out.print(" <th>序号</th> ");
out.print(" <th>员工编号</th> ");
out.print(" <th>员工姓名</th> ");
out.print(" <th>员工薪水</th> ");
out.print(" </tr> ");
// JDBC
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx", "root", "root");
String sql = "select empno,ename,sal from emp";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
int i = 0;
while (rs.next()) {
String empno = rs.getString("empno");
String ename = rs.getString("ename");
String sal = rs.getString("sal");
out.print(" <tr align='center'> ");
out.print(" <th>" + (++i) + "</th> ");
out.print(" <th>" + empno + "</th> ");
out.print(" <th>" + ename + "</th> ");
out.print(" <th>" + sal + "</th> ");
out.print(" </tr> ");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
out.print(" </table> ");
out.print(" </body> ");
out.print("</html> ");
}
2.配置xml
<servlet>
<servlet-name>listEmp</servlet-name>
<servlet-class>com.personal.javaweb.servlet.ListEmpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>listEmp</servlet-name>
<url-pattern>/system/list</url-pattern>
</servlet-mapping>
新建index.html
ps:这里值得一提的是index类的像index.html,index.jsp都是tomcat已经配置好了的默认欢迎页面,我们在浏览器输入项目名会直接跳转到index.html中,当然我们也可以修改tomcat的配置
<!DOCTYPE html>
<html>
<head>
<title>index page</title>
</head>
<body>
<a href="/oa/system/list">显示员工信息</a>
</body>
</html>
4.启动tomcat,打开浏览器
servlet中方法介绍**
1.关于servlet的生命周期:生命周期表示一个java对象从最初被创建到最终销毁,经历的所有过程
2.Servlet对象的生命周期,javaweb程序员是无权干涉的,包括Servlet对象的相关方法的调用,javaweb程序员也是无权干涉的。
Servlet对象从最初的创建,方法的调用,以及最后对象的销毁,整个过程,是由WEB容器Web Container来管理的。
3.默认情况下,Servlet对象在WEB服务器启动阶段不会被实例化。【特殊设置下可以在web服务器启动阶段实例化Servlet对象】
若希望在web服务器启动阶段实例化Servlet对象,需要在web.xml中进行相关的配置
<load-on-startup>1</load-on-startup> 其中1是优先级,越小优先级越高
4.**描述servlet的生命周期
1)用户在浏览器上输入URL:http://localhost:8080/项目名称/xxx
2)web容器截取请求路径: /项目名称/xxx
3)web容器在容器上下文中找请求路径/项目名称/xxx对应的Servlet对象
4)若没找到对应的Servlet对象
4.1)通过web.xml文件中相关的配置信息,得到请求路径/xxx对应的Servlet完整类名
4.2)通过反射机制,调用Servlet类的无参构造完成Servlet对象的实例化
4.3)web容器调用Servlet对象的init方法完成初始化操作
4.4)web容器调用Servlet对象的service方法提供服务
5)若找到对应的Servlet对象
web容器直接调用Servlet对象的service方法提供服务
6)若web容器关闭的时候/webapp重新部署的时候,该Servlet对象长时间没有用户再次访问的时候,
web容器会将Servlet对象销毁,在销毁对象之前,web容器会调用Servlet对象的destory帆帆,完成销毁之前的准备。
一个对象4)和6)只会有一次,5常发生在刷新访问等情况下。Servlet容器默认采用单例多线程的方式处理多个请求。
5.总之:
Servlet类的构造方法只执行一次
Servlet对象的init方法只执行一次
Servlet对象的service方法,只要用户请求一次,则执行一次
Servlet对象的desctroy方法只执行一次
init方法执行的时候,Servlet对象已经被创建好了。
destroy方法执行的时候,Servlet对象还没有被销毁,即将被销毁。
6.
Servlet对象是单例,但是不符合单列模式,只能称为伪单例,真单例的构造方法是私有化的。
Tomcat服务器支持多线程的,所以Servlet对象在单实例多线程环境下运行。
那么Servlet对象中若有实例变量,并且实例变量涉及到修改操作,那么这个Servlet对象一定会存在线程安全问题,
不建议在Servlet对象中使用实例变量,尽量使用局部变量。
7.
Servlet对象实例化后,大多数的WEB容器都是将该Servlet对象以及对应的url-pattern储存到MAP集合中了
Map<String,Servlet>集合
key value
------------------
/login LoginServlet对象引用
/delete DeleteServlet对象引用
/save SaveServlet对象引用
8.
服务器在启动的时候就会解析各个webapp的web.xml文件,做了什么?
将web.xml文件中的url-pattern对应的Servlet完整类名储存到Map集合中了;对应4的3>
Map<String,Servlet>集合
key value
------------------
/login com.personal.javaweb.servlet.LoginServlet
/delete com.personal.javaweb.servlet.DeleteServlet
...
9.
init,destory方法个人感觉和javase中垃圾回收器中finalize()差不多(对象被回收前执行一次),init
init()在对象创建后执行,destory()在对象销毁前创建
ServletConfig接口
实现Servlet接口后,重写的5个方法中有这样两个
@Override
public void init(ServletConfig config) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
这里我们看看ServletConfig接口
Apache Tomcat服务器实现了Servlet规范,Tomcat服务器专门写了一个ServletConfig接口的实现类。
完整类名为:org.apache.catalina.core.StandardWrapperFacade
我们在编程的时候,一直是面向ServletConfig接口去完成调用,不需要关心具体的实现类。
Tomcat服务器是一个实现了Servlet规范和JSP规范的容器。
接口中常用的方法:
- public String getInitParameter(String name); :通过初始化参数的name获取value
- public Enumeration<String> getInitParameterNames(); :获取所有初始化参数的name
- public String getServletName(); :获取<servlet-name>servletname</servlet-name>
- public ServletContext getServletContext(); :获取ServletContext():获取ServletContext[Servlet上下文]对象
ServletConfig到底是什么?
- ServletConfig是一个Servlet对象的配置信息对象,ServletConfig对象中封装了一个Servlet对象的配置信息。
Servlet对象的配置信息到web.xml文件中
- 一个Servlet对象对应一个ServletConfig对象,100个Servlet对象对应100个ServletConfig对象
将init方法上的ServletConfig参数移动到service方法中,因为我们程序员主要填写的方法是service方法,在service方法中我们可能需要ServletConfig!!!
- 在init方法中完成:局部变量config赋值给实例变量config
- 实现getServletConfig方法,提供公开的get方法目的是供子类使用
我们稍改造一下实现了Servlet接口的AServlet
private ServletConfig config;
@Override
public void init(ServletConfig config) throws ServletException {
//System.out.println("AServlet's ServletConfig="+config.toString());
this.config=config;//这样做在Service方法中也可以使用config
}
//这个方法是供子类使用的,在子类中若想获取ServletConfig,可以调用这个方法
@Override
public ServletConfig getServletConfig() {
return config;
}
1.先看看 public String getInitParameter(String name);
– 我们现在web.xml中做如下配置
<servlet>
<servlet-name>a</servlet-name>
<servlet-class>com.personal.javaweb.AServlet</servlet-class>
<!-- 初始化参数:被封转到ServletConfig对象中了 -->
<init-param>
<param-name>driver</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/xxx</param-value>
</init-param>
<init-param>
<param-name>user</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>root</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>a</servlet-name>
<url-pattern>/a</url-pattern>
</servlet-mapping>
那么我们在com.personal.javaweb.AServlet中的service方法中写入下面代码即可获得对应的值
String driver =config.getInitParameter("driver");
String url =config.getInitParameter("url");
String user =config.getInitParameter("user");
String password =config.getInitParameter("password");
2.public Enumeration getInitParameterNames();
Enumeration<String> names=config.getInitParameterNames();
while(names.hasMoreElements()) {
String name=names.nextElement();
String value=config.getInitParameter(name);
out.print(name+"="+value);
out.print("<br>");
}
3 . public String getServletName();
这里得到的就是a
String servletName=config.getServletName();
out.print("<servlet-name>"+servletName+"</servlet-name>");
4.public ServletContext getServletContext(); :获取ServletContext():获取ServletContext[Servlet上下文]对象
ServletContext application=config.getServletContext();
out.print(application.toString());
ServletContext接口,Servlet规范
1.ServletContext到底是什么?什么时候被创建和销毁?
ServletContext也是接口
- ServletContext被翻译为:Servlet上下文[Context一般都翻译为上下文]
- 一个webapp只有一个web.xml文件,web.xml文件在服务器启动阶段被解析
- 一个webapp只有一个ServletContext对象,ServletContext在服务器启动阶段被实例化
- ServletContext在服务器关闭的时候会被销毁
- ServletContext对应的是web.xml文件,是该文件的代表
- ServletContext是所有Servlet对象四周环境的代表【在每一个webapp中,所有的Servlet对象共享同一个”四周环境对象“,该对象就是ServletContext】
- 所有用户若想共享同一个数据,该数据可以放到ServletContext对象
- 一般放到ServletContext对象中的数据是不建议涉及到修改操作的,因为ServletContext是多线程共享的一个对象,修改时会存在线程安全问题
2.ServletContext接口中有哪些常用方法?
- void setAttribute(String name,Object object) :向ServletContext范围中添加数据
- Object getAttribute(String name) :从ServletContext范围中获取数据
- void removeAttribute(String name) :移除ServletContext范围中的数据
//这三个类似map集合map.put(key,value),Object value=map.get(key),map.remove(key)
- String getInitParameter(String name)
- Enumeration getInitParameterNames()
- String getRealPath(String path)
-
3.Servlet ,ServletConfig,ServletContext之间的关系?
- 一个Servlet对应一个ServletConfig,100个Servlet对应100个ServletConfig
- 所有的Servlet共享一个ServletContext对象
4.ServletContext范围可以完成跨用户传递数据。
欢迎页面
前面说过index.html是默认欢迎页面,我们自然可以自己手动设置
ps:tomcat中的设置的是所有项目的默认欢迎页面,默认欢迎页面也是就近原则,自己设置的优先级肯定高于tomcat的
全局配置:CATALINA_HOME/conf/web.xml
局部配置;CATALINA_HOME/webapps/webapp/WEB-INF/web.xml
在web.xml中做如下设置
<welcome-file-list>
<welcome-file>system/welcome</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>welcome</servlet-name>
<servlet-class>com.personal.javaweb.servlet.WelcomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>welcome</servlet-name>
<url-pattern>/system/welcome</url-pattern>
</servlet-mapping>
浏览器输入http://localhost:9527/prj-servlet-06/
默认打开的就是http://localhost:9527/prj-servlet-06/system/welcome
欢迎页面可以设置多个,越靠上面优先级越高,当然servelt,html,jsp等都可以设置为欢迎页面
网页错误error
程序难免出错(日常404),出错了显示的奇奇怪怪别人看不懂,这时就需要设置错误页面了,出现错误时自动跳转到错误页面
在xml中配置
<error-page>
<error-code>404</error-code>
<location>/error/error.html</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error/error.html</location>
</error-page>
这样出现404和500错误时就会自动跳转到/error/error.html了
这里:
在webapp中常见的错误代码:
- 404 - Not Found【资源未找到,可能是请求的资源路径写错了】
- 500 - Servlet Inner Error【服务器内部错误,这种情况一般都是java程序出现异常】
404和500都是HTTP协议状态码