三大件:Servlet、Tomcat、JSP,不过JSP不太常用了,因为前后端分离。

Servlet

最简单的 Servlet

使用 Servlet API 编写 Web Controller,基本上就是重写 doGet 和 doPost

  1. // WebServlet注解表示这是一个Servlet,并映射到地址/:
  2. @WebServlet(urlPatterns = "/")
  3. public class HelloServlet extends HttpServlet {
  4. protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  5. throws ServletException, IOException {
  6. // 设置响应类型:
  7. resp.setContentType("text/html");
  8. // 获取输出流:
  9. PrintWriter pw = resp.getWriter();
  10. // 写入响应:
  11. pw.write("<h1>Hello, world!</h1>");
  12. // 最后不要忘记flush强制输出:
  13. pw.flush();
  14. }
  15. }

Servlet对象由Servlet容器(如Tomcat)帮我们创建,不需要我们new

Tomcat 称为 Servlet 容器。

web.xml 文件,放在 src/main/webapp/WEB-INF 目录下,配置路由

JavaWeb - 图1

Servlet 重定向

  1. @WebServlet(urlPatterns = "/hi")
  2. public class RedirectServlet extends HttpServlet {
  3. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  4. // 构造重定向的路径:
  5. String name = req.getParameter("name");
  6. String redirectToUrl = "/hello" + (name == null ? "" : "?name=" + name);
  7. // 发送重定向响应:
  8. resp.sendRedirect(redirectToUrl);
  9. }
  10. }

Servlet 映射

  1. <servlet>
  2. <servlet-name>servletDemo3</servlet-name>
  3. <servlet-class>com.itheima.web.servlet.ServletDemo3</servlet-class>
  4. <!--配置Servlet的创建顺序,当配置此标签时,Servlet就会改为应用加载时创建
  5. 配置项的取值只能是正整数(包括0),数值越小,表明创建的优先级越高
  6. -->
  7. <load-on-startup>1</load-on-startup>
  8. </servlet>
  9. <servlet-mapping>
  10. <servlet-name>servletDemo3</servlet-name>
  11. <url-pattern>/servletDemo3</url-pattern>
  12. </servlet-mapping>

ServletContext

  1. String getInitParameter(String key) : 类似于根据key获取value
  2. String getContextPath() : 获取项目的虚拟路径
  3. String getRealPath(String path): 获取文件的真实(服务器)路径
  4. 域对象:共享数据
  5. 1. setAttribute(String name,Object value)
  6. 2. getAttribute(String name)
  7. 3. removeAttribute(String name)
  8. // 获取项目的虚拟路径
  9. public class ServletContextDemo2 extends HttpServlet {
  10. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  11. /*
  12. 测试ServletContext常用方法
  13. String getContextPath() : 获取项目的虚拟路径
  14. */
  15. //获取ServletContext
  16. ServletContext context = super.getServletContext();
  17. //获取项目虚拟路径
  18. String path = context.getContextPath();
  19. System.out.println("虚拟路径为: "+path);
  20. }
  21. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  22. this.doPost(request,response);
  23. }
  24. }

ServletConfig

不太常用,是 Servle t的配置参数对象,可以调用一些方法,读取 Servet 的配置

