JSP原理和使用
jsp简介
JSP(全称 Java Server Pages)Java 服务端页面技术,是 JavaEE 平台下的技术规范。它允许 使用特定的标签在 HTML 网页中插入 Java 代码,实现动态页面处理,所以 JSP 就是 HTML 与 Java 代码的复合体。JSP 技术可以快速的实现一个页面的开发,相比在 Servlet 中实现页面开 发将变得更加容易。
jsp原理
jsp技术特点
- JSP 和 Servlet 是本质相同的技术。当一个 JSP 文件第一次被请求时,JSP 引擎会将该 JSP 编译成一个 Servlet,并执行这个 Servlet。如果 JSP 文件被修改了,那么 JSP 引擎会重新编译 这个 JSP。
- JSP 引擎对 JSP 编译时会生成两个文件分别是.java 的源文件以及编译后的.class 文件,并 放到 Tomcat 的 work 目录的 Catalina 对应的虚拟主机目录中的 org\apache\jsp 目录中。两个 文件的名称会使用 JSP 的名称加”_jsp”表示。如:index_jsp.java、index_jsp.class
jsp与servlet的区别
- JSP以源文件形式(扩展名以_jap.java和_jap.java结尾)部署到容器中。而 Servlet 需要编译成 class 文件后部署到容器中。
- JSP 部署到 web 项目的根目录下或根目录下的其他子目录和静态同资源位于相同位置。而 Servlet 需要部署到 WEB-INF/classes 目录中。
- JSP 中的HTML代码会被 JSP 引擎放入到 Servlet 的 out.write()方法中。而在 Servlet 中我们需要自己通过对字符流输出流的操作生成响应的页面。
- JSP 更擅长表现于页面显示(写html代码),Servlet 更擅长于逻辑控制(写java代码)
jsp使用
jsp三种原始标签
jsp原始标签再任何版本都能使用
<%! %> 声明标签
- 声明标签用于在 JSP 中定义成员变量与方法的定义。标签中的内容会出现在 JSP 被编译 后的 Servlet 的 class 的{}中。
<% %> 脚本标签
- 脚本标签用于在 JSP 中编写业务逻辑。标签中的内容会出现在 JSP 被编译后的 Servlet的_jspService 方法体中。
<%= %> 赋值标签
- 赋值标签用于在 JSP 中做内容输出。标签中的内容会出现在_jspService 方法的 out.print() 方法的参数中。注意我们在使用赋值标签时不需要在代码中添加 ”;”。
jsp原始标签使用
需求:以20%概率显示你中奖了
首先idea导入jar包是servlet—api,其次我们需要在web里面创建.jsp文件
jsp中不支持语句的嵌套
<%@ page import="java.util.Random" %><%--
Created by IntelliJ IDEA.
User: pain_
Date: 2020/9/13
Time: 10:49 下午
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
// int flag =(int)(100*Math.random());
int flag =new Random().nextInt(100);
if(flag <= 20){
%>
中奖了<%=flag%>
<%
}else{
%>
再试试吧<%=flag%>
<%
}
%>
</body>
</html>
常用的指令标签分类
指令标签作用声明jsp页面的一些属性和动作
<%@指令名称 属性=“值” 属性“值”%> 值是字符串
-
page:主要声明jsp页面的一些属性
1.contextType 设置响应类型和编码
2.pageEncoding 设置页面编码
3.import:导入需要的包
4.session:设置jsp页面是否获取session内置对象 (在声明中可以设置是否获取session属性 session=“false”则不获取。 -
include:静态包含 可以将其他页面内容包含进来,一起进行编译运行,生成一个java.文件
<%@include file="包含jsp的相对路径"%> -
taglib;导入标签库(导入第三方标签)
<%taglib prefix="前缀名“ url=”名称空间“% >
jsp内置对象
- request 对象
request 对象是 HttpServletRequest 类型的对象。 - response 对象
response 对象是 HttpServletResponse 类型的对象。 - session 对象
session 对象是 HttpSession 类型的对象。只有在包含 session=“true” 的页面中才可以被使用。 - application 对象
application 对象是 ServletContext 类型的对象 - out 对象 字符输出流
out 对象是 JspWriter 类型的对象。 - config 对象
config 对象是 ServletConfig 类型的对象。 - pageContext 对象
pageContext 对象是 PageContext 类型的对象。作用是取得任何范围的参数,通过 它可以获取 JSP 页面的 out、request、reponse、session、application 等对象。pageContext 对象的创建和初始化都是由容器来完成的,在 JSP 页面中可以直接使用 pageContext 对象。 - page 对象
page 对象代表 JSP 本身。 - exception 对象
exception 对象的作用是显示异常信息,只有在包含 isErrorPage="true" 的页面中才可以被使用。
请求转发
什么是请求转发
请求转发是服务端的一种请求方式,相当于在服务端中直接请求某个资源
request.getRequestDispatcher("该jsp的名称.jsp").forword(request,response);
请求转发和重定向的区别
- 请求转发对于客户端浏览器而言是在一次请求与响应中完成,而重定向(需要客户端发起)是在两次请求两次响应中完成。
- 请求转发并不会改变客户端浏览器的地址栏中的内容(在服务端直接完成)。而重定向会改变客户端浏览器地
址栏中的内容。 - 请求转发可以使用 request 对象传递数据,而重定向不能使用 request 对象传递数据(因为request是浏览器发出的请求,请求结束request生命周期结束了,再次请求则是新的request对象)。
- 如果是处理的DML(添加修改删除)操作,建议使用重定向方式为客户端浏览器产生响应,可以解决表单重复提交现象。查询使用请求转发(请求转发地址栏不发生改变,因此提交数据表单
案例实现
- servlet
/**
* 需求:在 Servlet 中获取客户端浏览器所支持的语言,
* 并通过 JSP 页面将客户端浏览器所支持的语言响应给客户端浏览器。
* */
//配置servlet注解与url映射
@WebServlet("/language.do")
public class LanguageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String header =req.getHeader("Accept-language");
req.setAttribute("key",header);
req.getRequestDispatcher("/showMsg.jsp").forward(req,resp);
}
}
- jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
String value =(String)request.getAttribute("key");
%>
当前支持的语言:<%=value
%>
</body>
</html>
- 结果
jsp四大作用域对象
作用域:数据共享的范围,也就是说能够在多大的范围内邮箱
对象名称 | 作用范围 |
---|---|
application(ServletContext) | 整个应用都有效 |
session | 在当前会话中有效 |
request | 当前请求有效 |
paga(指jsp页面本身) | 当前页面有效 |
JSTL标签
JSTL(Java server pages standarded tag library,即 JSP 标准标签库)JSTL 标签是基于 JSP 页面的。这些标签可以插入在 JSP 代码中,本质上 JSTL 也是提前定义好的一组标签,这些标签封装了不同的功能,在页面上调用标签时,就等于调用了封装起来的功能。JSTL 的目标是 使 JSP 页面的可读性更强、简化 JSP 页面的设计、实现了代码复用、提高效率。
在 JSP2.0 版本后开始支持 JSTL 标签库。在使用 JSTL 标签库时需要在 JSP 中添加对应的 taglib 指令标签。
最常用的核心标签
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
使用该标签则需要进行相应的指令标签
EL表达式
EL(Expression Language)是一种表达式语言。是为了使 JSP 写起来更加简单,减少 java 代码,可以使得获取存储在 Java 对象中的数据变得非常简单。在 JSP2.0 版本后开始支持 EL 表达式。
语法结构
${表达式}
${对象.属性名}
EL表达式中操作符
EL表达式的隐含对象
表达式去除作用域中的值
- $
- $
- $
- ${applicationScope.name}
获取作用域属性中的数据时,也可以只写属性名,EL 表达式会按照 pageScope、 requestScope、sessionScope、applicationScope 的顺序查找该属性的值。$
JSTL标签库与表达式的使用
使用步骤
- 添加 jstl.jar 与 standard.jar
这里提供idea的导入方法
Intellij IDEA 添加jar包的三种方式(参考) - 在 Idea 中添加 JSTL 标签的约束文件(DTD)。
- 在 JSP 页面中添加 taglib 指令标签。
以核心标签为例:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
核心标签的使用
可以结合EL表达式使用
- <c:if>
标签判断表达式的值,如果表达式的值为 true 则执行其主体内容。 - <c:choose>, <c:when>, <c:otherwise>
<c:choose>标签与 Java switch 语句的功能一样,用于在众多选项中做出选择。switch 语句中有 case,而<c:choose>标签中对应有<c:when>,switch 语句中有 default, 而<c:choose>标签中有<c:otherwise>。
这三个标签不能单独出现 - <c:forEach>
迭代器,用于迭代集合。
varStatus:属性
current: 当前这次迭代的(集合中的)项
index: 当前这次迭代从 0 开始的迭代索引
count: 当前这次迭代从 1 开始的迭代计数
first: 用来表明当前这轮迭代是否为第一次迭代的标志 返回布尔类型
last: 用来表明当前这轮迭代是否为最后一次迭代的标志
begin: 属性值
end: 属性值
step:属性值
举例
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<c:if test="${1==1}">
执行了
</c:if>
<c:choose>
<c:when test="${2==1}">
when执行了
</c:when>
<c:otherwise>
otherwise执行了
</c:otherwise>
</c:choose>
<hr/>
<c:forEach begin="0" end="9" step="2" varStatus="a">
ForEach...${a.count},${a.first},${a.last},${a.current}<br/>
</c:forEach>
</body>
</html>
结果输出
上面代码中当<c:when test="${2==1}">时,会输出otherwise类似,java中的if.....else varStatus是循环状态名称.相应内容可以获得循环的相应状态
使用foreach案例
迭代List
创建 Users 对象,含有 userid,username 属性。
创建一个 Servlet,在 Servlet 中创建多个 Users 对象并放到 List 集合中,在 showUsers.jsp
的页面中显示所有的 Users 对象的信息。
创建User类
package pojo;
public class Users {
private Integer userId;
private String Username;
public Users() {
}
public Users(Integer userId, String username) {
this.userId = userId;
Username = username;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUsername() {
return Username;
}
public void setUsername(String username) {
Username = username;
}
}
创建Servlet
package com.hhxx.servlet;
import pojo.Users;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@WebServlet(urlPatterns = "/findUsers")
public class FindUsersServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<Users> list =new ArrayList<>();
Users users1 =new Users(1,"Lee");
Users users2 =new Users(2,"Jay");
list.add(users1);
list.add(users2);
//将属性存放在req
req.setAttribute("list",list);
//跳转的jsp位置
req.getRequestDispatcher("showUsers.jsp").forward(req,resp);
}
}
创建jsp(showUsers.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<table border="1" align="center">
<tr>
<th>用户ID</th>
<th>用户名</th>
</tr>
<c:forEach items="${requestScope.list}" var="a">
<tr>
<td>${a.userId}</td>
<td>${a.username}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
- 输出结果
- 通过请求定义的的值来传递属性,JSP中var的迭代元素变量名称可以随便取,servlet要进行web配置,jsp也需要进行导入标签配置
迭代Map
- uesrs类和上一致
- 创建Servlet
package com.hhxx.servlet;
import pojo.Users;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@WebServlet(urlPatterns = "/findUsers2")
public class FindUsers2servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Map<String, Users> map = new HashMap<>();
Users users1 =new Users(1,"Lee");
Users users2 =new Users(2,"Jay");
map.put("users1",users1);
map.put("users2",users2);
req.setAttribute("map",map);
req.getRequestDispatcher("showUser2.jsp").forward(req,resp);
}
}
- 创建jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<table border="2" >
<tr>
<td>Map的key</td>
<td>用户Id</td>
<td>用户名</td>
</tr>
<c:forEach items="${requestScope.map}" var="b">
<tr>
<td>${b.key}</td>
<td>${b.value.userId}</td>
<td>${b.value.username}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
与List相比不同之处在于:1.Map是无序的,2.Map是键-值(而我们目前的值包含2个userid,username)的数据,在jsp获取时需要注意
格式化标签使用
需配置文件
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
案例对日期和数字的格式化处理
java
package com.hhxx.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
@WebServlet(urlPatterns = "/format")
public class FormatServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("date",new Date());
req.setAttribute("balance",20210253.323);
req.getRequestDispatcher("format.jsp").forward(req,resp);
}
}
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<fmt:formatDate value="${date}" pattern="yyyy-MM-dd"/>
<fmt:formatNumber value="${requestScope.balance}" type="currency"/>
</body>
</html>
- 结果
简单理解MVC模式
什么MVC
- MVC 模式:Model、View、Controller 即模型、视图、控制器。是软件的一种架构模式 (Architecture pattern)。MVC 要实现的目标是将软件的用户界面和业务逻辑分离,可提高 代码可扩展性、可复用性、可维护性、以及灵活性。(不用组件做不同的事)
View(视图):用户的操作界面。如:html、jsp。 Model(模型):具体的业务模型与数据模型。如:service、dao、pojo。 Controller(控制):处理从视图层发送的请求,并选取模型层的业务模型完成响应的业务
实现,并产生响应。如:Servlet。
MVC模式与应用程序分层的区别
MVC 模式是一种软件的架构方式,而应用程序分层这是一种代码的组织方式。MVC 模式与应用程序分层的目标都是一致的:为了解耦和、提高代码复用性。
最后这句话,让我想起听过的一本书说的,编写代码的核心原则——ETC(容易变更)高内聚,低耦合 保证代码模块良好的设计,以及代码模块尽可能地复用,只需要一次修改,全部调用此模块的代码可以同步变更这里MVC其实也是有这样的一致认为。