JSP动态网页设计与JavaWeb编程

一 JSP

1.1 jsp介绍
为什么要引入jsp?
  	 html文件无法获取java程序中的数据,同时,如果使用Servlet来显示java数据又显得不太合理!
  	综上,需要一门技术,既可以显示页面,同时也可以获取java程序中的数据

什么是jsp
 	 jsp:java server page
  	简单理解为,它就是一个可以获取java数据的html文件。
1.2 jsp相关概念
jsp为什么是一个Servlet
  	jsp文件会转义成对应的java文件
  	比如:demo01.jsp转义成demo01_jsp.java,类demo01_jsp会继承于HttpJspPage,HttpJspPage又是Servlet子类,demo01.jsp就是Servlet
  	
jsp的执行流程
  	浏览器发起请求demo01.jsp
  	demo01.jsp就会转义生成对应demo01_jsp.java
  	在demo01_jsp类中,通过JspWriter类将demo01.jsp中的html标签作为响应正文响应给浏览器进行渲染显示!
1.3 jsp脚本
作用
	可以在页面上写java代码

分类
 	声明脚本:<%! java代码 %>	在jsp对应java类中,生成一个成员变量
  	片段脚本:<% java代码 %>	在jsp对应的java类的_jspService方法中,生成一个局部变量
  	输出脚本::<%= 变量值 %>	向浏览器输出内容,相当于response.getWriter().write()
1.3.1 普通脚本

<% java代码%>

Hello World!<br/>
  <%
    //jsp使用小脚本嵌入代码
    out.println("hi");
    System.out.println("hello");
  %>
  • 普通脚本可以使用所有java语法,除了定义函数
  • 脚步与脚本之间不可嵌套,脚步与html标签不可嵌套
1.3.2 声明脚本

<%! 定义变量、函数%>

<%! int i=0;%>
  <%! int a,b,c;%>
  <%! Object object = new Object();%>
  <%!
    //定义方法
    public void m1(){
      System.out.println("你好");
    }
  %>
  • 声明脚本声明的变量是全局变量
  • 声明脚本的内容必须在偶同脚本中调用
  • 如果声明脚本中的函数具有返回值,可以使用输出脚本调用<%= %>
1.3.3 输出脚本

<%= java表达式%>

<p>
      今天的日期是:<%=new java.util.Date()%>
    </p>

输出脚本可以输出带有返回值的函数
输出脚本没有“;”

1.4 jsp注释
jsp文件中,既可以有html代码,也可以有java代码
这就意味着,jsp文件中,既可以使用html注释,也可以使用java注释,同时还可以使用jsp注释
html注释	<!-- -->
	用来注释html代码
	会将注释内容生成到jsp对应的java文件中
	通过浏览器查看源代码可以看见
java注释	//
	用来注释java代码
	会将注释内容生成到jsp对应的java文件中
jsp注释	<%--  --%>
	用来注释html代码
	不会讲注释内容生成到jsp对应的java文件中
	注释内容不会发送至浏览器甚至不会被编译
	<p>
      今天的日期是:<%=new java.util.Date()%>
    </p>
  <%--jsp注释在网页中不会被显示--%>
  <!--html注释在网页中会显示-->
1.5 jsp指令

用于指示jsp执行某些操作 、用于指示jsp表现特定行为或效果

 <%@ 指令名称 属性名1="属性值1" 属性名2="属性值2" %>
1.5.1 include指令(了解)

用于将外部引入到jsp文件中

<%@ include file="top.jsp"%>
1.5.2 page指令
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" errorPage="error.jsp" %>
<%@ page isErrorPage="true" %>
contentType="text/html;charset=UTF-8"
	告诉浏览器应该以utf-8解码响应正文,告诉服务器应该以utf-8对响应正文进行编码

language="java"
  	设置jsp页面能够使用的语言,不动!

import="java.util.List" 
  	在当前jsp页面中导入List类

isELIgnored="false"
  	当前jsp页面不要忽略el表达式,默认就是不忽略

errorPage="error.jsp"
  	当前jsp页面发生异常,所要跳转到页面

isErrorPage="true"
  	标记当前jsp页面是否是一个错误页面,如果为true那么就可以使用jsp内置对象exception,否则不能使用
1.5.3 taglib指令

在当前jsp页面中导入jstl标签库

<%@taglib prefix="前缀" uri="路径" %>
  • 导入jstl标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
1.6 jsp内置对象

