回顾
-
http 协议的定义和组成
- 请求行 请求头 请求体
- 响应行 响应头 响应体
-
常见响应状态码的含义
- 200 - 成功
- 404 - 未找到
- 405 - 方法不支持
- 500 - 服务器出现异常
-
常见请求头
- Host: 主机
- User-Agent: 客户端类型
-
常见响应头
- Content-Type: 资源类型
- Content-Length: 资源大小
-
servlet 继承关系
- Servlet => GenericServlet => HttpServlet
-
如何开发一个 servlet
-
类继承HttpServlet, 重写 doGet 和 doPost 方法
-
配置 servlet
-
web.xml
<servlet> <servelt-name>名</servelt-name> <servlet-class>servlet类的全路径</servlet-class> </servlet> <servlet-mapping> <servelt-name>名</servelt-name> <url-pattern>/资源路径</url-pattern> </servlet-mapping>
-
注解 @WebServlet(urlPatterns="/资源路径")
-
-
访问 http://ip:端口/虚拟目录/资源路径?参数名=值&参数名=值
-
-
servlet 程序的执行流程
-
servlet 程序的生命周期,什么时候会创建? 能否控制?
- init()
- service()
- destroy()
- load-on-startup
-
怎么保证 servlet 的线程安全
- 局部变量
- 共享变量(只读)
- 共享变量加锁
-
servlet 的路径映射有几种
- /精确路径
- /前缀/*
- *.后缀
- /
今日内容
1. 注解方式(*)
要点:掌握 @WebServlet 中的三个属性 urlPatterns,value 和 loadOnStartup
示例代码:
//@WebServlet(urlPatterns = {"/s1","/s2"}) // urlPatterns 取值是一个数组,可以支持多个资源路径
//@WebServlet("/s3") // value 与 urlPatterns 功能完全等价, 好处可以进一步简化资源路径
@WebServlet(loadOnStartup = 1, value="/s3") // loadOnStartup 是在服务器启动时创建和初始化此servlet
public class AnnotationServlet extends HttpServlet {
//static String AppName = "it黑马应用程序";
public AnnotationServlet () {
System.out.println("构造方法");
}
@Override
public void init() throws ServletException {
System.out.println("被初始化");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("执行了 AnnotationServlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2. ServletContext 与 ServletConfig (了解)
- servletContext 上下文,保存所有 servlet 共同的信息
-
- 获取servletContext 对象
-
- getInitParameter 获得初始化参数
-
- getRealPath() 根据一个相对 web 文件夹路径,寻找磁盘此文件的真实路径(*)
-
- setAttribute , getAttribute, removeAttribute 存储 servletContext 的共享数据
- servletContext 内部有一个键值集合 name value
- Attribute 本意是【属性】
- setAttribute(name, value) - 将 name value 放入 servletContext 的键值集合
- getAttribute(name) - 根据 name 返回 value
- removeAttribute(name) 根据 name,删除整个 name 和 value
例1:演示 getInitParameter 获取全局初始化参数
// 演示初始化参数的读取
@WebServlet("/demo1")
public class ServletContextDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取 servletContext
ServletContext servletContext = this.getServletContext();
// 2. 读取 servletContext 的初始化参数
String value = servletContext.getInitParameter("appname");
System.out.println(value);
// 3. 读取另一个参数
System.out.println(servletContext.getInitParameter("appdesc"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
web.xml 中有如下全局参数
<!-- servletContext 所使用的初始化参数 -->
<context-param>
<param-name>appname</param-name>
<param-value>it黑马应用程序</param-value>
</context-param>
<context-param>
<param-name>appdesc</param-name>
<param-value>应用程序描述</param-value>
</context-param>
例2:getRealPath 使用
其中 student.txt 在 web 目录下
@WebServlet("/demo2")
public class ServletContextDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取 servletContext
ServletContext servletContext = this.getServletContext();
// 2. 获取文件的真实路径, / 代表 web 目录的起点
String realPath = servletContext.getRealPath("/student.txt");
System.out.println(realPath);
BufferedReader reader = new BufferedReader(
new FileReader(realPath, Charset.forName("utf-8")));
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
System.out.println(line);
}
reader.close();
}
}
如果编译不过,说明jdk版本低于 11,解决方法:
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(realPath), "utf-8"));
例3:演示 setAttribute 和 getAttribute
@WebServlet("/demo3")
public class ServletContextDemo3 extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("执行文件的读取操作");
try {
// 1. 获取 servletContext
ServletContext servletContext = this.getServletContext();
// 2. 获取文件的真实路径, / 代表 web 目录的起点
String realPath = servletContext.getRealPath("/student.txt");
BufferedReader reader = new BufferedReader(
new FileReader(realPath, Charset.forName("utf-8")));
List<Student> list = new ArrayList<>();
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
System.out.println(line); // 1 zhangsan 18
// 3. 对每行数据进行切分
String[] split = line.split(",");
// 4. 将数据存入 student 对象
Student student = new Student();
student.setId(split[0]);
student.setName(split[1]);
student.setAge(split[2]);
// 5. 将学生对象放入 list
list.add(student);
}
// 6. 将 list 集合数据存入 servletContext
servletContext.setAttribute("students", list);
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 7. 从 ServletContext 中获取 list 数据,后续请求都从内存中获取
ServletContext servletContext = this.getServletContext();
List<Student> students = (List<Student>) servletContext.getAttribute("students");
for (Student student : students) {
System.out.println(student);
}
}
}
例4:演示读取每个servlet的初始化参数
ServletConfig - 代表每个servlet 的配置信息(了解)
- ServletConfig.getInitParameter(“参数名”) 返回参数值,获取是servlet自己配置的参数
- ServletContext.getInitParameter(“参数名”) 返回参数值,获取是全局配置的参数
对于下面的 StudentServlet 要读取其 filename 参数
<servlet>
<servlet-name>stuServlet</servlet-name>
<servlet-class>demo.StudentServlet</servlet-class>
<!-- 每个 servlet 独有的配置信息 -->
<init-param>
<param-name>filename</param-name>
<param-value>student.txt</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>stuServlet</servlet-name>
<url-pattern>/stu</url-pattern>
</servlet-mapping>
最简单的办法是
public class StudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取 servlet 自己独有的配置信息,它内部会间接调用 ServletConfig.getInitParameter()
String value = this.getInitParameter("filename");
System.out.println(value);
}
}
此外,还可以用下面的方法,但不如上面的方便
String value = this.getServletConfig().getInitParameter("filename");
3. 请求(**)
作用:获取浏览器传递过来的数据
-
ServletRequest 父接口
-
HttpServletRequest 子接口
- getContextPath() - 获取虚拟目录 (*)
- getServletPath() - 获取资源路径
- getQueryString() - 获取所有请求参数
- getRequestURI 标识(范围大= 虚拟目录+资源路径)(*)
- getRequestURL 定位 (完整路径)
- getRemoteAddr() 获取浏览器的 ip (*)
- 在tomcat的设置里 VM options 中加入 -Djava.net.preferIPv4Stack=true
获取请求头方法
- getHeader(String name) 获取值 (*)
- connection:keep-alive (长连接)
- connection: close(短连接) 服务器发现取值是close 就会在响应返回后断开连接
- accept-encoding
- getHeaders(String name) 获取多个值
- getHeaderNames() 获取所有的请求头名称
获取请求参数的方法(**)
- getParameter(String name) ==> 根据参数名返回参数值
- getParameterValues(String name) ==> 根据参数名返回参数值的数组(多值)
- getParameterMap() ==> 获取所有请求参数的map集合,key 为参数名,value为参数值数组
封装参数的方式
- 反射的缺点是效率比正常调用低,好处是更通用
- BeanUtils.populate(java对象, request.getParameterMap() )
- 前提:map中 key 要和 java 对象的属性名要一致
- 所有第三方 jar 要放到 WEB-INF/lib 下