07 JSP

发布于:2024-07-26 ⋅ 阅读:(236) ⋅ 点赞:(0)

JSP

1、JSP 概述

  • JSP(全称:Java Server Pages):Java 服务端页面
    (1)是一种动态的网页技术
    (2)既可以定义 HTML、JS、CSS等静态内容,还可以定义 Java代码的动态内容
    (3)JSP = HTML + Java

  • JSP 快速入门

    • (1)搭建环境
      创建一个maven的 web 项目
      pom.xml 文件内容如下:

      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
      
          <groupId>org.example</groupId>
          <artifactId>jsp-demo</artifactId>
          <version>1.0-SNAPSHOT</version>
          <packaging>war</packaging>
      
          <properties>
              <maven.compiler.source>8</maven.compiler.source>
              <maven.compiler.target>8</maven.compiler.target>
          </properties>
      
          <dependencies>
            <dependency>
                  <groupId>javax.servlet</groupId>
                  <artifactId>javax.servlet-api</artifactId>
                  <version>3.1.0</version>
                  <scope>provided</scope>
              </dependency>
          </dependencies>
      
          <build>
              <plugins>
                  <plugin>
                      <groupId>org.apache.tomcat.maven</groupId>
                      <artifactId>tomcat7-maven-plugin</artifactId>
                      <version>2.2</version>
                  </plugin>
              </plugins>
          </build>
      </project>
      
      • (2)导入 JSP 依赖
      <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>jsp-api</artifactId>
          <version>2.2</version>
          <scope>provided</scope>
      </dependency>
      

      scope 必须设置为 provided, 因为tomcat 中有这个jar包了,不能将这个依赖打包进工程中

      • (3)创建 jsp 页面

      • 编写代码
        hello.jsp 页面中书写 HTML 标签和 Java 代码,如下

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head>
          <title>Title</title>
      </head>
      <body>
          <h1>hello jsp</h1>
      
          <%
              System.out.println("hello,jsp~");
          %>
      </body>
      </html>
      
      • (5)测试
  • JSP 原理:JSP 本质上就是一个 Servlet

    访问jsp时的流程:

    1. 浏览器第一次访问 hello.jsp 页面
    2. tomcat 会将 hello.jsp 转换为名为 hello_jsp.java 的一个 Servlet
    3. tomcat 再将转换的 servlet 编译成字节码文件 hello_jsp.class
    4. tomcat 会执行该字节码文件,向外提供服务

2、JSP 脚本和缺点

  1. JSP 脚本分类
    JSP 脚本有如下三个分类:

    • <%…%>:内容会直接放到_jspService()方法之中
    • <%=…%>:内容会放到out.print()中,作为out.print()的参数
    • <%!…%>:内容会放到_jspService()方法之外,被类直接包含
  2. JSP 缺点
    由于 JSP页面内,既可以定义 HTML 标签,又可以定义 Java代码,造成了以下问题:

    • 书写麻烦:特别是复杂的页面既要写 HTML 标签,还要写 Java 代码
    • 阅读麻烦
    • 复杂度高:运行需要依赖于各种环境,JRE,JSP容器,JavaEE…
    • 占内存和磁盘:JSP会自动生成.java和.class文件占磁盘,运行的是.class文件占内存
    • 调试困难:出错后,需要找到自动生成的.java文件进行调试
    • 不利于团队协作:前端人员不会 Java,后端人员不精 HTML
  3. 技术的发展
    JSP 已逐渐退出历史舞台,使用 HTML + Ajax 来替代

    1. 第一阶段:使用 servlet 即实现逻辑代码编写,也对页面进行拼接

    2. 第二阶段:随着技术的发展,出现了 JSP ,人们发现 JSP 使用起来比 Servlet 方便很多,但是还是要在 JSP 中嵌套 Java 代码,也不利于后期的维护

    3. 第三阶段:使用 Servlet 进行逻辑代码开发,而使用 JSP 进行数据展示

    4. 第四阶段:使用 servlet 进行后端逻辑代码开发,而使用 HTML 进行数据展示,由 ajax进行动态数据展示