可以在jsp页面上直接使用的对象

内置对象名描述
page当前页面对象
java.lang.Object
pageContext当前页面上下文对
javax.servlet.jsp.PageContext
request请求对象
javax.servlet.http.HttpServletRequest
response响应对象
javax.servlet.http.HttpServletResponse
session会话对象
javax.servlet.http.HttpSession
configServletConfig对象
javax.servlet.ServletConfig
exception异常对象
java.lang.Throwable
applicationServletContext对象
javax.servlet.ServletContext
outJspWriter对象
javax.servlet.jsp.JspWriter

在jsp对应的java文件中,已经提前声明好了这些内置对象,所以可以直接使用

  • request、response、session
<%
//    String username = request.getParameter("username");
//    System.out.println(username);
//    response.getWriter().write(username);
//    session.setAttribute("msg","hello jsp");
    application.setAttribute("msg","hello jsp jsp");
%>
<%
//    String msg = (String) session.getAttribute("msg");
//    System.out.println(msg);
    String msg = (String) application.getAttribute("msg");
    System.out.println(msg);
%>
<%
    out.write("i am very happy");
%>
1.7 jsp中四大域对象

域对象:就是可以用来存储数据对象

jsp域对象
	request	代表整个请求链
	
  	session	整个会话
  	
  	application	整个web应用
  	
  	pageContext	代表page域,但是jsp中page它的类型是Object,所以操作page域我们使用的是
  				pageContext对象,page域就是指当前页面范围
1.7.1 pageContext域对象
作用
  	获取其他的内置对象
  	
  	操作域
    	操作page域
    	操作request、session、application
  • 获取其他的内置对象
    • 没有获取out内置对象
  <%
      pageContext.getPage();//获取内置对象page
      pageContext.getRequest();//获取内置对象request
      pageContext.getResponse();//获取内置对象response
      pageContext.getSession();//获取内置对象session
      pageContext.getServletContext();//获取application
      pageContext.getServletConfig();//config
      pageContext.getException();//exception
  %>
  • 操作page域
    • 作用范围只在当前页面
	<%
        //往pageContext域中存储了一个msg变量
        pageContext.setAttribute("msg" ,"hello page msg");
    %>
    
    <%
        //往pageContext域中存储了一个msg变量
        Object msg = pageContext.getAttribute("msg");
        System.out.println(msg);
    %>
  • 操作其他域
    • request域
    <%
        //定义变量的意义! 提高复用性! 提高可维护性!
        //String name : 参数名称
        //Object value : 参数值
        //int scope : 操作的域
        pageContext.setAttribute("msg1","hello page1",PageContext.REQUEST_SCOPE);
        //请求转发
        request.getRequestDispatcher("/demo06.jsp").forward(request,response);
    %>
    
    <%
        //变量msg1定义到_jspService方法中
        Object msg1 = request.getAttribute("msg1");
        System.out.println("msg1 : "+msg1);
    
        Object msg11 = pageContext.getAttribute("msg1", PageContext.REQUEST_SCOPE);
        System.out.println(msg11);
    %>
    • session域
    <%
        pageContext.setAttribute("msg2","hello page2",PageContext.SESSION_SCOPE);
    %>
    • application域
    <%
        pageContext.setAttribute("msg3","hello page3",PageContext.APPLICATION_SCOPE);
    %>

二 el表达式

2.1 el表达式介绍

el(expression language),是由jsp内置提供
el表达式用来替换jsp脚本

作用
  	向页面输出数据
  	获取web对象
格式	
	${表达式}

如果page指令中isELIgnored=“true”,jsp页面就不会解析执行el表达式,会原样显示

2.2 el获取域数据基本使用
  • 获取page域数据
  <%
  pageContext.setAttribute("msg1","hello page1");
  %>
  
  ${pageScope.msg1}
  • 获取request域数据
  <%
  request.setAttribute("msg1","hello page1");
  %>
  
  ${requestScope.msg1}
  • 获取session域数据
  <%
  session.setAttribute("msg1","hello page1");
  %>
  
  ${sessionScope.msg1}
  • 获取application域数据
  <%
  application.setAttribute("msg1","hello page1");
  %>
  
  ${applicationScope.msg1}
