JavaWeb学习笔记(三)------Servlet
Servlet简介
- Servlet就是sun公司开发动态web的一门技术,sun公司在这些API中提供了一个接口,叫做Servlet。
- 如果想要开发一个Servlet程序,只需要完成两个步骤:
- 编写一个类,实现Servlet接口
- 把开发好的java类部署到web服务器中
- 把实现了Servlet接口的Java程序,叫做Servlet
HelloServlet
实现类
- Servlet接口Sun公司有两个默认的实现类:HttpServlet,GenericServlet
- 构建一个普通的Maven项目,删掉里面的src目录,以后的学习在这个项目中建立Module。这个空的工程就是Maven的主工程
关于Maven父子工程的理解
- 在父项目中会有
<modules>
<module>servlet-01</module>
</modules>
- 子项目中会有
<parent>
<artifactId>javaweb-02-servlet</artifactId>
<groupId>com.zmt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
- 父项目中的jar包,子项目可以直接使用,反过来不信
Maven环境优化
- 修改web.xml为最新的
- 将maven的环境搭建完整
编写一个Servlet接口
- 编写一个普通类
- 实现Servlet接口,直接继承HttpServlet
public class HelloServlet extends HttpServlet {
//由于get或者post只是请求实现的不同的方式,可以相互调用,因为业务逻辑都一样
//重写的post方法调用了get方法,所以直接重写get方法即可
//用get调post同理
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//ServletInputStream inputStream = req.getInputStream();
//ServletOutputStream outputStream = resp.getOutputStream();
System.out.println("进入doGet方法");
PrintWriter writer = resp.getWriter(); //响应流
writer.print("Hello,Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
编写Servlet的映射
- 为什么需要映射?
- 因为我们写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需要给他一个浏览器能够访问的路径
- 在web.xml中进行配置
<!--注册Servlet servlet文件对应的名字-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.zmt.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的请求路径,url-pattern:在地址栏请求的网络接口 servlet-name:请求的servlet -->
<!--配置url-pattern,一定要在前面加/,不然会出错 -->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
配置tomcat
- 注意:配置项目发布的路径就可以了
启动测试
- 成功
- 注意:Tomcat下配置的Artifacts文件,要和项目文件名一样,否则产生的war包有问题
Servlet运行原理
- Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:
Mapping问题
- 一个Servlet可以指定一个映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 一个Servlet可以指定多个映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping>
- 一个Servlet可以指定通用映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
- 可以自定义后缀实现请求映射
注意: *前面不能加项目映射的路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.abc</url-pattern>
</servlet-mapping>
- 默认请求路径(尽量不用)
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
优先级问题
- 指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求
ServletContext
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,他代表了当前的web应用:
共享数据
- 我在这个Servlet中保存的数据,可以在另外一个Servlet中拿到
- 存入数据
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//this.getInitParameter(); 初始化参数
//this.getServletConfig(); Servlet配置
//this.getServletContext(); Servlet上下文
ServletContext context = this.getServletContext();
String username = "zmt"; //数据
//将一个数据保存在 ServletContext中,键值对形式,
//名字为:username 值zmt
context.setAttribute("username",username);
System.out.println("Hello");
}
}
- 读出数据
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = (String)context.getAttribute("username");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("名字:"+username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- XML文件
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.zmt.servlet.HelloServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>get</servlet-name>
<servlet-class>com.zmt.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>get</servlet-name>
<url-pattern>/get</url-pattern>
</servlet-mapping>
</web-app>
- 测试访问结果
获取初始化参数
- 在web.xml中进行初始化配置
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 配置一些web应用的初始化参数 -->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
<servlet>
<servlet-name>gp</servlet-name>
<servlet-class>com.zmt.servlet.ServletDemo03</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gp</servlet-name>
<url-pattern>/gp</url-pattern>
</servlet-mapping>
</web-app>
- 获取初始配置
public class ServletDemo03 extends HelloServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
请求转发
- 请求转发,路径不会发生变化
public class ServletDemo04 extends HelloServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
System.out.println("进入Demo04");
//请求转发 /gp为转发的请求路径
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");
//调用forward实现请求转发,转发时,路径不会变
requestDispatcher.forward(req,resp);
// 合并也可以实现 context.getRequestDispatcher("/gp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- XML文件
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- 配置一些web应用的初始化参数 -->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
<servlet>
<servlet-name>gp</servlet-name>
<servlet-class>com.zmt.servlet.ServletDemo03</servlet-class>
</servlet>
<servlet>
<servlet-name>sd4</servlet-name>
<servlet-class>com.zmt.servlet.ServletDemo04</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gp</servlet-name>
<url-pattern>/gp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>sd4</servlet-name>
<url-pattern>/sd4</url-pattern>
</servlet-mapping>
</web-app>
- 本质上A和B产生练习,由B去C处获取信息,所以路径没有发生变化
读取资源文件
- 在java目录下,新建proterties
- 在resources目录下,新建proterties
- 都被打包在同一路径下:target——servlet-02——WEB-INF——classes
- 俗称该路径为:classpath,类路径
- 思路:需要一个文件流
- 在build中配置resources,来防止我们资源导出失败的问题
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
- 具体实现
public class ServletDemo05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ”/“代表当前web项目,即跳转到tomcat文件中webapps中的本项目目录下
// 本项目名为tomcat中Application Context设置值
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(is);
String user = prop.getProperty("username");
String pwd = prop.getProperty("password");
resp.getWriter().print(user+":"+pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- Properties
username = root
password = 123456
- 测试访问结果