Java之Servlet
2021/7/26 9:05:54
本文主要是介绍Java之Servlet,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Servlet
sun公司基于java开发动态web的一门技术
其中在这些API中提供了一个接口就是Servlet
servlet有两个实现类,HttpServlet、GenericServlet,其中GenericServlet是HttpServlet的父类
在servlet3.0版本后可以不用写web.xml文件,可以直接使用注解定义加载。
我们直接在类上面加入注解
@WebServlet(urlPatterns = "/demo")
HelloServlet
-
新建一个普通项目,不要勾选maven中webapp模版,并删掉项目中的src目录,这个空工程就是Maven父工程
-
在pom.xml中导入依赖
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.3</version> </dependency>
如果导入失败,手动下载jar包放在本地仓库中
-
创建子modul,勾选webapp模版
-
子项目中pom.xml添加
<parent>
标签关于Maven父子工程:
在父工程的
pom.xml
中会多出<modules> <module>servlet01</module> </modules>
在子工程的
pom.xml
中会多出(Maven3.6.0之后一开始会有,项目加载完后会被自动清除掉,自己手动添加即可)<parent> <artifactId>javaweb01</artifactId> <groupId>com.zh1z3ven</groupId> <version>1.0-SNAPSHOT</version> </parent>
父项目中的jar包,子项目可以直接使用
-
修改子项目中的
web.xml
<?xml version="1.0" encoding="UTF-8" ?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0" metadata-complete="true"> </web-app>
-
子项目中新建
java
和resources
目录,并修改对应目录属性 -
新建com.zh1z3ven.servlet包,编写servlet程序
写一个普通类,实现servlet接口
这里需要注意父项目的pom.xml文件中的
<scope>
标签,注意如果父项目存在<scope>
标签且值为provided
时,子modul无法成功引用父类jar包在Maven中依赖的域有:compile、provided、runtime、system、test、import
一、compile(默认)
当依赖的scope为compile的时候,那么当前这个依赖的包,会在编译的时候被加入进来,并且在打包(mvn package)的时候也会被加入进来。
编译范围有效,在编译与打包时都会加入进去。二、provided
当依赖的scope为provided的时候,在编译和测试的时候有效,在执行(mvn package)进行打包时不会加入。比如, 我们开发一个web应用,在编译时我们需要依赖servlet-api.jar,但是在运行时我们不需要该 jar包,因为这个jar 包已由web服务器提供,如果在打包时又被加入进去,那么就可能产生冲突。此时我们就可以使用 provided 进行范围修饰。
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class HelloServlet extends HttpServlet { //由于get和post只是请求相互实现的方式,可以互相调用,业务逻辑都一样 @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 { doGet(req,resp); } }
-
修改
web.xml
注册servlet,编写servlet映射<!-- 注册servlet--> <servlet> <servlet-name>hello</servlet-name> <!-- 绑定servlet实现类--> <servlet-class>com.zh1z3ven.servlet.HelloServlet</servlet-class> </servlet> <!-- 注册servlet路由--> <servlet-mapping> <servlet-name>hello</servlet-name> <!-- 设置访问路由--> <url-pattern>/hello</url-pattern> </servlet-mapping>
-
配置Tomcat,配置完后先点击
apply
再点击ok
-
启动测试
-
关于target目录
Servlet原理
客户端请求通过浏览器发送到web服务器,请求包含请求头请求体,之后变成request对象传给servlet,servlet调用service方法处理请求并返回response。而对于Servlet来说,当服务器处理请求时,先根据URL中的路径查找是否在web.xml的<servlet-mapping>
(servlet映射)<url-pattern>
标签有对应的值,有的话根据此Servlet对应的类名,通过该类的实例化对象调用service方法处理请求并返回响应。
Servlet-Mapping
-
一个servlet可以指定一个映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
-
一个servlet可以指定多个映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello1</url-pattern> </servlet-mapping>
-
一个servlet可以指定通用映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping>
-
指定一些后缀或前缀等...,例如.do
以这个后缀结尾,不管前面uri加了多少层目录都可以访问到
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
-
默认请求路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
处理简单报错Servlet
ErrorServelt
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class ErrorServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); PrintWriter writer = resp.getWriter(); writer.print("<h1>404</h1>"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
Web.xml中添加,这里<url-pattern>/*</url-pattern>
虽然设置的默认通配符,但是url输入其他注册好的servlet还是会优先走对应的servlet。指定了固定路径的映射默认优先级最高,如果找不到才会走默认的处理请求。
<servlet> <servlet-name>error</servlet-name> <servlet-class>com.zh1z3ven.servlet.ErrorServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>error</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
ServletContext
Web容器在启动的时候会为每个Web程序创建一个ServletContext对象,代表当前的Web应用对象。这个ServletContext可以保存一些数据,也可以供Servlet从中读取数据。类似于Servlet之间的中介,实现Servlet直接的数据共享。
ServletContext:Servlet上下文
可根据HttpServlet的实例化对象调用getServletContext获取
ServletContext servletContext = this.getServletContext();
1、共享数据
在一个servlet中创建的数据可以在另一个servlet中拿到。ServletContext对象是可以被多个Servlet共用的
写入数据
servletContext.setAttribute("username",username); //将数据写入ServletContext中
public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("Hello Servlet doGet"); //this.getInitParameter() 初始化参数 //this.getServletConfig() sevlet配置 //this.getServletContext() sevlet上下文 //获得ServletContext对象 ServletContext servletContext = this.getServletContext(); //this指代当前这个类本身 String username = "zh1z3ven"; servletContext.setAttribute("username",username); //将数据写入ServletContext中 } }
读取数据
public class GetServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("Hello GetServlet "); ServletContext servletContext = this.getServletContext(); String username = (String) servletContext.getAttribute("username"); //强制类型转换 PrintWriter writer = resp.getWriter(); writer.print("<h1>username: </h1>" + username); } }
Web.xml
<servlet> <servlet-name>hello</servlet-name> <servlet-class>com.zh1z3ven.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <servlet> <servlet-name>getname</servlet-name> <servlet-class>com.zh1z3ven.servlet.GetServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>getname</servlet-name> <url-pattern>/getname</url-pattern> </servlet-mapping>
测试结果
需要先访问/s2/hello,才会触发HelloServlet类中的doGet方法将name写入ServletContext中;再访问/s2/getname时触发GetServlet中的doGet方法去读取ServletContext中的name并根据代码回显到页面上。
2、获取初始化参数getInitParameter
参数为web.xml中的<context-param>
下的参数
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this.getServletContext(); String url = servletContext.getInitParameter("url"); resp.setCharacterEncoding("utf-8"); resp.setContentType("text/html"); PrintWriter writer = resp.getWriter(); writer.print(url); }
Web.xml
<context-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/mybatis</param-value> </context-param> <servlet> <servlet-name>gp</servlet-name> <servlet-class>com.zh1z3ven.servlet.ServletDemo03</servlet-class> </servlet> <servlet-mapping> <servlet-name>gp</servlet-name> <url-pattern>/gp</url-pattern> </servlet-mapping>
3、请求转发requestDispatcher
获取ServletContext上下文对象,调用requestDispatcher的forward方法转发请求
RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/gp"); //请求转发目标路径 requestDispatcher.forward(req,resp); //调用forward方法转发请求
Web.xml
<servlet> <servlet-name>sd4</servlet-name> <servlet-class>com.zh1z3ven.servlet.ServletDemo04</servlet-class> </servlet> <servlet-mapping> <servlet-name>sd4</servlet-name> <url-pattern>/sd4</url-pattern> </servlet-mapping>
class
public class ServletDemo04 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = this.getServletContext(); //RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/gp"); //请求转发目标路径 //requestDispatcher.forward(req,resp); //调用forward方法转发请求 servletContext.getRequestDispatcher("/gp").forward(req,resp); } }
如果出现tomcat爆500的情况,可以尝试关掉tomcat然后maven clean一下项目的target,在重启tomcat可能就好了
4、读取资源文件
Properties,如果在项目的java目录下有写properties文件的话默认是不会被导出的,需要在pom.xml中多加一段build的配置,使得java目录下的资源文件也可以被导出。
但是不管是resources和java目录下的properties文件都会被打报道WEB-INF/classes目录下,也就是classpath路径
思路:利用this.getServletContext().getResourceAsStream()
方法返回一个流,通过Properties
类的实例化对象调用load()
方法加载这个流获取数据。
public class PropertiesServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/zh1z3ven/servlet/test.properties"); //返回InputStream流 Properties properties = new Properties(); //实例化Properties对象 properties.load(is); //loadInputStream流 String username = properties.getProperty("username"); String password = properties.getProperty("password"); resp.getWriter().print(username + ":" + password); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } }
Web.xml
<servlet> <servlet-name>sd5</servlet-name> <servlet-class>com.zh1z3ven.servlet.PropertiesServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>sd5</servlet-name> <url-pattern>/sd5</url-pattern> </servlet-mapping>
资源文件路径,同理如果是在源码目录下,只需要写好相对路径即可。
例如:此test.properties
路径为:
/WEB-INF/classes/com/zh1z3ven/servlet/test.properties
HttpServletResponse
web服务器会将客户端发来的http请求进行处理,生成两个对象HttpServletRequest和HttpServletResponse。
- 如果要获取客户端发来的请求信息:HttpServletRequest
- 如果要处理需要响应给客户端的信息:HttpServletResponse
1、简单分类
向客户端发送数据的方法
ServletOutputStream getOutputStream() throws IOException; //普通输出流 PrintWriter getWriter() 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); void setStatus(int var1);
2、常见应用
- 向浏览器输出消息(getWriter,getOutputStream)
- 下载文件
- 获取下载文件的路径
- 下载的文件名
- 让浏览器支持我们能下载的东西
- 获取下载文件的输入流
- 创建缓冲区
- 获取OutputStream对象
- 将FileOutputStream流写入到buffer缓冲区
- 使用OutputStream将buffer缓冲区的数据输出到客户端
public class FileServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("=====================123131==========================="); //获取下载文件的路径 //String realPath = this.getServletContext().getRealPath("/1.png");//获取绝对路径 String realPath = "/Users/b/Desktop/javacode/JavaWeb_Maven/javaweb-02-servlet/response/src/main/resources/1.png"; System.out.println("下载文件的路径: " + realPath); //下载的文件名 String fileName = realPath.substring(realPath.lastIndexOf("/") + 1); System.out.println(fileName); //让浏览器支持我们能下载的东西 resp.setHeader("Content-Disposition", "attachment;filename=" + fileName); //获取下载文件的输入流 FileInputStream fis = new FileInputStream(realPath); //创建缓冲区 int len = 0; byte[] buffer = new byte[1024]; //获取OutputStream对象 ServletOutputStream servletOutputStream = resp.getOutputStream(); //将FileOutputStream流写入到buffer缓冲区 while ((len = fis.read(buffer)) != -1){ // 使用OutputStream将buffer缓冲区的数据输出到客户端 servletOutputStream.write(buffer, 0, len); } //释放资源 servletOutputStream.close(); fis.close(); }
重定向
方法:
void sendRedirect(String var1) throws IOException;
Demo:
public class RedirectServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.sendRedirect("/download"); } }
重定向与转发
重定向与转发都会使用户访问其他资源,只是发生位置不同,请求转发放生在服务端,只能访问该项目内部资源。重定向是第一次收到用户请求后让客户端重新访问一个新的url地址,客户一共请求了两次。
HttpServletRequest
1、Request常用方法
String getMethod() //获取请求方式 String getContextPath() //获取虚拟路径 String getServletPath() //获取Servlet路径 String getQueryString() //获取get请求方式参数 String getRequestURI() //获取请求uri StringBuffer getRequestURL() //获取URL String getProtocol() //获取协议版本 String getRemoteAddr() //获取客户端ip String getHeader(String name) //通过请求头的名称获取请求头的值 Enumeration<String> getHeaderNames() //获取所有的请求头名称 String getParameter(String var1); //获取一个指定参数的值 Enumeration<String> getParameterNames(); String[] getParameterValues(String var1); //获取多个参数的值,返回一个String数组 Map<String, String[]> getParameterMap();
public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); //设置编码 String username = req.getParameter("username"); String password = req.getParameter("password"); String[] hobbys = req.getParameterValues("hobbys"); System.out.println("================================"); System.out.println(username); System.out.println(password); System.out.println(Arrays.toString(hobbys)); //获取string数组 System.out.println("================================"); req.getRequestDispatcher("/success.jsp").forward(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
这篇关于Java之Servlet的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-22项目:远程温湿度检测系统
- 2024-12-21《鸿蒙HarmonyOS应用开发从入门到精通(第2版)》简介
- 2024-12-21后台管理系统开发教程:新手入门全指南
- 2024-12-21后台开发教程:新手入门及实战指南
- 2024-12-21后台综合解决方案教程:新手入门指南
- 2024-12-21接口模块封装教程:新手必备指南
- 2024-12-21请求动作封装教程:新手必看指南
- 2024-12-21RBAC的权限教程:从入门到实践
- 2024-12-21登录鉴权实战:新手入门教程
- 2024-12-21动态权限实战入门指南