2.3 el获取复杂域数据
  • 获取数组
  <%
      //数组静态初始化
      String[] msgs = {"tom","steve","barry"};
      pageContext.setAttribute("msgs",msgs);
  %>
  <%--jsp输出脚本--%>
  <%=
      ((String[])pageContext.getAttribute("msgs"))[0]
  %>
  ${msgs[1]}
  • 获取List集合
  <%
      List<String> msgs1 = new ArrayList<>();
      msgs1.add("kate");
      msgs1.add("jay");
      request.setAttribute("msgs1",msgs1);
  %>
  
  <%=
      ((List<String>)request.getAttribute("msgs1")).get(0)
  %>
  
  ${msgs1[1]}
  • 获取map集合
  <%
      HashMap<String,Object> map = new HashMap<>();
      map.put("username","jerry");
      map.put("age",16);
      session.setAttribute("map",map);
  %>
  
  <%=
      ((HashMap<String,Object>)session.getAttribute("map")).get("username")
  %>
  ${map.age}
  • 获取java对象
  <%
      User user = new User();
      user.setId(1);
      user.setUsername("alex");
      user.setPassword("123456");
      application.setAttribute("user",user);
  %>
  <%=
      ((User)application.getAttribute("user")).getUsername()
  %>
  
  ${user.password}
2.4 el表达式执行运算
  • 算术运算
  +
  -
  *
  /:div
  %:mod
  • 关系运算
  > : gt
  >= : ge
  < : lt
  <= : le
  == : eq
  != : ne
  • 逻辑运算
  && : and
  || : or
  !  : not
  • 三元运算
${num1 gt num2 ? "num1大于num2" : "num1不大于num2"}
2.5 el表达式中web对象
  • 11个web对象
el表达式说明
pageScope
(常用)
是page域对象,获取pageContext域属性
requestScope
(常用)
获取request域属性
sessionScope
(常用)
获取session域属性
applicationScope
(常用)
获取application域属性
param对应参数,它是一个Map,其中key是参数,value是参数值,适用于单值的参数
相当于request.getParameter()
paramValues对应参数,她是一个Map,其中key是参数,value是多个参数值,适用于多值的参数
相当于request.getParameterValues()
header对应请求头,它是一个Map,其中key表示头名称,value是单个头值,适用于单值的请求头
获取单个请求头值
headerValues对应请求头,它是一个Map,其中key表示头名称,value是多个头值,适用于多值的请求头
获取一组请求头的值
initParam获取初始化参数,获取web.xml中内的参数
cookie
(常用)
用于获取cookie
Map<String,Cookie>,其中key是cookie的name,value是cookie对象
pageContext
(常用)
相当于pageContext对象,获取jsp九大内置对象
应用场景:获取当前项目路径
	${pageContext.request.contextPath}

三 jstl标签库

3.1 介绍

jstl (java standard tag libarary),jsp标签库,它是apache对el表达式的扩展
和el表达式结合使用,可以让功能更加强

3.1.1 环境准备
  • 导入jar包
    在这里插入图片描述
  • 在jsp页面导入jstl标签库
    • 使用taglib指令
   <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
3.2 jstl核心标签
3.2.1 set标签

向域对象(page域、request域、session域、application域)中存储数据

var:参数名称
scope:域
value:参数值
  <c:set var="msg" scope="request" value="hello jstl"></c:set>
  ${msg}
3.2.2 remove标签

移除域对象中的数据

var:参数名称
scope:域
  <c:remove var="msg" scope="request"></c:remove>
  ${msg}<br>
3.2.3 catch标签

捕获jsp页面的异常,相当于try…catch

var:声明异常对象名称,比如:var="e" ,变量e就可以接收异常对象
  <c:catch var="e">
      <%
          int num = 1 / 0;
      %>
  </c:catch>
  ${e}<br>
3.2.4 if标签

条件判断

test :编写条件
  <c:set var="num" value="2" scope="request"></c:set>
  <c:if test="${num == 1}">
      num 等于 1
  </c:if>
  
  <c:if test="${num != 1}">
      num 不等于 1
  </c:if>
3.2.5 forEach标签

遍历集合或数组

