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