JavaWeb程序设计学习随笔
第4章 请求与相应
1. 中文乱码问题
-
原因:
-
HttpServletRequest请求对象默认使用ISO8859-1表对客户端中文字符数据编码解码,而Java平台默认显示utf8。
-
HttpServletResponse响应对象默认使用ISO8859-1表编码,浏览器默认使用GB2312表解码;
-
-
解决:
-
响应消息返回客户端时的乱码
//方法一 response.setContentType("text/html; charset=utf-8"); //直接设置响应消息的文本格式。 //方法二 response.setCharacterEncoding("utf-8"); //设置response对象的编码方式。 response.setHeader("Content-Type","text/html;charset=utf-8"); //设置消息头告知浏览器编码方式。
-
请求消息发送到后台时的乱码
//post提交方式的参数存放在消息体中,因此可设置请求对象的解码方式 request.setCharacterEncoding("utf-8"); //get方式的请求参数存放在消息头中,需要手动转码。 String value = request.getParameter("paramName"); //获取乱码的字符串参数; byte[] binValue = value.getBytes("iso-8859-1"); //用默认码表变回字节码; value = new String(binValue, "utf-8"); //用utf8码表重新解码成字符串。
-
2. 应用response对象实现网页跳转
//通过消息头告知浏览器定时刷新页面或跳转(必须设置时间,若没有URL则只刷新)。
response.setHeader("Refresh", "3; /chapter04/RedirectedServlet");
//重定向请求,会让客户端重新发送请求信息到指定URL。
response.sendRedirect("/chapter04/table.html");
3. 应用request对象实现请求转发
//在request中可获取转发器对象
RequestDispatcher dispatcher = request.getRequestDispatcher("/ForwardedServlet");
//使用转发器直接方式转发请求,不使用当前servlet
dispatcher.forward(request, response);
//使用转发器以包含方式转发,即包含两个servlet的响应消息
dispatcher.include(request, response);
第5章 会话技术
1. cookie技术的实现
-
简述
- 用于将会话过程中的数据保存到用户的浏览器中。
- 用响应头的Set-Cookie字段发给浏览器,浏览器请求访问时在请求头将cookie发回给servlet。
- 一个cookie就是一个名称和它对应的string类型的值(不能含特殊符号)。
-
构造器
public Cookie(String name, String value);
-
实现示例
//1、在请求消息获取cookie集合 Cookie[] cookies = request.getCookies(); String lastVisitedTime = null; //2、遍历请求消息中的cookie集合,找到某cookie名称。 if (cookies != null) { for (int i = 0; i < cookies.length; i++) { if (cookies[i].getName().equals("lastVisited")) { lastVisitedTime = cookies[i].getValue(); } } } //3、判断是否找到相应的cookie。 if (lastVisitedTime == null) { response.getWriter().print("你是首次访问本站!" +"<br>"); } else { response.getWriter().print("你上次的访问时间是:" +lastVisitedTime +"<br>"); } //4、每次访问都创建新cookie //注意!!构造cookie时的value中不能含有空格、逗号、分号等特殊字符!否则addCookie()方法会异常报警,发送失败。 String currentTime = (new SimpleDateFormat("yyyy-MM-dd/hh:mm:ss")).format(new Date()); Cookie timeCookie = new Cookie("lastVisited", currentTime); //5、设置cookie的生效时长,并发送回客户端。 timeCookie.setMaxAge(5*60); response.addCookie(timeCookie);
2. session技术的实现
-
简述
- 用于将会话数据保证在服务器端一段时间。
- 一个session对象有一个ID属性,用于找出该会话数据,且需要借助cookie传递id值,以辨别用户。
- session对象可以将其他对象作为属性来存入、取出、删除。
- session对象有默认“超时限制”(在web.xml中
标签),没有客户继续访问时,将结束会话,session失效。
-
常用方法
方法 功能 void setAttribute(String name, Object value) 存入数据对象 Object getAttribute(String name) 返回一个指定的数据对象 void removeAttribute(String name) 删除一个指定的数据对象 String getId() 返回该session对象的ID void invalidate() 强制使session对象无效 -
实现示例
//1、在请求对象中获取session对象(request会根据请求头cookie记录的JSESSIONID属性查找对应的会话)。 HttpSession session = request.getSession(true); //2、在session对象中获取存放的数据对象。 User user = (User) session.getAttribute("user"); //3、判断如果没有存放数据对象,则创建并存入。 if (user == null) { User user = new User(); session.setAttribute("user", user); } //4、创建cookie响应会话id给客户端(不建议用cookie,httpSession可以自动找到与客户端的会话) Cookie cookie = new Cookie("JSESSIONID", session.getId()); cookie.setMaxAge(30*60); response.addCookie(cookie);
第6章 JSP技术
1. 概述
-
JSP全称Java Server Pages,是一种动态网页开发技术。它使用JSP标签在HTML网页中插入Java代码,用来实现网页中的动态内容展示,文件后缀为.jsp。
-
JSP基于servlet程序,工作模式是请求/响应模式,客户端发出http请求,jsp程序收到请求后处理并响应。jsp文件第一次收到请求时,jsp容器(即catalina程序)会把jsp文件转换成一个servlet程序,并成为服务器的常驻程序,所有响应非常快。
-
一个html文件第一行加上jsp声明标签,并将后缀改成.jsp,即可变成jsp文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
了解详情,请查看https://www.runoob.com/jsp/jsp-tutorial.html
2. 基本语法标签
-
脚本语句(会被jsp容器编译到_jspService()方法中,并会被执行。)
<% 执行语句 %> //或使用等价的xml标签 <jsp:scriptlet> 执行语句 </jsp:scriptlet>
-
声明语句(用作声明变量,jsp容器会将其编译在_jspService()方法外,成为servlet对象的成员变量)
<%! 声明语句; 声明语句; ... %> //或 <jsp:declaration> 声明语句 </jsp:declaration>
-
表达式语句(用于将servlet的数据响应回客户端,等价于out.print()方法)
<%= 表达式 %> //或 <jsp:expression> 表达式 </jsp:expression>
-
注释(注释内容不会被发送至浏览器甚至不会被编译)
<%-- 注释 --%>
3. jsp指令
用来设置整个JSP页面相关的属性,如网页的编码方式和脚本语言。如:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
指令 | 描述 |
---|---|
<%@ page ... %> | 定义网页依赖属性,比如脚本语言、error页面、缓存需求等等 |
<%@ include ... %> | 包含其他文件 |
<%@ taglib ... %> | 引入标签库的定义 |
4. jsp动作
JSP动作元素是用XML语法写成,可以动态地插入文件、重用JavaBean组件、把用户重定向到另外的页面、为Java插件生成HTML代码。动作元素基本上都是预定义的函数,JSP规范定义了一系列的标准动作,它用JSP作为前缀:
语法 | 描述 |
---|---|
jsp:include | 在页面被请求的时候引入一个文件。 |
jsp:useBean | 寻找或者实例化一个JavaBean。 |
jsp:setProperty | 设置JavaBean的属性。 |
jsp:getProperty | 输出某个JavaBean的属性。 |
jsp:forward | 把请求转到一个新的页面。 |
jsp:plugin | 根据浏览器类型为Java插件生成OBJECT或EMBED标记。 |
jsp:element | 定义动态XML元素 |
jsp:attribute | 设置动态定义的XML元素属性。 |
jsp:body | 设置动态定义的XML元素内容。 |
jsp:text | 在JSP页面和文档中使用写入文本的模板 |
5. 隐式对象
jsp默认创建的内置对象
对象 | 描述 |
---|---|
request | HttpServletRequest 接口的实例 |
response | HttpServletResponse 接口的实例 |
out | JspWriter类的实例,用于把结果输出至网页上 |
session | HttpSession类的实例 |
application | ServletContext类的实例,与应用上下文有关 |
config | ServletConfig类的实例 |
pageContext | PageContext类的实例,提供对JSP页面所有对象以及命名空间的访问 |
page | 类似于Java类中的this关键字 |
Exception | Exception类的对象,代表发生错误的JSP页面中对应的异常对象 |
6. 实现代码示例
一个页面的不同板块作为不同的jsp文件,再用<%@ include file="url" %>
指令将它们拼接成完整的页面,提高页面板块的复用性。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>首页</title>
<link rel="stylesheet" href="css/初始化样式.css" type="text/css">
<link rel="stylesheet" href="css/12-23页面布局详细样式.css" type="text/css">
</head>
<body>
<!-- 1. 插入头部部分 -->
<%@include file="head.jsp" %>
<!-- 2. 插入内容主体 -->
<section class="main_body center">
<%@include file="leftSection.jsp" %>
<%@include file="rightSection.jsp" %>
</section>
<!-- 3. 插入页脚部分 -->
<%@include file="foot.jsp" %>
</body>
</html>
第7章 Bean、EL、JSTL等jsp工具
1. JavaBean
-
JavaBean 是特殊的 Java 类,使用 Java 语言书写,并且遵守 JavaBean API 规范:
- 有且仅有一个默认的无参构造函数。
- 需要被序列化并且实现了 Serializable 接口。
- 可能有一系列可读写属性(成员变量)。
- 可能有一系列的 getter 或 setter 方法。
-
Apache BeanUtils工具可用来快速操作Bean对象,需要导入相应jar包。
- beanUtils 可以便于对javaBean的属性进行赋值。
- beanUtils 可以便于对javaBean的对象进行赋值。
- beanUtils可以将一个MAP集合的数据拷贝到一个javabean对象中。
- 数据类型转换:字符串类型转换为各种具体的数据类型(实现Converter接口)。
2. EL表达式
-
概述
-
EL即Expression Language,一种数据访问格式,用于获取servlet域对象中存储的数据。
-
使得访问存储在JavaBean中的数据变得非常简单。JSP EL既可以用来创建算术表达式也可以用来创建逻辑表达式。在JSP EL表达式内可以使用整型数,浮点数,字符串,常量true、false,还有null。
-
格式:
${expression}
-
表达式中可使用常量和运算符、还可使用有特殊功能的保留字。
-
-
隐式对象
隐含对象 描述 pageScope page 作用域 requestScope request 作用域 sessionScope session 作用域 applicationScope application 作用域 param Request 对象的参数,字符串 paramValues Request对象的参数,字符串集合 header HTTP 信息头,字符串 headerValues HTTP 信息头,字符串集合 initParam 上下文初始化参数 cookie Cookie值 pageContext 当前页面的pageContext
3. JSTL
-
概述
JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能,即一些有特殊功能的标签。包括5大类:
标签库 标签库的引入URI 功能 Core <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 一些通用操作 |18N <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 实现国际标准化操作 SQL <%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> 数据库操作(较少用) XML <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> 创建和操作XML文档的操作 函数 <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> 一些通用的字符串处理函数 -
使用
-
到Apache基金会官网下载一个二进制工具包jakarta-taglibs-standard-1.1.2.zip。
-
将里面的jstl.jar和standard.jar两个包导入到web项目。
-
在jsp文件加上taglib指令,即可引入标签库到jsp文件。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> //引入标签库 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title></title> </head> <body> <c:out value="Hello World!"></c:out> //使用标签,格式:<前缀:标签> </body> </html>
-
第8章 过滤器和监听器
1. 过滤器Filter
-
JSP 和 Servlet 中的过滤器都是filter接口的实现类,在servlet容器调用servlet程序之前,和servlet响应回客户端之前,都会先被过滤器拦截,并进行一些操作。
-
实现filter接口,重写方法,在web.xml中注册过滤器,即可实现拦截。
-
注册过滤器时使用
<dispatcher>
标签,可以指定何种调用方式会被拦截,可以是REQUEST
,INCLUDE
,FORWARD
和ERROR
之一,默认REQUEST
。用户可以设置多个<dispatcher>
子元素用来指定 Filter 对资源的多种调用方式进行拦截。 -
filter接口的3个方法:
-
public void init(FilterConfig filterConfig)
FilterConfig 对象可获取filter初始化的配置参数(在web.xml的
<filter>
标签中)。 -
public void doFilter (ServletRequest, ServletResponse, FilterChain)
过滤器主要操作都在doFilter()中进行,只有调用过虑链的对象方法FilterChain.doFilter()才能将请求交付,否则请求无法访问目标servlet。
-
public void destroy()
-
2. 过虑链FilterChain
-
过虑链即多个filter对同一个URL进行拦截,无论请求还是响应,都要经过多个filter程序组成的链。
-
只需在web.xml注册多个过滤器时,将映射设为同一个目标,即可构成过虑链,链的顺序与注册顺序一致。
-
过虑链类似递归法,当目标servlet返回响应时,每个filter将会继续执行chain.dofilter()后的代码。
-
实现代码示例:
-
目标servlet
public class targetServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().println("Target servlet received the request."); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
-
过滤器1
public class filterOne implements Filter { FilterConfig config = null; public void init(FilterConfig fConfig) throws ServletException { this.config = fConfig; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { response.getWriter().println(config.getFilterName()+":Request passed the filter01"); chain.doFilter(request, response); response.getWriter().println(config.getFilterName()+":Response passed the filter01"); } public void destroy() { } }
-
过滤器2
public class filterTwo implements Filter { FilterConfig config = null; public void init(FilterConfig fConfig) throws ServletException { this.config = fConfig; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { response.getWriter().println("Request passed the filter02 " +config.getInitParameter("date")); chain.doFilter(request, response); response.getWriter().println("Response passed the filter02 " +config.getInitParameter("date")); } public void destroy() { } }
-
注册到web.xml
<servlet> <servlet-name>targetServlet</servlet-name> <servlet-class>idv.jarjack.chapter08.chainTest.targetServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>targetServlet</servlet-name> <url-pattern>/targetServlet</url-pattern> </servlet-mapping> <filter> <filter-name>filterOne</filter-name> <filter-class>idv.jarjack.chapter08.chainTest.filterOne</filter-class> </filter> <filter-mapping> <filter-name>filterOne</filter-name> <url-pattern>/targetServlet</url-pattern> </filter-mapping> <filter> <filter-name>filterTwo</filter-name> <filter-class>idv.jarjack.chapter08.chainTest.filterTwo</filter-class> <init-param> <param-name>date</param-name> <param-value>2021/8/16</param-value> </init-param> </filter> <filter-mapping> <filter-name>filterTwo</filter-name> <url-pattern>/targetServlet</url-pattern> </filter-mapping>
-
运行结果
-
3. 监听器Listener
-
监听的组成:
- 事件源:发生事件的对象。
- 事件:对象发生的某个行为,如创建、销毁、点击等。
- 监听器:接收事件对象的程序。
- 处理器:监听器程序中处理事件的方法。
-
监听的过程:
- 事件源要注册一个或多个监听器;
- 事件源发生相应事件;
- 被注册的监听器收到相应事件对象;
- 监听器调用相应的方法处理事件。
-
servlet事件监听器专门监听web应用中的域对象,具有监听创建、销毁、属性变更等事件的8种监听器,且域对象默认注册了相应的监听器。
-
创建销毁的监听器
- ServletContextListener
- ServletRequestListener
- HttpSessionListener
-
属性变更的监听器
- ServletContextAttributeListener
- ServletRequestAttributeListener
- HttpSessionAttributeListener
-
会话事件的监听器
-
HttpSessionBindingListener 用于监听Bean对象在HttpSession对象中的绑定或解绑。
-
HttpSessionActivationListener 用于监听HttpSession对象活化或钝化的事件。
(钝化是会话数据从内存持久到硬盘,活化是持久化的数据放到内存中运行。)
-
-
-
实现代码示例(以request域对象为例)
-
创建一个过程监听器
public class ProcessListener implements ServletContextListener, ServletRequestListener { public ProcessListener() { System.out.println("==== 过程监听器已开启 ===="); } public void requestInitialized(ServletRequestEvent sre) { System.out.println("==== request对象被创建 ===="); } public void requestDestroyed(ServletRequestEvent sre) { System.out.println("==== request对象被销毁 ===="); } public void contextDestroyed(ServletContextEvent sce) { System.out.println("==== context对象被销毁 ===="); } public void contextInitialized(ServletContextEvent sce) { System.out.println("==== context对象被创建 ===="); } }
-
创建一个属性监听器
public class AttribListener implements ServletRequestAttributeListener { public AttribListener() { System.out.println("==== 属性监听器已开启 ===="); } public void attributeRemoved(ServletRequestAttributeEvent srae) { System.out.println("request对象移除了属性:" +srae.getName()); } public void attributeAdded(ServletRequestAttributeEvent srae) { System.out.println("request对象添加了属性:" +srae.getName()); } public void attributeReplaced(ServletRequestAttributeEvent srae) { System.out.println("request对象替换了属性:" +srae.getName()); } }
-
在web.xml中有web应用注册监听器的信息
<listener> <listener-class>idv.jarjack.chapter08.listenerTest.ProcessListener</listener-class> </listener> <listener> <listener-class>idv.jarjack.chapter08.listenerTest.AttribListener</listener-class> </listener>
-
试验的jsp文件
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>测试监听器的页面</title> </head> <body> This is a listener test page. <% request.setAttribute("paramName", "paramValue"); request.setAttribute("paramName", "value"); request.removeAttribute("paramName"); %> </body> </html>
-
监听结果
-
第11章 web应用的开发模型
1. jsp开发模型
在web开发中,为了更方便地使用JSP技术,SUN公司为JSP开发提供了两种开发模型:JSP Model 1 和 JSP Model 2。Model 1简单轻便,适合小型web项目的快速开发;Model 2 在Model 1的基础上更清晰分层,更适合多人合作开发的大型web项目。
JSP文件是一个可以独立自主完成所有任务的模块,可以负责处理业务逻辑、控制页面流程和输出等所有事务(即“浏览器—JSP—数据库”模型),但是这样的应用中,JSP页面功能过于复杂:html代码和Java代码强耦合,导致代码可读性差;数据、业务逻辑、和控制流程混在一起,使得程序难以修改和维护,因此需要用到可将应用的不同事务拆分的模型。
-
JSP Model 1
-
使用 JSP+JavaBean 的技术,将页面显示和业务逻辑分开。
-
JSP文件实现流程控制和页面显示,JavaBean对象实现数据封装和业务逻辑。
-
-
JSP Model 2
-
使用 JSP+Servlet+JavaBean 技术,将原本JSP页面中的流程控制代码放在servlet程序中,实现web应用的页面显示、流程控制、业务逻辑的分离。
-
实际上就是MVC模式,servlet接收客户端请求,根据请求调用JavaBean对象封装数据库返回的数据,最后选择相应的JSP页面响应给客户端。
-
2. MVC设计模式
即模型-视图-控制器模式(Model-View-Controller)。
-
控制器接收到用户请求后,会根据请求调用模型中的业务方法。
-
业务处理完后,控制器再根据模型返回的结果选择相应的视图。
-
视图显示处理结果和响应的数据。