Servlet简介
Servlet是sun公司开发的一款动态Web技术
把实现了Servlet接口的java程序叫Servlet
构建Servlet
新建一个Maven项目,删掉里面的src文件夹,这个空的工程就是Maven的主工程
去导入相关的包
放入pom.xml中,有红色报错就刷新
由于是Servlet项目需要建一个Webapp
这里路径每次都需要重新设置的话,可以参考https://blog.csdn.net/tanghuan0827/article/details/107023594
关于Maven父子工程的理解:
在父项目中会有
<modelVersion>4.0.0</modelVersion>
父项目中的JAR包子项目可以直接使用
再新建两个文件夹
Maven环境优化
1.修改web.xml为最新的
2.将maven架构搭建完整
编写一个Servlet程序
新建一个package里面新建java文件
1.编写普通类
2.实现Servlet接口,直接继承httpServlet
以下是他们直接的关系
public class HelloServlet extends HttpServlet {
}
public abstract class HttpServlet extends GenericServlet {
}
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
}
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
//主要方法
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
为什么我们的程序是Servlet程序,因为继承了HttpServlet
HttpServlet
抽象类 继承了GenericServlet
,GenericServlet
实现了Servlet
接口,因此我们自己的类只需要继承HttpServlet
既可以。
Servlet接口包含在GenericServlet中实现了,判断调用了什么类型方法,然后去调用默认实现
最后类的编写为:
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.print("Hello Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
3.编写Servlet的映射
我们写的java程序,需要浏览器访问,浏览器需要连接Web服务器,所以我们需要在Web服务中注册我们写的Servlet,还需要浏览器能够访问的路径
<!--注册Servlet-->
<servlet>
<!--名字和下面的相同就行-->
<servlet-name>Hello</servlet-name>
<!--项目下的类-->
<servlet-class>com.ylc.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<!--Servlet请求路径-->
<servlet-name>Hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
4.配置Tomcat
5.测试tomcat运行成功
6.接下来访问映射的那个请求路径
Servlet实现原理
Serlvet是由Web服务器调用,Web服务器其收到六零看起请求之后会:
Mapping
匹配请求路径
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>.ylc</url-pattern><!--自定义后缀请求路径-->
</servlet-mapping>
*前面不能加任何项目路径
优先级问题:指定了固定路径优先级最高
ServletContext对象
Web容器启动的时候,会为每一个Web程序都创建一个ServletContext对象,代表了当前应用
共享数据
在这个ServletContext保存的数据,在其他servlet可以拿到
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext=this.getServletContext();
String username="ylc";
servletContext.setAttribute("username",username);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext= this.getServletContext();
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
String username=(String) servletContext.getAttribute("username");
resp.getWriter().print("名字:"+username);
}
<servlet>
<servlet-name>GetC</servlet-name>
<servlet-class>GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetC</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>helloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>
运行结果:
请求转发
A想要从C那里拿到东西,但是不能直接连接到C,只能通过B从C那里拿到东西,C给B,B再给A。
这样A和C就不用会面,路径也不需要发生改变,这就是转发的概念
重定向就是A找B要一个资源,B告诉A要去C那里拿,然后B就请求C资源
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
System.out.println("请求转发");
servletContext.getRequestDispatcher("/getc").forward(req,resp);
}
读取资源文件
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("url");
resp.getWriter().print(url);
}
读取资源文件
Properties
username="ylc"
passworld=123
在Java目录和resources中新建Properties都被打包到了同一个目录下:classes,俗称:classpath
需要一个文件流
读取不到资源是因为限定了资源的格式
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
public class ServletText04 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
InputStream resourceAsStream = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties");
Properties properties = new Properties();
properties.load(resourceAsStream);
String user=properties.getProperty("username");
String passworld=properties.getProperty("passworld");
resp.getWriter().print(user+":"+passworld);
}
}
<servlet>
<servlet-name>Pro</servlet-name>
<servlet-class>ServletText04</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Pro</servlet-name>
<url-pattern>/Pro</url-pattern>
</servlet-mapping>
HttpServletRequest
HttpServletResponse
Web服务器接收到客户端的请求,如果要给客户端一些响应的消息用HttpServletResponse
负责向浏览器发送数据的方法
PrintWriter getWriter() throws IOException;
ServletOutputStream getOutputStream() throws IOException;
负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
响应的状态码
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
Response下载图片
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>fileServlet</servlet-name>
<servlet-class>FileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>fileServlet</servlet-name>
<url-pattern>/fileServlet</url-pattern>
</servlet-mapping>
</web-app>
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取要下载文件的路径
String path="E:\\javaweb-servlet\\FileServletText\\src\\resourse\\1.jpg";
//加载的文件名
String filename=path.substring(path.lastIndexOf("\\")+1);
//让浏览器支持下载
resp.setHeader("Content-Disposition","attachment; filename="+ URLEncoder.encode(filename,"UTF-8"));
//获取下载的文件
FileInputStream stream=new FileInputStream(path);
//建立缓冲区
int len=0;
byte[] bytes=new byte[1024];
//获取outputstream 向客户端写入数据
ServletOutputStream outputStream = resp.getOutputStream();
//将fileputputstream写入缓冲区
while ((len=stream.read(bytes))>0)
{
outputStream.write(bytes,0,len);
}
stream.close();
outputStream.close();
}
}
重定向
resp.sendRedirect();
请求转发和重定向的区别:
相同点:页面都会跳转
不同点:
重定向的时候url会发生变化 302
转发的时候url不会发生变化 307