演示Servlet的初始化参数对象

  1. /**
  2. * 演示Servlet的初始化参数对象
  3. * @author 黑马程序员
  4. * @Company http://www.itheima.com
  5. */
  6. public class ServletDemo8 extends HttpServlet {
  7. //定义Servlet配置对象ServletConfig
  8. private ServletConfig servletConfig;
  9. /**
  10. * 在初始化时为ServletConfig赋值
  11. * @param config
  12. * @throws ServletException
  13. */
  14. @Override
  15. public void init(ServletConfig config) throws ServletException {
  16. this.servletConfig = config;
  17. }
  18. /**
  19. * doGet方法输出一句话
  20. * @param req
  21. * @param resp
  22. * @throws ServletException
  23. * @throws IOException
  24. */
  25. @Override
  26. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  27. //1.输出ServletConfig
  28. System.out.println(servletConfig);
  29. //2.获取Servlet的名称
  30. String servletName= servletConfig.getServletName();
  31. System.out.println(servletName);
  32. //3.获取字符集编码
  33. String encoding = servletConfig.getInitParameter("encoding");
  34. System.out.println(encoding);
  35. //4.获取所有初始化参数名称的枚举
  36. Enumeration<String> names = servletConfig.getInitParameterNames();
  37. //遍历names
  38. while(names.hasMoreElements()){
  39. //取出每个name
  40. String name = names.nextElement();
  41. //根据key获取value
  42. String value = servletConfig.getInitParameter(name);
  43. System.out.println("name:"+name+",value:"+value);
  44. }
  45. //5.获取ServletContext对象
  46. ServletContext servletContext = servletConfig.getServletContext();
  47. System.out.println(servletContext);
  48. }
  49. /**
  50. * 调用doGet方法
  51. * @param req
  52. * @param resp
  53. * @throws ServletException
  54. * @throws IOException
  55. */
  56. @Override
  57. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  58. doGet(req,resp);
  59. }
  60. }

配置 Servlet,使用 init-param 标签

  1. <!--配置ServletDemo8-->
  2. <servlet>
  3. <servlet-name>servletDemo8</servlet-name>
  4. <servlet-class>com.itheima.web.servlet.ServletDemo8</servlet-class>
  5. <!--配置初始化参数-->
  6. <init-param>
  7. <!--用于获取初始化参数的key-->
  8. <param-name>encoding</param-name>
  9. <!--初始化参数的值-->
  10. <param-value>UTF-8</param-value>
  11. </init-param>
  12. <!--每个初始化参数都需要用到init-param标签-->
  13. <init-param>
  14. <param-name>servletInfo</param-name>
  15. <param-value>This is Demo8</param-value>
  16. </init-param>
  17. </servlet>
  18. <servlet-mapping>
  19. <servlet-name>servletDemo8</servlet-name>
  20. <url-pattern>/servletDemo8</url-pattern>
  21. </servlet-mapping>

基于注解开发Servlet

使用Servlet3.1版本的规范时,脱离了web.xml进行注解开发

参考这里 https://www.yuque.com/yuchenhuang/dgl7mw/9f418c940abdd1769b9cadedf9c48073#39546de1

req

  1. /**
  2. * 请求对象的各种信息获取
  3. * @author 黑马程序员
  4. * @Company http://www.itheima.com
  5. */
  6. public class RequestDemo1 extends HttpServlet {
  7. public void doGet(HttpServletRequest request, HttpServletResponse response)
  8. throws ServletException, IOException {
  9. //本机地址:服务器地址
  10. String localAddr = request.getLocalAddr();
  11. //本机名称:服务器名称
  12. String localName = request.getLocalName();
  13. //本机端口:服务器端口
  14. int localPort = request.getLocalPort();
  15. //来访者ip
  16. String remoteAddr = request.getRemoteAddr();
  17. //来访者主机
  18. String remoteHost = request.getRemoteHost();
  19. //来访者端口
  20. int remotePort = request.getRemotePort();
  21. //统一资源标识符
  22. String URI = request.getRequestURI();
  23. //统一资源定位符
  24. String URL = request.getRequestURL().toString();
  25. //获取查询字符串
  26. String queryString = request.getQueryString();
  27. //获取Servlet映射路径
  28. String servletPath = request.getServletPath();
  29. // 获取请求头信息
  30. String value = request.getHeader("Accept-Encoding");
  31. System.out.println("getHeader():"+value);
  32. // 获取请求参数
  33. String username = request.getParameter("username");
  34. String password = request.getParameter("password");
  35. String gender = request.getParameter("gender");
  36. }
  37. public void doPost(HttpServletRequest request, HttpServletResponse response)
  38. throws ServletException, IOException {
  39. doGet(request, response);
  40. }
  41. }