begin:开始
end:结束
step:步数
var:元素名称
items:集合/数组
varStatus:元素状态对象
	first:是否是第一个元素
	last:是否是最后一个元素
	current:当前元素
	index“:当前脚标
  <!-- 基本使用 -->
  <c:forEach begin="1" end="10" step="3" var="num">
      ${num}
  </c:forEach>
  
  <%
      List<String> strs  = new ArrayList<>();
      strs.add("aaa");
      strs.add("bbb");
      strs.add("ccc");
      request.setAttribute("strs",strs);
  %>
  <!-- 相当于普通for循环 -->
  <c:forEach begin="0" end="${strs.size() - 1}" step="1" var="i">
      ${strs[i]}
  </c:forEach>
  
  <!-- 相当于增强for循环 -->
  <c:forEach var="str" items="${strs}" varStatus="status">
  	${str}<br>
      ${status.current} -- ${status.index} -- ${status.first} -- ${status.last}<br>
  </c:forEach>
3.2.6 forToken标签

分割字符串

items:要分割的字符串
delims:分割的规则
var:分割产生的元素
  <%
      String msg1 = "aaa--bbb--ccc";
      request.setAttribute("msg1",msg1);
  %>
  
  <c:forTokens items="${msg1}" delims="--" var="sonMsg">
      ${sonMsg}
  </c:forTokens>
3.2.7 choose标签

<c:choose>标签与switch语句功能一样,用于在众多选项中做出选择

<c:choose>
	<c:when test="条件1">结果1</c:when>
	<c:when test="条件2">结果2</c:when>
	<c:when test="条件3">结果3</c:when>
	<c:otherwise>结果4</c:otherwise>
</c:choose>
3.2.8 ul标签

<c:ul>标签将URL格式化为一个字符串,然后存储在变量中
自动重写URL,var属性用于存储格式化后的URL

<c:ul value='${pageContext.request.contextPath}/xxxController' var="myurl"/>
3.3 jstl综合案例——显示商品信息
3.3.1 准备工作
  • 导入jar包
    在这里插入图片描述

  • ProductDao

  public class ProductDaoImpl implements ProductDao {
      @Override
      public List<Product> selectProductList() throws Exception {
          return new QueryRunner(JDBCUtils.getDataSource())
                  .query("select * from tb_product",
                          new BeanListHandler<Product>(Product.class));
      }
   }
  • ProductServlet
  @WebServlet(name = "ProductServlet" ,urlPatterns = "/selectProductList")
  public class ProductServlet extends HttpServlet {
  
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          ProductDao productDao = new ProductDaoImpl();
          try {
              List<Product> productList = productDao.selectProductList();
              System.out.println(productList);
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  
      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          doPost(request, response);
      }
  }
3.3.2 功能完成
  • productList.jsp
  <table border="1px" cellspacing="0px" cellpadding="10px" width="500px" height="200px">
      <tr>
          <td>ID</td>
          <td>名称</td>
          <td>单价</td>
          <td>数量</td>
          <td>小计</td>
      </tr>
      <%--循环之前,总价为0--%>
      <c:set var="total" value="0" scope="page"></c:set>
      <c:forEach items="${productList}" var="product">
          <%--forEach标签,循环一次就是一个小计!--%>
          <tr>
              <td>${product.id}</td>
              <td>${product.name}</td>
              <td>${product.price}</td>
              <td>${product.count}</td>
              <td>${product.price * product.count}</td>
          </tr>
          <c:set var="total" value="${total + product.price * product.count}" scope="page"></c:set>
      </c:forEach>
      <%--循环之后,计算出总价--%>
      <tr>
          <td colspan="5" align="right">
              总价:${total}元
          </td>
      </tr>
  
  </table>

四 jsp模式

分类
	model1模式	jsp+javaBean
	model2模式	jsp+javaBean+Servlet
4.1 model1模式

在这里插入图片描述

jsp
    处理请求
    业务处理
    操作数据库
    显示数据

javaBean
    封装数据
优点:开发简单
缺点:维护难,代码几乎都在jsp中
<%@ page import="org.apache.commons.dbutils.QueryRunner" %>
<%@ page import="util.JDBCUtils" %>
<%@ page import="org.apache.commons.dbutils.handlers.BeanListHandler" %>
<%@ page import="bean.Product" %>
<%@ page import="java.util.List" %>
<%@ page import="java.security.interfaces.RSAKey" %><%--
  Created by IntelliJ IDEA.
  User: EVA_01
  Date: 2020/4/28 0028
  Time: 15:13
  To 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" %>
<html>
<head>
    <title>jsp的model1模式</title>
</head>
<body>
<%
    //请求处理
    //业务处理
    //操作数据库
    List<Product> productList = new QueryRunner(JDBCUtils.getDataSource())
            .query("select * from tb_product", new BeanListHandler<Product>(Product.class));
    System.out.println(productList);
    pageContext.setAttribute("productList",productList);
