本文主要是介绍新职课(chapter5-2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- Servlet
- API
- 生命周期
- Request
- Response
- 会话
- 初始化参数
- 注解
- JSP
- 内置对象
- 指令
- 常见状态码
- EL表达式
- JSTL
Servlet
- Servlet(Server Applet)
- 作用:是⽤Java编写的服务器端程序,扩展基于HTTP协议的Web服务器
- 说成人话就是:运行于tomcat这样的应用服务器之上的处理web请求的类(接口),实现请求与处理的衔接
tomcat + Servlet
提供了JavaWeb的运行环境,类似Python中的UWSGI服务器,实现路由
- 工作流程
- 客户端发送请求⾄服务器
- 服务器启动并调⽤Servlet,Servlet根据客户端请求⽣成响应内容(调用我们自定义的逻辑)并将其传给服务器
- 服务器将响应返回客户端
API
- Servlet是接口,需要实现;关系如图:
- 使用需要导入 javaee-api-7.0.jar,注意scope
- 继承和实现都可以
// 业务逻辑类最终都是要通过这两个方方式调用的嘛 public class ServletTest extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 业务逻辑System.out.println("get---------");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 业务逻辑System.out.println("post----------");} }
- 如何验证,我们用到了实现的servlet,处理前端的请求?要用到WEB-INF/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"><servlet><servlet-name>demo</servlet-name><servlet-class>web.ServletTest</servlet-class></servlet><servlet-mapping><servlet-name>demo</servlet-name><url-pattern>/test</url-pattern></servlet-mapping> </web-app>
- mapping中匹配到路径,就到servlet标签中找逻辑类,调用我们重写的
get/post
方法 - flask用装饰器路由到处理方法,并限定请求方法;这里用xml映射和servlet类的请求方法包裹处理方法
- 总之:都完成了路由和限定请求方法的作用
- mapping中匹配到路径,就到servlet标签中找逻辑类,调用我们重写的
生命周期
- 四个过程
- 实例化 --先创建servlet实例
- 初始化 --init()
- 处理请求 --service(),即doGet/doPost方法(先调用父类的service())
- 服务终⽌ --destory()
- ⽤户发送第⼆次请求时,会判断servlet对象是否存在,但不再执⾏init(),直接执⾏
service
⽅法
Request
HttpServletRequest
表示Http环境中的Servlet请求。它扩展于 javax.servlet.ServletRequest 接⼝- 更改一下业务逻辑,使用
req
获取参数getParameter()
public class ServletTest extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 业务逻辑System.out.println("get---------");String username = req.getParameter("username");String userage = req.getParameter("userage");System.out.println(username+"----"+userage);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 业务逻辑System.out.println("post----------");req.setCharacterEncoding("utf-8");String username = req.getParameter("username");System.out.println(username);} }
- get请求不需要指定编码,post请求需要指定
- 更改代码后需要重启tomcat应用服务器
- 无论前端使用什么格式传递,后端都用
String
接收,也可以指定跳转到某个页面(redirect)@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 业务逻辑System.out.println("post----------");req.setCharacterEncoding("utf-8");String username = req.getParameter("username");System.out.println(username);String[] hobbyes = req.getParameterValues("hobby");for (String hobby : hobbyes) {System.out.println(hobby);}req.getRequestDispatcher("/index.html").forward(req,resp); // 这个根目录就是web }
- 在单次请求中,可以存值取值
@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 业务逻辑System.out.println("get---------");String username = req.getParameter("username");String userage = req.getParameter("userage");System.out.println(username+"----"+userage);req.setAttribute("usersex", "man");Object sex = req.getAttribute("usersex");System.out.println(sex);req.getRequestDispatcher("/index.html").forward(req,resp); }
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>demo</title> </head> <body><h1>this is demo for servlet</h1><!-- 查询字符串 也叫路径参数--><a href="test?username=roy&userage=18">servlet impl</a><form action="test" method="post">username: <input type="text" name="username"><input type="submit" value="servlet">hobby: <input type="checkbox" value="basketball" name="hobby"> 篮球<input type="checkbox" value="volleyball" name="hobby"> 排球<input type="checkbox" value="soccer" name="hobby"> 足球</form> </body> </html>
Response
- 目前能看到效果的就是redirect方法
// req.getRequestDispatcher("/index.html").forward(req,resp); resp.sendRedirect("/index.html");
- 转发和重定向的区别是什么呢?重定向第一次只返回页面的路径,会再次请求(地址栏修改了两次)
- 转发会直接返回路由路径
会话
- request存的值只能在单次请求中保存,保存的数据不能跨⻚⾯,当重定向时,request存的值会丢失
- 会话:从打开浏览器到关闭浏览器,期间访问服务器就称为⼀次会话
- session的数据可以在多个⻚⾯中共享
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 业务逻辑System.out.println("get---------");// sessionHttpSession session = req.getSession();session.setAttribute("name", "roy");session.getAttribute("name");String sid = session.getId();System.out.println(sid); // 520A40F0E0F2022B809BAC62D0579C5Dresp.sendRedirect("/index.html"); }
初始化参数
- 分全局和局部初始化参数,编写两个业务类测试一下,对应的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"><context-param><param-name>param_g</param-name><param-value>allen~</param-value></context-param><servlet><servlet-name>demo</servlet-name><servlet-class>web.ServletTest</servlet-class><!--局部初始化参数--><init-param><param-name>param_l</param-name><param-value>roy~</param-value></init-param></servlet><servlet-mapping><servlet-name>demo</servlet-name><url-pattern>/test</url-pattern></servlet-mapping><servlet><servlet-name>demo2</servlet-name><servlet-class>web.ServletParam</servlet-class></servlet><servlet-mapping><servlet-name>demo2</servlet-name><url-pattern>/test2</url-pattern></servlet-mapping> </web-app>
public class ServletTest extends HttpServlet {@Overridepublic void init(ServletConfig config) throws ServletException {System.out.println(config.getInitParameter("param_l")); // local paramSystem.out.println(config.getServletContext().getInitParameter("param_g")); // global init param} }
public class ServletParam extends HttpServlet {@Overridepublic void init(ServletConfig config) throws ServletException {System.out.println(config.getInitParameter("param_l")); // local paramSystem.out.println(config.getServletContext().getInitParameter("param_g")); // global init param} }
注解
- 使用注解的方式实现Servlet,不使用xml文件映射;更像Python装饰器了
@WebServlet(urlPatterns = {"/test/stu", "/test/student"}, name="stu", initParams = {@WebInitParam(name = "stu-param", value = "stu-value") }, loadOnStartup = 1) // 值越小,优先级越高 public class Student extends HttpServlet {@Overridepublic void init(ServletConfig config) throws ServletException {System.out.println("stu servlet: " + config.getInitParameter("stu-param"));}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("get");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);} }
JSP
- Java Server Pages,其根本是⼀个简化的Servlet设计,底层还是servlet
- JSP就是在HTML⻚⾯中嵌⼊了java代码,得到
.jsp
动态页面(应以HTML为主)- 使用小脚本嵌入Java代码
<%!变量或者⽅法声明%> // 声明标签 <%= 表达式%> // 表达式标签 <%java代码%> // 程序代码标签
- 看个例子,这里要用到 jasper-6.0.29.jar
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <body><%! int i=10;%> <!--成员变量--><%! public void show(){}%> <!--成员⽅法--><%=i%> <!--输出变量值,要输出的话就不能跟分号--> </body>
- 原理
- 根据路径找到index.jsp⽂件
- 翻译成index_jsp.java⽂件
- 进⾏编译,产⽣⼀个index_jsp.class⽂件,加载运⾏
- HTML代码最终以流的形式翻译输出到class,再写回浏览器(out.Writer()),这期间动态的换上了Java逻辑要输出的内容
- 查看生成的
.java
文件会发现继承了HttpServlet
- 查看生成的
内置对象
- 面试必考,有九个分别为:
request、response、session、application、out、 pagecontext、config、page、exception
- 建立两个页面测试一下下面四个对象的作用域:
// index.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html><head><title>$Title$</title></head><body><% // 单次请求期间,通过index2.jsp访问就会变成nullrequest.setAttribute("a",10); %>request: <%= request.getAttribute("a") %><% // 一次浏览器会话期间session.setAttribute("b", 11);%>session: <%= session.getAttribute("b")%><% // 整个程序运行期间,换了浏览器也行application.setAttribute("c", 12);%>appliaction: <%= application.getAttribute("c") %><% // 当前页面, page = java this 可以获取当前页面的java对象pageContext.setAttribute("d", 13);%>page: <%= pageContext.getAttribute("d") %></body> </html>
// index2.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>index2.jsp</title> </head> <body>request: <%= request.getAttribute("a") %>session: <%= session.getAttribute("b")%>application: <%= application.getAttribute("c") %>page: <%= pageContext.getAttribute("d") %> </body> </html>
- 换了浏览器application的值仍然可以get到
- 可以指定404页面(errorPage)
// index.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="index2.jsp" %> // 制造异常 out: <% out.print(6/0);%>// index2.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %> errorMSG: <%=exception.getMessage() %>
指令
- JSP指令⽤来设置整个JSP⻚⾯相关的属性,有三个
- 可以包含多个page指令,
<%@ page attribute="value" %>
- include可以传入相对路径:
<%@ include file="⽂件 url 地址" %>
- 将JSTL时会详细介绍标签库taglib
常见状态码
- 提升调错能力
EL表达式
- 之前使用小脚本的方式,把HTML代码和Java代码混着写,这样好吗?这样不好,容易傻
- 于是有了EL(expression language),用于展示数据,jsp中使用
${ }
,包括的基础操作符:
- 来个例子看看,只能识别作用域中的变量,就是那几个内置对象设置的变量才行
<%@ page import="java.util.List" %> <%@ page import="java.util.ArrayList" %> <%@ page import="java.util.Map" %> <%@ page import="java.util.HashMap" %><%--Created by IntelliJ IDEA.User: Windows10Date: 2021/12/28Time: 14:57To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %> <html> <head><title>index2.jsp</title> </head> <body><%request.setAttribute("p1", 15);List list = new ArrayList();list.add(18);pageContext.setAttribute("p2", list);Map map = new HashMap();map.put("m1", 66);application.setAttribute("p3", map);%>${10+20}<br>p1: ${p1}<br>list: ${p2[0]}<br>map: ${p3.m1} </body> </html>
- 如果内置对象设置的变量名冲突了呢?默认从小到大找:pageContext < request < session < application
JSTL
- EL最初定义于JSTL1.0部分,JSP2.0之后将其搞出来成为了JSP的一部分
- JSTL就是封装了EL的标签库,让我们更方便的使用EL,而定义的一些标签,更加简化jsp⻚⾯的编写
- 比如EL取集合的值只能逐个写标签,不能循环取值
- 按功能分五部分:分别是 :核⼼标签 格式化标签 sql标签 xml标签 jstl函数
- 使用:jakarta-taglibs-standard-1.1.2/lib/ 下的两个 jar ⽂件:standard.jar 和 jstl.jar ⽂件拷⻉到 /WEB-INF/lib/ 下
- taglibs是JSTL的具体实现,所以下载的话还是taglibs,里面包含了jstl和standard,别搞混
- 核⼼标签是最常⽤的 JSTL标签,看个例子
<%@ page import="java.util.List" %> <%@ page import="java.util.ArrayList" %> <%@ page import="java.util.Date" %><%--Created by IntelliJ IDEA.User: Windows10Date: 2021/12/28Time: 21:12To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <html> <head><title>Title</title> </head> <body><h1>JSTL</h1><c:set var="name" value="roy" scope="session"></c:set>${name}<%--一般使用上面的EL表达式直接输出--%><c:out value="${sessionScope.name}"></c:out><%--分支 --%><c:if test="${name=='roy'}">this is roy.</c:if><%--多分支--%><c:choose><c:when test="${name=='allen'}">this is allen.</c:when><c:otherwise>this is roy.</c:otherwise></c:choose><%List list = new ArrayList();list.add(18);list.add(20);pageContext.setAttribute("list", list);%><%--循环结果--%><c:forEach items="${list}" var="id" varStatus="stat">${stat.count}---${stat.index}: ${id}<br></c:forEach><%--i18n--%><%pageContext.setAttribute("time", new Date());%><fmt:formatDate value="${time}" pattern="yyyy-MM-dd"></fmt:formatDate> </body> </html>
- 比较常用的还有
fmt:formatDate
- 比较常用的还有
- OK!
这篇关于新职课(chapter5-2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!