3、EL 表达式

  1. 概述

    • EL(全称Expression Language )表达式语言

    • 用于简化 JSP 页面内的 Java 代码

    • EL 表达式的主要作用是 获取数据

    • 从域对象中获取数据,然后将数据展示在页面上

    • 语法:${expression}

      例如:${brands} 就是获取域中存储的 key 为 brands 的数据

  2. 代码演示

    • 定义servlet,在 servlet 中封装一些数据并存储到 request 域对象中并转发到 el-demo.jsp 页面

      @WebServlet("/demo1")
      public class ServletDemo1 extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //1. 准备数据
              List<Brand> brands = new ArrayList<Brand>();
              brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));
              brands.add(new Brand(2,"优衣库","优衣库",200,"优衣库,服适人生",0));
              brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));
      
              //2. 存储到request域中
              request.setAttribute("brands",brands);
      
              //3. 转发到 el-demo.jsp
              request.getRequestDispatcher("/el-demo.jsp").forward(request,response);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
    • el-demo.jsp 中通过 EL表达式 获取数据

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <html>
      <head>
          <title>Title</title>
      </head>
      <body>
          ${brands}
      </body>
      </html>
      
    • 在浏览器的地址栏输入 http://localhost:8080/jsp-demo/demo1 ,页面效果如下:

  3. 域对象
    JavaWeb中有四大域对象

    • page:当前页面有效
    • request:当前请求有效
    • session:当前会话有效
    • application:当前应用有效

      el 表达式获取数据,会依次从这4个域中寻找,直到找到为止

4、JSTL标签

  1. 概述
    JSP标准标签库(Jsp Standarded Tag Library) ,使用标签取代JSP页面上的Java代码

  2. JSTL 使用步骤:

    • 导入坐标
      <dependency>
          <groupId>jstl</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
      </dependency>
      <dependency>
          <groupId>taglibs</groupId>
          <artifactId>standard</artifactId>
          <version>1.1.2</version>
      </dependency>
      
    • 在JSP页面上引入JSTL标签库
      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
      
    • 使用标签
  3. if 标签
    <c:if>:相当于 if 判断,属性:test,用于定义条件表达式

    <c:if test="${flag == 1}"></c:if>
    <c:if test="${flag == 2}"></c:if>
    
  4. forEach 标签
    <c:forEach>:相当于 for 循环。java中有增强for循环和普通for循环,JSTL 中的 <c:forEach> 也有两种用法

    • 用法一
      • items:被遍历的容器
      • var:遍历产生的临时变量
      • varStatus:遍历状态对象
      <c:forEach items="${brands}" var="brand">    
      	<tr align="center">        
      		<td>${brand.id}</td>        
      		<td>${brand.brandName}</td>        
      		<td>${brand.companyName}</td>       
      		<td>${brand.description}</td>    
      	</tr>
      </c:forEach>
      
    • 用法二
      • begin:开始数
      • end:结束数
      • step:步长
      <c:forEach begin="0" end="10" step="1" var="i">
          ${i}
      </c:forEach>
      

5、MVC模式和三层架构

  1. MVC模式
    MVC 是一种分层开发的模式,其中:

    • M:Model,业务模型,处理业务
    • V:View,视图,界面展示
    • C:Controller,控制器,处理请求,调用模型和视图

      控制器(serlvlet)用来接收浏览器发送过来的请求,控制器调用模型(JavaBean)来获取数据,比如从数据库查询数据;控制器获取到数据后再交由视图(JSP)进行数据展示
    • MVC 好处:
      • 职责单一,互不影响。每个角色做它自己的事,各司其职。
      • 有利于分工协作。
      • 有利于组件重用
  2. 三层架构

    • 数据访问层:对数据库的CRUD基本操作

    • 业务逻辑层:对业务逻辑进行封装,组合数据访问层层中基本功能,形成复杂的业务逻辑功能。例如 注册业务功能 ,我们会先调用 数据访问层selectByName() 方法判断该用户名是否存在,如果不存在再调用 数据访问层insert() 方法进行数据的添加操作

    • 表现层:接收请求,封装数据,调用业务逻辑层,响应数据

    • 三层架构的每一层都有特有的包名称:

      • 表现层: com.itheima.controller 或者 com.itheima.web
      • 业务逻辑层:com.itheima.service
      • 数据访问层:com.itheima.dao 或者 com.itheima.mapper
  3. MVC 和 三层架构
    三层架构 是对 MVC 模式 实现架构的思想

