三大件:Servlet、Tomcat、JSP,不过JSP不太常用了,因为前后端分离。
Servlet
最简单的 Servlet
使用 Servlet API 编写 Web Controller,基本上就是重写 doGet 和 doPost
// WebServlet注解表示这是一个Servlet,并映射到地址/:@WebServlet(urlPatterns = "/")public class HelloServlet extends HttpServlet {protected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {// 设置响应类型:resp.setContentType("text/html");// 获取输出流:PrintWriter pw = resp.getWriter();// 写入响应:pw.write("<h1>Hello, world!</h1>");// 最后不要忘记flush强制输出:pw.flush();}}
Servlet对象由Servlet容器(如Tomcat)帮我们创建,不需要我们new
Tomcat 称为 Servlet 容器。
web.xml 文件,放在 src/main/webapp/WEB-INF 目录下,配置路由

Servlet 重定向
@WebServlet(urlPatterns = "/hi")public class RedirectServlet extends HttpServlet {protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 构造重定向的路径:String name = req.getParameter("name");String redirectToUrl = "/hello" + (name == null ? "" : "?name=" + name);// 发送重定向响应:resp.sendRedirect(redirectToUrl);}}
Servlet 映射
<servlet><servlet-name>servletDemo3</servlet-name><servlet-class>com.itheima.web.servlet.ServletDemo3</servlet-class><!--配置Servlet的创建顺序,当配置此标签时,Servlet就会改为应用加载时创建配置项的取值只能是正整数(包括0),数值越小,表明创建的优先级越高--><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>servletDemo3</servlet-name><url-pattern>/servletDemo3</url-pattern></servlet-mapping>
ServletContext
String getInitParameter(String key) : 类似于根据key获取valueString getContextPath() : 获取项目的虚拟路径String getRealPath(String path): 获取文件的真实(服务器)路径域对象:共享数据1. setAttribute(String name,Object value)2. getAttribute(String name)3. removeAttribute(String name)// 获取项目的虚拟路径public class ServletContextDemo2 extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {/*测试ServletContext常用方法String getContextPath() : 获取项目的虚拟路径*///获取ServletContextServletContext context = super.getServletContext();//获取项目虚拟路径String path = context.getContextPath();System.out.println("虚拟路径为: "+path);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request,response);}}
ServletConfig
不太常用,是 Servle t的配置参数对象,可以调用一些方法,读取 Servet 的配置
演示Servlet的初始化参数对象
/*** 演示Servlet的初始化参数对象* @author 黑马程序员* @Company http://www.itheima.com*/public class ServletDemo8 extends HttpServlet {//定义Servlet配置对象ServletConfigprivate ServletConfig servletConfig;/*** 在初始化时为ServletConfig赋值* @param config* @throws ServletException*/@Overridepublic void init(ServletConfig config) throws ServletException {this.servletConfig = config;}/*** doGet方法输出一句话* @param req* @param resp* @throws ServletException* @throws IOException*/@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1.输出ServletConfigSystem.out.println(servletConfig);//2.获取Servlet的名称String servletName= servletConfig.getServletName();System.out.println(servletName);//3.获取字符集编码String encoding = servletConfig.getInitParameter("encoding");System.out.println(encoding);//4.获取所有初始化参数名称的枚举Enumeration<String> names = servletConfig.getInitParameterNames();//遍历nameswhile(names.hasMoreElements()){//取出每个nameString name = names.nextElement();//根据key获取valueString value = servletConfig.getInitParameter(name);System.out.println("name:"+name+",value:"+value);}//5.获取ServletContext对象ServletContext servletContext = servletConfig.getServletContext();System.out.println(servletContext);}/*** 调用doGet方法* @param req* @param resp* @throws ServletException* @throws IOException*/@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);}}
配置 Servlet,使用 init-param 标签
<!--配置ServletDemo8--><servlet><servlet-name>servletDemo8</servlet-name><servlet-class>com.itheima.web.servlet.ServletDemo8</servlet-class><!--配置初始化参数--><init-param><!--用于获取初始化参数的key--><param-name>encoding</param-name><!--初始化参数的值--><param-value>UTF-8</param-value></init-param><!--每个初始化参数都需要用到init-param标签--><init-param><param-name>servletInfo</param-name><param-value>This is Demo8</param-value></init-param></servlet><servlet-mapping><servlet-name>servletDemo8</servlet-name><url-pattern>/servletDemo8</url-pattern></servlet-mapping>
基于注解开发Servlet
使用Servlet3.1版本的规范时,脱离了web.xml进行注解开发
参考这里 https://www.yuque.com/yuchenhuang/dgl7mw/9f418c940abdd1769b9cadedf9c48073#39546de1
req
/*** 请求对象的各种信息获取* @author 黑马程序员* @Company http://www.itheima.com*/public class RequestDemo1 extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//本机地址:服务器地址String localAddr = request.getLocalAddr();//本机名称:服务器名称String localName = request.getLocalName();//本机端口:服务器端口int localPort = request.getLocalPort();//来访者ipString remoteAddr = request.getRemoteAddr();//来访者主机String remoteHost = request.getRemoteHost();//来访者端口int remotePort = request.getRemotePort();//统一资源标识符String URI = request.getRequestURI();//统一资源定位符String URL = request.getRequestURL().toString();//获取查询字符串String queryString = request.getQueryString();//获取Servlet映射路径String servletPath = request.getServletPath();// 获取请求头信息String value = request.getHeader("Accept-Encoding");System.out.println("getHeader():"+value);// 获取请求参数String username = request.getParameter("username");String password = request.getParameter("password");String gender = request.getParameter("gender");}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}
res
public class ResponseDemo4 extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 缓存头String str = "设置缓存时间";response.setDateHeader("Expires",System.currentTimeMillis()+1*60*60*1000);response.setContentType("text/html;charset=UTF-8");response.getOutputStream().write(str.getBytes());//1.设置响应状态码//response.setStatus(302);//2.定向到哪里去: 其实就是设置响应消息头,Location//response.setHeader("Location", "ResponseDemo7");//使用重定向方法response.sendRedirect("ResponseDemo7");//此行做了什么事,请看上面}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}
JSP
还记得 res.end 吗?错了,是 PrintWriter。
PrintWriter pw = resp.getWriter();pw.write("<html>");pw.write("<body>");pw.write("<h1>Welcome, " + name + "!</h1>");pw.write("</body>");pw.write("</html>");pw.flush();
模版放到这里/src/main/webapp,类似 template 目录
hello.jsp
<html><head><title>Hello World - JSP</title></head><body><%-- JSP Comment --%><h1>Hello World!</h1><p><%out.println("Your IP address is ");%><span style="color:red"><%= request.getRemoteAddr() %></span></p></body></html>
JSP在执行前首先被编译成一个Servlet。本质上就是一个Servlet
在Tomcat的临时目录下,可以找到一个hello_jsp.java的源文件
Filter 过滤器
为了把一些公用逻辑从各个Servlet中抽离出来,JavaEE的Servlet规范还提供了一种Filter组件,即过滤器,它的作用是,在HTTP请求到达Servlet之前,可以被一个或多个Filter预处理,类似打印日志、登录检查等逻辑,完全可以放到Filter中。
常见应用场景:URL级别的权限控制;过滤敏感词汇;中文乱码问题等等。
@WebFilter("/*")public class LogFilter implements Filter {public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;String requestURI = req.getRequestURI();chain.doFilter(request, response);}}
配置过滤器
<!--配置过滤器--><filter><filter-name>LogFilter</filter-name><filter-class>com.itheima.web.filter.LogFilter</filter-class></filter><filter-mapping><filter-name>FilterDemo1</filter-name><url-pattern>/*</url-pattern></filter-mapping>
Listener 监听器
把初始化数据库连接池等工作放到contextInitialized()回调方法中,把清理资源的工作放到contextDestroyed()回调方法中
@WebListenerpublic class AppListener implements ServletContextListener {// 在此初始化WebApp,例如打开数据库连接池等:public void contextInitialized(ServletContextEvent sce) {System.out.println("WebApp initialized.");}// 在此清理WebApp,例如关闭数据库连接池等:public void contextDestroyed(ServletContextEvent sce) {System.out.println("WebApp destroyed.");}}
配置监听器
<!--配置监听器--><listener><listener-class>com.itheima.web.listener.ServletContextListenerDemo</listener-class></listener>
MVC

