新职课(chapter5-2)

2023-10-17 06:48
文章标签 chapter5 职课

本文主要是介绍新职课(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是接口,需要实现;关系如图:
    1
  • 使用需要导入 javaee-api-7.0.jar,注意scope
    2
  • 继承和实现都可以
    // 业务逻辑类最终都是要通过这两个方方式调用的嘛
    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类的请求方法包裹处理方法
    • 总之:都完成了路由和限定请求方法的作用

生命周期

  • 四个过程
    • 实例化 --先创建servlet实例
    • 初始化 --init()
    • 处理请求 --service(),即doGet/doPost方法(先调用父类的service())
    • 服务终⽌ --destory()
  • ⽤户发送第⼆次请求时,会判断servlet对象是否存在,但不再执⾏init(),直接执⾏ service ⽅法
    3

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");
    
  • 转发和重定向的区别是什么呢?重定向第一次只返回页面的路径,会再次请求(地址栏修改了两次)
    4
    • 转发会直接返回路由路径

会话

  • 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⻚⾯相关的属性,有三个
    1
  • 可以包含多个page指令,<%@ page attribute="value" %>
    2
  • include可以传入相对路径:<%@ include file="⽂件 url 地址" %>
  • 将JSTL时会详细介绍标签库taglib

常见状态码

  • 提升调错能力
    3

EL表达式

  • 之前使用小脚本的方式,把HTML代码和Java代码混着写,这样好吗?这样不好,容易傻
  • 于是有了EL(expression language),用于展示数据,jsp中使用${ },包括的基础操作符:
    4
  • 来个例子看看,只能识别作用域中的变量,就是那几个内置对象设置的变量才行
    <%@ 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函数
    6
  • 使用: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)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/223656

相关文章

【Chapter5】死锁与饥饿,计算机操作系统教程,第四版,左万利,王英

文章目录 1.1 什么是死锁1.2 死锁的类型1.2.1 竞争资源引起的死锁1.2.2 进程间通信引起的死锁1.2.3 其他原因引起的死锁 1.3 死锁产生必要条件1.4 死锁的处理策略1.5 死锁的预防1.5.1 破坏资源独占条件1.5.2 破坏不可剥夺条件1.5.3 破坏保持申请条件1.5.4 破坏循环等待条件 1.6 死锁的避免1.6.1 什么是安全序列1.6.2 安全序列、不安全状态

【java程序设计期末复习】chapter5 子类的继承

子类的继承 继承是一种由已有的类创建新类的机制。利用继承,我们可以先创建一个共有属性的一般类,根据该一般类再创建具有特殊属性的新类,新类继承一般类的状态和行为,并根据需要增加它自己的新的状态和行为。由继承而得到的类称为子类,被继承的类称为父类(超类)。 Java不支持多重继承(子类只能有一个父类)。 使用关键字extends来定义一个类的子类,格式如下: class Student e

列出游戏库存的字典功能-用Python自动化无聊的东西-chapter5

想象一下,被征服的龙的战利品被表示为这样的字符串: dragonLoot = ['gold coin', 'dagger', 'gold coin', 'gold coin', 'ruby'] 编写一个名为的函数addToInventory(inventory, addedItems),其中inventory参数是表示玩家的库存的字典(如上一个项目中所示),addedItems参数是一个列表d

记录客人带来的食物的总数-用Python自动化无聊的东西-chapter5

当您模拟更复杂的事情时,您可能会发现需要包含其他字典和列表的字典和列表。列表可用于包含一系列有序的值,并且字典对于将键与值相关联很有用。例如,这是一个使用包含其他字典的字典的程序,以查看谁带来了野餐。该totalBrought()功能可以读取此数据结构,并计算所有客人所携带的物品的总数。 提示:应用到字典中嵌套字典,get()获取。 源代码: allGuests = {'Alice': {'

《机器学习(周志华)》Chapter5 神经网络 课后习题答案

若用线性函数作为神经元激活函数则无法处理复杂的非线性问题。 激活函数在神经网络中的作用 相当于每个神经元都在进行对率回归 学习率控制着梯度下降的搜索步长,学习率过大收敛过程容易发生振荡,学习率过小收敛速度过慢 https://blog.csdn.net/victoriaw/article/details/78075266 https://blo

《机器学习(周志华)》Chapter5 神经网络

一、神经元模型: θ为阀值,输入样本x与权重w相乘再求和若大于阀值θ则兴奋即输出为1,否则抑制输出为0,f为激活函数经典的有Sigmoid函数 二、感知机与多层网络: 感知机由两层神经元组成 若θ设置为常数,则可训练出权重w 多层前馈神经网络: 三、误差逆传播算法 称BP算法,采用链式求导法则求出各层权重及阀值的导数。 假设神经网络的输出为: 则均

Java for the Web With Servlets, JSP, and EJB(Part1-Chapter5)Session Management

文章目录 一、为什么需要Session二、信息管理2.1 Server端不存储信息,直接将信息返回给Client(危险!)2.1.1 Server端返回HTML页面的2.1.2 Server端返回JSON的2.1.2 Server/Client将信息写入Cookie 2.2 Server端存储信息,返回Client端一个凭据(没那么危险)2.2.1 凭据使用Cookie或直接写在URL中2.

Java并发编程实战读书笔记-Chapter5-1

Java并发编程实战读书笔记-Chapter5 5.1 同步容器类5.1.1 同步容器类的问题5.1.2 迭代器ConcurrentModificationException 第4章介绍了构造线程安全类时采用的一些技术,例如将线程安全性委托给现有的线程安全类。委托是创建线程安全类的一个最有效的策略:只需让现有的线程安全类管理所有的状态即可。 Java平台类库包含了丰富的并发基础

【王道数据结构】【chapter5树与二叉树】【P159t15】

设计一个算法将二叉树的叶结点从左到右的顺序连成一个单链表,表头指针为head。二叉树按二叉链表方式存储,链接时用叶结点的右指针来存放单链表指针。 #include <iostream>#include <stack>#include <queue>typedef struct treenode{char data;struct treenode *left;struct treeno

【王道数据结构】【chapter5树与二叉树】【P159t13】

假设二叉树采用二叉链表存储结构,设计一个算法,求非空二叉树b的宽度(即具有节点数最多的那一层的结点个数) #include <iostream>#include <stack>#include <queue>typedef struct treenode{char data;struct treenode *left;struct treenode *right;}treenode