res

  1. public class ResponseDemo4 extends HttpServlet {
  2. public void doGet(HttpServletRequest request, HttpServletResponse response)
  3. throws ServletException, IOException {
  4. // 缓存头
  5. String str = "设置缓存时间";
  6. response.setDateHeader("Expires",System.currentTimeMillis()+1*60*60*1000);
  7. response.setContentType("text/html;charset=UTF-8");
  8. response.getOutputStream().write(str.getBytes());
  9. //1.设置响应状态码
  10. //response.setStatus(302);
  11. //2.定向到哪里去: 其实就是设置响应消息头,Location
  12. //response.setHeader("Location", "ResponseDemo7");
  13. //使用重定向方法
  14. response.sendRedirect("ResponseDemo7");//此行做了什么事,请看上面
  15. }
  16. public void doPost(HttpServletRequest request, HttpServletResponse response)
  17. throws ServletException, IOException {
  18. doGet(request, response);
  19. }
  20. }

JSP

还记得 res.end 吗?错了,是 PrintWriter。

  1. PrintWriter pw = resp.getWriter();
  2. pw.write("<html>");
  3. pw.write("<body>");
  4. pw.write("<h1>Welcome, " + name + "!</h1>");
  5. pw.write("</body>");
  6. pw.write("</html>");
  7. pw.flush();

模版放到这里/src/main/webapp,类似 template 目录

hello.jsp

  1. <html>
  2. <head>
  3. <title>Hello World - JSP</title>
  4. </head>
  5. <body>
  6. <%-- JSP Comment --%>
  7. <h1>Hello World!</h1>
  8. <p>
  9. <%
  10. out.println("Your IP address is ");
  11. %>
  12. <span style="color:red">
  13. <%= request.getRemoteAddr() %>
  14. </span>
  15. </p>
  16. </body>
  17. </html>

JSP在执行前首先被编译成一个Servlet。本质上就是一个Servlet

在Tomcat的临时目录下,可以找到一个hello_jsp.java的源文件

Filter 过滤器

为了把一些公用逻辑从各个Servlet中抽离出来,JavaEE的Servlet规范还提供了一种Filter组件,即过滤器,它的作用是,在HTTP请求到达Servlet之前,可以被一个或多个Filter预处理,类似打印日志、登录检查等逻辑,完全可以放到Filter中。

常见应用场景:URL级别的权限控制;过滤敏感词汇;中文乱码问题等等。

  1. @WebFilter("/*")
  2. public class LogFilter implements Filter {
  3. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  4. throws IOException, ServletException {
  5. HttpServletRequest req = (HttpServletRequest) request;
  6. String requestURI = req.getRequestURI();
  7. chain.doFilter(request, response);
  8. }
  9. }

配置过滤器

  1. <!--配置过滤器-->
  2. <filter>
  3. <filter-name>LogFilter</filter-name>
  4. <filter-class>com.itheima.web.filter.LogFilter</filter-class>
  5. </filter>
  6. <filter-mapping>
  7. <filter-name>FilterDemo1</filter-name>
  8. <url-pattern>/*</url-pattern>
  9. </filter-mapping>

Listener 监听器

把初始化数据库连接池等工作放到contextInitialized()回调方法中,把清理资源的工作放到contextDestroyed()回调方法中

  1. @WebListener
  2. public class AppListener implements ServletContextListener {
  3. // 在此初始化WebApp,例如打开数据库连接池等:
  4. public void contextInitialized(ServletContextEvent sce) {
  5. System.out.println("WebApp initialized.");
  6. }
  7. // 在此清理WebApp,例如关闭数据库连接池等:
  8. public void contextDestroyed(ServletContextEvent sce) {
  9. System.out.println("WebApp destroyed.");
  10. }
  11. }

配置监听器

  1. <!--配置监听器-->
  2. <listener>
  3. <listener-class>com.itheima.web.listener.ServletContextListenerDemo</listener-class>
  4. </listener>

MVC

JavaWeb - 图2