Servlet通常指的就是实现Servlet接口的java类,通过对http请求进行处理并响应结果,用以开发动态web。
Servlet
是sun公司开发动态web的一门技术
。实现了Servlet接口
的Java程序叫做Servlet。HttpServlet
和GenericServlet
HttpServlet
类即可。public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ServletOutputStream outputStream = resp.getOutputStream();
PrintWriter writer = resp.getWriter(); // 响应流
writer.println("Hello,Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
用户在上网时,由客户端浏览器发送http请求
至服务器,服务器根据用户请求方式及地址从磁盘中加载对应的Servlet程序文件
到Servlet容器。服务器解析http请求为request对象
,转发request对象到相应Servlet中
进行处理,Servlet处理后返回response对象
,服务器再将response对象转为http响应
,响应给客户端浏览器。
要通过浏览器访问java程序,而浏览器需要连接web服务器,所以需要在web服务中注册Servlet,还要给它一个浏览器能够访问的路径。
@WebServlet注解
// test只是个名字而已,value为访问地址
@WebServlet(name = "test", value = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ServletOutputStream outputStream = resp.getOutputStream();
PrintWriter writer = resp.getWriter(); // 响应流
writer.println("Hello,Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
web.xml
<web-app>
<servlet>
<servlet-name>SpenceServletservlet-name>
<servlet-class>com.spence.HelloServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>SpenceServletservlet-name>
<url-pattern>/spenceurl-pattern>
servlet-mapping>
web-app>
注意:
标签与
标签一一对应,且
。
ServletContext是上下文对象,用于管理整个web应用
web容器在启动时,会为每个web程序(每个Service)都创建一个对应的ServletContext对象,它代表当前web应用
。但要注意,每个web程序(Servlet类)中创建的ServletContext对象其实是同一个对象
,因此可通过ServletContext对象使得各个Servlet类中的数据互通共享(ServletContext对象凌驾于所有Servlet类之上,它是由web容器(服务器)创建的
)。
向ServletContext对象中存入数据
public class SetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String userName = "哥哥";
// 将一个数据以键值对形式保存在了 servletContext 中
servletContext.setAttribute("userName", userName);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
从ServletContext对象中取出对象
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String userName = (String) servletContext.getAttribute("userName");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
PrintWriter writer = resp.getWriter();
writer.println(userName);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
可在web.xml配置文件中写入一些初始化参数
<web-app>
...
<context-param>
<param-name>jdbc_urlparam-name>
<param-value>jdbc:mysql://localhost:3306/mybatisparam-value>
context-param>
...
web-app>web-app>
通过ServletContext对象中getInitParameter方法读取初始化参数
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("jdbc_url"); // 读入初始化参数
PrintWriter writer = resp.getWriter();
writer.println(url);
}
通过ServletContext对象中getRequestDispatcher方法写入转发请求路径,再通过RequestDispatcher对象的forward方法实现转发。相当于指明一个新的请求路径,把请求和响应参数传入到新的请求中(该种情况不同于重定向,不会改变浏览器页中URL地址)。
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/jdbc"); // 转发的请求路径
requestDispatcher.forward(req, resp); // 调用forward实现转发
}
想办法搞出一个文件流即可。
发现:都被打包到了同一个路径下—> class,我们俗称这个路径为classpath。
在resources目录下新建 db.properties 文件
username=root
password=123456
通过ServletContext对象中 getResourceAsStream 方法读取文件
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
// 通过 getResourceAsStream 方法读取文件 /WEB-INF/classes/db.properties 为打包后文件所在相对路径
InputStream iStream = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties"); // File流为绝对路径,在线上不方便使用
Properties prop = new Properties();
prop.load(iStream);
// 获取配置文件中信息
String username = prop.getProperty("username");
String password = prop.getProperty("password");
PrintWriter writer = resp.getWriter();
writer.println(username +":"+ password);
}
web服务器收到客户端http请求后,针对该请求分别创建一个代表请求的HttpServletRequest对象,和一个代表响应的HttpServletResponse对象
。
负责向浏览器发送数据的方法:
// 平常的流
ServletOutputStream getOutputStream() throws IOException;
// 字符
PrintWriter getWriter() throws IOException;
负责向浏览器发送一些响应头的方法
// 设置响应的编码
void setCharacterEncoding(String var1);
// 设置响应字符串长度
void setContentLength(int var1);
// 设置流长度
void setContentLengthLong(long var1);
// 设置类型
void setContentType(String var1);
...
getOutputStream、getWriter等
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 让浏览器3秒自动刷新一次
resp.setHeader("refresh", "3");
// 在内存中创建一个图片
BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_BGR);
// 得到图片
Graphics2D g = (Graphics2D)image.getGraphics(); // 画笔
// 设置画笔颜色
g.setColor(Color.PINK);
// 给图片填充数据
g.fillRect(0, 0, 80, 20);
// 给图片写入数据
g.setColor(Color.BLUE);
g.setFont(new Font(null, Font.BOLD, 20));
g.drawString(makeNum(), 0, 20);
// 告诉浏览器,这个请求用图片的方式打开
resp.setContentType("image/jpeg");
// 不让浏览器缓存
resp.setDateHeader("expires", -1);
resp.setHeader("Cache-Control", "no-cache");
resp.setHeader("Pragma", "no-cache");
// 把图片写给浏览器
ImageIO.write(image, "jpg", resp.getOutputStream());
}
// 生成随机数
private String makeNum(){
Random random = new Random();
String num = random.nextInt(9999999) + "";
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 7-num.length(); i++) {
sb.append("0");
}
return sb.toString()+num;
}
1. 获取要下载文件的路径
2. 下载的文件名
3. 让浏览器能够支持所需下载的东西
4. 创建下载文件的输入流
5. 创建缓冲区
6. 获取OutputStream对象
7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取要下载文件的路径
// String realPath = this.getServletContext().getRealPath("/pic_01.png");
String realPath = "D:\\IDEA_WorkSpace\\my-demo\\maven-03-web\\web-03-test\\src\\main\\resources\\static\\img\\pic_01.png";
// 2. 下载的文件名
String fileName = realPath.substring(realPath.lastIndexOf("//") + 1);
// 3. 让浏览器能够支持所需下载的东西
// resp.setHeader("content-disposition", "attachment;fileName"+fileName);
// 中文文件名用 URLEncoder.encode 编码,否则有可能乱码
resp.setHeader("content-disposition", "attachment;filename="+ URLEncoder.encode(fileName, "utf-8"));
// 4. 创建下载文件的输入流
FileInputStream fileInputStream = new FileInputStream(realPath);
// 5. 创建缓冲区
int len = 0;
byte[] buffer = new byte[1024];
// 6. 获取OutputStream对象
ServletOutputStream outputStream = resp.getOutputStream();
// 7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端
while ((len = fileInputStream.read(buffer))>0){
outputStream.write(buffer,0 , len);
}
fileInputStream.close();
outputStream.close();
}
一个web资源收到客户端请求后,他会通知客户端去访问另外一个web资源,这个过程叫重定向(该过程不同于转发,客户端浏览器中URL会发生改变)。
常见场景
:用户登录
重定向方法
:void sendRedirect(String var1) throws IOException;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 重定向
resp.sendRedirect("/test3/image");
/**
* resp.sendRedirect("/test3/image");
* 等价于
* resp.setHeader("Location", "/test3/image");
* resp.setStatus(302);
*/
}
HttpServletRequest代表客户端请求,用户通过Http协议访问服务器,Http请求中的所有信息会被封装到HttpServletRequest
,通过这个HttpServletRequest的方法,获得客户端的所有信息。
请求转发
String getParameter(String var1);
String[] getParameterValues(String var1);
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbies = req.getParameterValues("hobbies");
// 这里的 / 代表当前的web应用
req.getRequestDispatcher("/success.jsp").forward(req, resp);
}