//    request.getRequestDispatcher("/productList1.jsp").forward(request, response);
%>

<table border="1px" cellspacing="0px" cellpadding="10px" width="500px" height="200px">
    <tr>
        <td>ID</td>
        <td>名称</td>
        <td>单价</td>
        <td>数量</td>
        <td>小计</td>
    </tr>
    <%--循环之前,总价为0--%>
    <c:set var="total" value="0" scope="page"></c:set>
    <c:forEach items="${productList}" var="product">
        <%--forEach标签,循环一次就是一个小计!--%>
        <tr>
            <td>${product.id}</td>
            <td>${product.name}</td>
            <td>${product.price}</td>
            <td>${product.count}</td>
            <td>${product.price * product.count}</td>
        </tr>
        <c:set var="total" value="${total + product.price * product.count}" scope="page"></c:set>
    </c:forEach>
    <%--循环之后,计算出总价--%>
    <tr>
        <td colspan="5" align="right">
            总价:${total}</td>
    </tr>

</table>
</body>
</html>
4.2 model2模式

在这里插入图片描述

servlet
    处理请求
    业务处理
    操作数据库

jsp
    显示数据

javaBean
    封装数据
优缺点
	维护方便,开发人员各司其职,有利于我们进行分工操作
	比较适合开发一些比较复杂项目,因为它的很多组件可以重用。
	开发难度增大,对开发人员要求比较高

五 BeanUtils框架

可以将请求参数封装到java对象中

5.1 开发步骤
  • 导包
    在这里插入图片描述
        Map<String, String[]> map = request.getParameterMap();
        User user = new User();
        System.out.println(user);
        try {
            BeanUtils.populate(user,map);
            System.out.println(user);
        } catch (Exception e) {
            e.printStackTrace();
        }

页面上的name属性值要和java对象中的属性名一致

5.2 自定义BeanUtils框架
  • MyBeanUtils
public class MyBeanUtils {  
      /**
       * 将map集合中的请求参数值封装到对象t中
       * @param t
       * @param map : 键:参数名称;值:一组参数值。
       * @param <T>
       */
      public static<T> void populate(T t , Map<String,? extends Object> map ){
          Class<?> clazz = t.getClass();
          Field[] fields = clazz.getDeclaredFields();
          for (Field field : fields) {
              String fieldName = field.getName();
              String methodName = "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
              System.out.println(methodName);
              //获取对应的set方法
              try {
                  Class<?> type = field.getType();
                  Method method = clazz.getMethod(methodName, type);
                  if (null != method) {
                      //第二个参数:请求参数的值
                      //id、username、password、age
                      Object object = map.get(fieldName);
                      if (null != object) {
                          String[] strs = (String[]) object;
                          if (type.getName().equals("java.lang.Integer")) {
                              method.invoke(t,Integer.parseInt(strs[0]));
                          } else {
                              method.invoke(t,strs[0]);
                          }
                      }
                  }
              } catch (Exception e) {
  //                e.printStackTrace();
                  throw new MyNoSuchMethodException("field " + fieldName + " there is no setter method!!!");
              }
          }
  
      }
  
  }
  • MyNoSuchMethodException
  public class MyNoSuchMethodException extends RuntimeException{
  
      public MyNoSuchMethodException() {
      }
  
      public MyNoSuchMethodException(String message) {
          super(message);
      }
  
      public MyNoSuchMethodException(String message, Throwable cause) {
          super(message, cause);
      }
  
      public MyNoSuchMethodException(Throwable cause) {
          super(cause);
      }
  
      public MyNoSuchMethodException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
          super(message, cause, enableSuppression, writableStackTrace);
      }
  }


六 mvc设计模式

它是一种软件设计典范,用一种业务逻辑,数据,界面分离的方式来组织代码,将业务逻辑聚集 到一个部件中,方便程序的重复使用,提高我们的开发效率


jsp的model2模式是mvc设计模式的一种

  • 业务分工
m:	model	数据封装
v:	view	显示页面,即视图层 数据的显示 jsp
c:	controller	控制层,用于业务处理,而业务处理包含:处理请求、业务逻辑、操作数据库
存在的弊端
    c中的代码太多,职责不单一!需要使用到三层结构
  • 三层结构
web层:处理请求
service层:业务逻辑,业务层
dao层:操作数据库,持久层

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值