Servlet
简介
为什么需要Servlet?
//TODO
因为html文件无法直接和dao-jdbc交互
狭义上:servlet指javax.servlet.Servlet接口及其子接口
广义上:指实现了Servlet接口的实现类
对象由Servlet容器创建。
一般使用:
自己新建一个类集成 javax.servlet.http.HttpServlet,实现doGet、doPost 或 service方法
通过 request 对象获取客户端的请求数据
request.getParameter()
通过 response 对象给客户端返回响应
response.getWriter().writer();
通过注解 @WebServlet设置servlet对应的请求路径
乱码问题解决
客户端的请求数据乱码
request.setCharacterEncoding("UTF-8");
服务器的响应数据乱码
response.setContentType("text/plain;charset=UTF-8");
text/plain是数据的MIMEType
输出流
不要把拿到的输出流关闭了,因为不是自己创建的。
具体细节
注册是因为可以通过反射来创建对象
- 加载类全路径
- url映射
servlet的路径默认在WebContent下,所以注册了之后,这里这样写就可以了:
多个路径
@WebServlet({"/test1", "/test2"})
public class TestServlet extends HttpServlet {
public TestServlet() {
System.out.println(this + "_构造方法");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) {
System.out.println(this + "_service");
}
}
尽管是两个请求路径,但它们会共用一个servlet。
但是Servlet并没有被设计成单例模式。但是一般情况下,服务器只会创建一个实例对象,因为它觉得没必要。
建议:不要再Servlet中定义可写可改变的成员变量,会引发线程安全问题。
如下:
@WebServlet({"/test1", "/test2"})
public class TestServlet extends HttpServlet {
private int age = 10;
public TestServlet() {
System.out.println(this + "_构造方法");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) {
System.out.println(this + "_service123" + age);
}
}
Servlet生命周期
构造器:
- 执行次数:在整个生命周期中执行一次
- 执行时机:第一次接收请求时执行
init():初始化 - 执行次数:在整个生命周期中执行一次
- 执行时机:第一次接收请求时执行
service() - 执行次数:在整个生命周期中执行多次
- 执行时机:每次接收请求时执行
destroy() - 执行次数:在整个生命周期中执行一次
- 执行时机:关闭服务器时执行
ServletConfig与ServletContext
ServletConfig
定义:代表了Servlet的配置对象
作用:
- 获取Servlet初始化参数
- 获取ServletContext对象
- 获取Servlet名称
ServletContext
定义:代表了Servlet的上下文对象,什么是上下文对象?
作用:
- 获取初始化参数(当前Servlet上下文)
- 获取真实路径
- 域对象
转发与重定向
那么其实纯Servlet和纯Jsp都是比较麻烦的做法。我们可以混合使用它们。想达到的效果是Servlet中没有HTML代码,JSP中没有Java代码
------------恢复内容结束------------
------------恢复内容开始------------
简介
为什么需要Servlet?
//TODO
因为html文件无法直接和dao-jdbc交互
狭义上:servlet指javax.servlet.Servlet接口及其子接口
广义上:指实现了Servlet接口的实现类
对象由Servlet容器创建。
一般使用:
自己新建一个类集成 javax.servlet.http.HttpServlet,实现doGet、doPost 或 service方法
通过 request 对象获取客户端的请求数据
request.getParameter()
通过 response 对象给客户端返回响应
response.getWriter().writer();
通过注解 @WebServlet设置servlet对应的请求路径
乱码问题解决
客户端的请求数据乱码
request.setCharacterEncoding("UTF-8");
服务器的响应数据乱码
response.setContentType("text/plain;charset=UTF-8");
text/plain是数据的MIMEType
输出流
不要把拿到的输出流关闭了,因为不是自己创建的。
具体细节
注册是因为可以通过反射来创建对象
- 加载类全路径
- url映射
servlet的路径默认在WebContent下,所以注册了之后,这里这样写就可以了:
多个路径
@WebServlet({"/test1", "/test2"})
public class TestServlet extends HttpServlet {
public TestServlet() {
System.out.println(this + "_构造方法");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) {
System.out.println(this + "_service");
}
}
尽管是两个请求路径,但它们会共用一个servlet。
但是Servlet并没有被设计成单例模式。但是一般情况下,服务器只会创建一个实例对象,因为它觉得没必要。
建议:不要再Servlet中定义可写可改变的成员变量,会引发线程安全问题。
如下:
@WebServlet({"/test1", "/test2"})
public class TestServlet extends HttpServlet {
private int age = 10;
public TestServlet() {
System.out.println(this + "_构造方法");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) {
System.out.println(this + "_service123" + age);
}
}
Servlet生命周期
构造器:
- 执行次数:在整个生命周期中执行一次
- 执行时机:第一次接收请求时执行
init():初始化 - 执行次数:在整个生命周期中执行一次
- 执行时机:第一次接收请求时执行
service() - 执行次数:在整个生命周期中执行多次
- 执行时机:每次接收请求时执行
destroy() - 执行次数:在整个生命周期中执行一次
- 执行时机:关闭服务器时执行
ServletConfig与ServletContext
ServletConfig
定义:代表了Servlet的配置对象
作用:
- 获取Servlet初始化参数
- 获取ServletContext对象
- 获取Servlet名称
ServletContext
定义:代表了Servlet的上下文对象,什么是上下文对象?
作用:
- 获取初始化参数(当前Servlet上下文)
- 获取真实路径
- 域对象
转发与重定向
那么其实纯Servlet和纯Jsp都是比较麻烦的做法。我们可以混合使用它们。想达到的效果是Servlet中没有HTML代码,JSP中没有Java代码。
那么想要Servlet中没有HTML代码,我们可以让Servlet转发到JSP,而JSP中不想要Java代码,我们可以使用EL表达式和JSTL标签库来简化JSP代码
最后就形成了MVC开发模式。
转发只能在同一个 context中转发
同一个context也就是同一个项目中。
像上面这种两次请求之间怎么共享数据以后再说。先说同一个请求转发多次之间的数据共享。
重定向的路径得是完整的,因为是告诉客户端一个新的请求的地址