6、案例

  1. 需求:完成品牌数据的增删改查操作

  2. 环境准备

    • 创建新的模块 brand_demo,引入坐标
    • 创建三层架构的包结构
    • 数据库表 tb_brand
    • 实体类 Brand
    • MyBatis 基础环境
      • Mybatis-config.xml
      • BrandMapper.xml
      • BrandMapper接口
    • 编写工具类
  3. 查询所有

    • (1)编写BrandMapper
      mapper 包下创建创建 BrandMapper 接口,在接口中定义 selectAll() 方法

      @Select("select * from tb_brand")
      List<Brand> selectAll();
      
    • (2) 编写BrandService

      public class BrandService {
          SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();
      
          /**
           * 查询所有
           * @return
           */
          public List<Brand> selectAll(){
              //调用BrandMapper.selectAll()
      
              //2. 获取SqlSession
              SqlSession sqlSession = factory.openSession();
              //3. 获取BrandMapper
              BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
      
              //4. 调用方法
              List<Brand> brands = mapper.selectAll();
      
              sqlSession.close();
      
              return brands;
          }
      }
      
    • (3) 编写Servlet
      web 包下创建名为 SelectAllServletservlet,该 servlet 的逻辑如下:

      • 调用 BrandServiceselectAll() 方法进行业务逻辑处理,并接收返回的结果
      • 将上一步返回的结果存储到 request 域对象中
      • 跳转到 brand.jsp 页面进行数据的展示
      @WebServlet("/selectAllServlet")
      public class SelectAllServlet extends HttpServlet {
          private  BrandService service = new BrandService();
      
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      
              //1. 调用BrandService完成查询
              List<Brand> brands = service.selectAll();
              //2. 存入request域中
              request.setAttribute("brands",brands);
              //3. 转发到brand.jsp
              request.getRequestDispatcher("/brand.jsp").forward(request,response);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
    • (4)编写brand.jsp页面

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
      <hr>
      <table border="1" cellspacing="0" width="80%">
          <tr>
              <th>序号</th>
              <th>品牌名称</th>
              <th>企业名称</th>
              <th>排序</th>
              <th>品牌介绍</th>
              <th>状态</th>
              <th>操作</th>
          </tr>
      
          <c:forEach items="${brands}" var="brand" varStatus="status">
              <tr align="center">
                  <%--<td>${brand.id}</td>--%>
                  <td>${status.count}</td>
                  <td>${brand.brandName}</td>
                  <td>${brand.companyName}</td>
                  <td>${brand.ordered}</td>
                  <td>${brand.description}</td>
                  <c:if test="${brand.status == 1}">
                      <td>启用</td>
                  </c:if>
                  <c:if test="${brand.status != 1}">
                      <td>禁用</td>
                  </c:if>
                  <td><a href="/brand-demo/selectByIdServlet?id=${brand.id}">修改</a> <a href="#">删除</a></td>
              </tr>
          </c:forEach>
      </table>
      </body>
      </html>
      
    • (5)测试

      使用 resultMap 标签定义映射关系

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="com.itheima.mapper.BrandMapper">
      
          <resultMap id="brandResultMap" type="brand">
              <result column="brand_name" property="brandName"></result>
              <result column="company_name" property="companyName"></result>
          </resultMap>
      </mapper>
      

      并且在 BrandMapper 接口中的 selectAll() 上使用 @ResuleMap 注解指定使用该映射

      /**
        * 查询所有
        * @return
        */
      @Select("select * from tb_brand")
      @ResultMap("brandResultMap")
      List<Brand> selectAll();
      

  4. 添加

    • (1)编写BrandMapper方法
      BrandMapper 接口,在接口中定义 add(Brand brand) 方法

      @Insert("insert into tb_brand values(null,#{brandName},#{companyName},#{ordered},#{description},#{status})")
      void add(Brand brand);
      
    • (2)编写BrandService方法
      BrandService 类中定义添加品牌数据方法 add(Brand brand)

      public void add(Brand brand){
      
              //2. 获取SqlSession
              SqlSession sqlSession = factory.openSession();
              //3. 获取BrandMapper
              BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
      
              //4. 调用方法
              mapper.add(brand);
      
              //提交事务
              sqlSession.commit();
              //释放资源
              sqlSession.close();
          }
      
    • (3)编写servlet
      web 包下创建 AddServletservlet,该 servlet 的逻辑如下:

      • 设置处理post请求乱码的字符集
      • 接收客户端提交的数据
      • 将接收到的数据封装到 Brand 对象中
      • 调用 BrandServiceadd() 方法进行添加的业务逻辑处理
      • 跳转到 selectAllServlet 资源重新查询数据
      @WebServlet("/addServlet")
      public class AddServlet extends HttpServlet {
          private BrandService service = new BrandService();
      
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      
              //处理POST请求的乱码问题
              request.setCharacterEncoding("utf-8");
      
              //1. 接收表单提交的数据,封装为一个Brand对象
              String brandName = request.getParameter("brandName");
              String companyName = request.getParameter("companyName");
              String ordered = request.getParameter("ordered");
              String description = request.getParameter("description");
              String status = request.getParameter("status");
      
              //封装为一个Brand对象
              Brand brand = new Brand();
              brand.setBrandName(brandName);
              brand.setCompanyName(companyName);
              brand.setOrdered(Integer.parseInt(ordered));
              brand.setDescription(description);
              brand.setStatus(Integer.parseInt(status));
      
              //2. 调用service 完成添加
              service.add(brand);
      
              //3. 转发到查询所有Servlet
              request.getRequestDispatcher("/selectAllServlet").forward(request,response);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
    • (4)编写addBrand.jsp页面

      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <!DOCTYPE html>
      <html lang="en">
      
      <head>
          <meta charset="UTF-8">
          <title>添加品牌</title>
      </head>
      <body>
      <h3>添加品牌</h3>
      <form action="/brand-demo/addServlet" method="post">
          品牌名称:<input name="brandName"><br>
          企业名称:<input name="companyName"><br>
          排序:<input name="ordered"><br>
          描述信息:<textarea rows="5" cols="20" name="description"></textarea><br>
          状态:
          <input type="radio" name="status" value="0">禁用
          <input type="radio" name="status" value="1">启用<br>
      
          <input type="submit" value="提交">
      </form>
      </body>
      </html>
      
    • (5)修改brand.jsp页面
      添加 新增 按钮

      <input type="button" value="新增" id="add"><br>
      

      并给该按钮绑定单击事件,当点击了该按钮需要跳转到 brand.jsp 添加品牌数据的页面

      <script>
          document.getElementById("add").onclick = function (){
              location.href = "/brand-demo/addBrand.jsp";
          }
      </script>
      
    • (6) 测试

  5. 修改 - 回显数据

    • (1)编写BrandMapper方法
      BrandMapper 接口,在接口中定义 selectById(int id) 方法

       @Select("select * from tb_brand where id = #{id}")
          @ResultMap("brandResultMap")
          Brand selectById(int id);
      
    • (2)编写BrandService方法
      BrandService 类中定义根据id查询数据方法 selectById(int id)

      public Brand selectById(int id){
              //调用BrandMapper.selectAll()
              //2. 获取SqlSession
              SqlSession sqlSession = factory.openSession();
              //3. 获取BrandMapper
              BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
              //4. 调用方法
              Brand brand = mapper.selectById(id);
              sqlSession.close();
              return brand;
          }
      
    • (3)编写servlet
      web 包下创建 SelectByIdServletservlet,该 servlet 的逻辑如下

      • 获取请求数据 id
      • 调用 BrandServiceselectById() 方法进行数据查询的业务逻辑
      • 将查询到的数据存储到 request 域对象中
      • 跳转到 update.jsp 页面进行数据真实
      @WebServlet("/selectByIdServlet")
      public class SelectByIdServlet extends HttpServlet {
          private  BrandService service = new BrandService();
      
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              //1. 接收id
              String id = request.getParameter("id");
              //2. 调用service查询
              Brand brand = service.selectById(Integer.parseInt(id));
              //3. 存储到request中
              request.setAttribute("brand",brand);
              //4. 转发到update.jsp
              request.getRequestDispatcher("/update.jsp").forward(request,response);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
    • (4)编写update.jsp页面
      拷贝 addBrand.jsp 页面,改名为 update.jsp 并做出以下修改:

      • title 标签内容改为 修改品牌
      • form 标签的 action 属性值改为 /brand-demo/updateServlet
      • input 标签要进行数据回显,需要设置 value 属性
      • textarea 标签要进行数据回显,需要在标签体中使用 EL表达式
      • 单选框使用 if 标签需要判断 brand.status 的值是 1 还是 0 在指定的单选框上使用 checked 属性,表示被选中状态
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>修改品牌</title>
      </head>
      <body>
      <h3>修改品牌</h3>
      <form action="/brand-demo/updateServlet" method="post">
      
          品牌名称:<input name="brandName" value="${brand.brandName}"><br>
          企业名称:<input name="companyName" value="${brand.companyName}"><br>
          排序:<input name="ordered" value="${brand.ordered}"><br>
          描述信息:<textarea rows="5" cols="20" name="description">${brand.description} </textarea><br>
          状态:
          <c:if test="${brand.status == 0}">
              <input type="radio" name="status" value="0" checked>禁用
              <input type="radio" name="status" value="1">启用<br>
          </c:if>
      
          <c:if test="${brand.status == 1}">
              <input type="radio" name="status" value="0" >禁用
              <input type="radio" name="status" value="1" checked>启用<br>
          </c:if>
      
          <input type="submit" value="提交">
      </form>
      </body>
      </html>
      
    • (5)测试

  6. 修改 - 修改数据

    • (1)编写BrandMapper方法
      BrandMapper 接口,在接口中定义 update(Brand brand) 方法

      @Update("update tb_brand set brand_name = #{brandName},company_name = #{companyName},ordered = #{ordered},description = #{description},status = #{status} where id = #{id}")
      void update(Brand brand);
      
    • (2)编写BrandService方法
      BrandService 类中定义根据id查询数据方法 update(Brand brand)

      public void update(Brand brand){
              //2. 获取SqlSession
              SqlSession sqlSession = factory.openSession();
              //3. 获取BrandMapper
              BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
              //4. 调用方法
              mapper.update(brand);
              //提交事务
              sqlSession.commit();
              //释放资源
              sqlSession.close();
          }
      
    • (3)编写servlet
      web 包下创建 AddServletservlet,该 servlet 的逻辑如下:

      • 设置处理post请求乱码的字符集
      • 接收客户端提交的数据
      • 将接收到的数据封装到 Brand 对象中
      • 调用 BrandServiceupdate() 方法进行添加的业务逻辑处理
      • 跳转到 selectAllServlet 资源重新查询数据
      @WebServlet("/updateServlet")
      public class UpdateServlet extends HttpServlet {
          private BrandService service = new BrandService();
      
          @Override
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      
              //处理POST请求的乱码问题
              request.setCharacterEncoding("utf-8");
              //1. 接收表单提交的数据,封装为一个Brand对象
              String id = request.getParameter("id");
              String brandName = request.getParameter("brandName");
              String companyName = request.getParameter("companyName");
              String ordered = request.getParameter("ordered");
              String description = request.getParameter("description");
              String status = request.getParameter("status");
      
              //封装为一个Brand对象
              Brand brand = new Brand();
              brand.setId(Integer.parseInt(id));
              brand.setBrandName(brandName);
              brand.setCompanyName(companyName);
              brand.setOrdered(Integer.parseInt(ordered));
              brand.setDescription(description);
              brand.setStatus(Integer.parseInt(status));
      
              //2. 调用service 完成修改
              service.update(brand);
      
              //3. 转发到查询所有Servlet
              request.getRequestDispatcher("/selectAllServlet").forward(request,response);
          }
      
          @Override
          protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              this.doGet(request, response);
          }
      }
      
    • (4)修改update.jsp
      update.jsp 页面的表单中添加如下代码:

      <%--隐藏域,提交id--%>
      <input type="hidden" name="id" value="${brand.id}">
      
    • (5)测试


网站公告

今日签到

点亮在社区的每一天
去签到