JSP快速上手与MVC模式和三层架构的知识点总结+综合案例

阅读提示:

1、 JSP概述

  • JSP(全称:Java Server Pages):Java 服务端页面
  • JSP = HTML + Java
  • 示例

        Title

        JSP,Hello World

2、JSP快速入门

2.1 环境和依赖

  • 创建Maven-webapp项目: pom.xml

    4.0.0

    priv.dandelion
    day10JSP
    1.0-SNAPSHOT
    war

        8
        8

            junit
            junit
            4.11
            test

            javax.servlet
            javax.servlet-api
            3.1.0

                org.apache.tomcat.maven
                tomcat7-maven-plugin
                2.2

  • 导入JSP依赖

    javax.servlet.jsp
    jsp-api
    2.2
    provided

2.2 编码

  • 测试代码

    Title

    JSP, hello

  • 访问
// 访问后页面跳转且控制台有输出
http://localhost:8080/day10JSP/hello.jsp

3、JSP原理

  • JSP的访问流程
  • 浏览器第一次访问 hello.jsp 页面
  • tomcat 会将 hello.jsp 转换为名为 hello_jsp.java 的一个 Servlet
  • tomcat 再将转换的 servlet 编译成字节码文件 hello_jsp.class
  • tomcat 会执行该字节码文件,向外提供服务
  • Servlet生成位置
  • 项目路径\target\tomcat\work\Tomcat\localhost\jsp-demo\org\apache\jsp目录
  • JSP间接继承 HttpServlet,其本质上是一个Servlet,其中HTML代码改写为 out.write("HTML代码")

4、JSP脚本

4.1 JSP脚本

4.1.1 脚本分类

*
*

4.1.2 脚本演示

*


// 转换的_jsp.java文件中为
System.out.println("hello,jsp~");
int i = 3;

*


// 转换的_jsp.java文件中为
out.write("hello");
out.write(i);

*


// 转换的_jsp.java文件中为
// 位于成员方法和成员变量位置
void  show(){}
String name = "zhangsan";

4.2 案例

4.2.1 实现

  • HTML代码和Java代码脚本

    Title

            序号
            品牌名称
            企业名称
            排序
            品牌介绍
            状态
            操作

            1
            三只松鼠
            三只松鼠
            100
            三只松鼠,好吃不上火
            启用
            修改 删除

            2
            优衣库
            优衣库
            10
            优衣库,服适人生
            禁用

            修改 删除

            3
            小米
            小米科技有限公司
            1000
            为发烧而生
            启用

            修改 删除

 brands = new ArrayList();
    brands.add(new Brand(1,"三只松鼠","三只松鼠",100,"三只松鼠,好吃不上火",1));
    brands.add(new Brand(2,"优衣库","优衣库",200,"优衣库,服适人生",0));
    brands.add(new Brand(3,"小米","小米科技有限公司",1000,"为发烧而生",1));
%>

注意:脚本中的类需要导包,使用方式见4.2.2成品代码
* 将Java代码和HTML代码进行合并,使用循环和脚本进行动态数据展示,见4.2.2成品代码

4.2.2 成品代码

  • 改进后代码

 brands = new ArrayList();
    brands.add(new Brand(1, "三只松鼠", "三只松鼠", 100, "三只松鼠,好吃不上火", 1));
    brands.add(new Brand(2, "优衣库", "优衣库", 200, "优衣库,服适人生", 0));
    brands.add(new Brand(3, "小米", "小米科技有限公司", 1000, "为发烧而生", 1));

%>

    Title

        序号
        品牌名称
        企业名称
        排序
        品牌介绍
        状态
        操作

            修改
            删除

4.3 JSP的缺点与改进

4.3.1 JSP的缺点

  • 书写麻烦:特别是复杂的页面 既要写 HTML 标签,还要写 Java 代码
  • 阅读麻烦 上面案例的代码,相信你后期再看这段代码时还需要花费很长的时间去梳理
  • 复杂度高:运行需要依赖于各种环境,JRE,JSP容器,JavaEE…

  • 占内存和磁盘:JSP会自动生成.java和.class文件占磁盘,运行的是.class文件占内存

  • 调试困难:出错后,需要找到自动生成的.java文件进行调试
  • 不利于团队协作:前端人员不会 Java,后端人员不精 HTML,如果页面布局发生变化,前端工程师对静态页面进行修改,然后再交给后端工程师,由后端工程师再将该页面改为 JSP 页面

由于上述的问题, JSP 已逐渐退出历史舞台,以后开发更多的是使用 HTML + Ajax 来替代。Ajax 是我们后续会重点学习的技术。有个这个技术后,前端工程师负责前端页面开发,而后端工程师只负责前端代码开发。
下来对技术的发展进行简单的说明

4.3.2 JSP的发展

  1. 第一阶段:使用 servlet 即实现逻辑代码编写,也对页面进行拼接。这种模式我们之前也接触过
  2. 第二阶段:随着技术的发展,出现了 JSP ,人们发现 JSP 使用起来比 Servlet 方便很多,但是还是要在 JSP 中嵌套 Java 代码,也不利于后期的维护
  3. 第三阶段:使用 Servlet 进行逻辑代码开发,而使用 JSP 进行数据展示
  4. 第四阶段:使用 servlet 进行后端逻辑代码开发,而使用 HTML 进行数据展示。而这里面就存在问题, HTML 是静态页面,怎么进行动态数据展示呢?这就是 ajax 的作用了。

5、EL表达式

5.1 概述

  • EL(全称Expression Language )表达式语言,用于简化 JSP 页面内的 Java 代码。
  • EL 表达式的主要作用是 获取数据。其实就是从域对象中获取数据,然后将数据展示在页面上。
  • 而 EL 表达式的语法也比较简单, ${expression} 。例如: ${brands} 就是获取域中存储的 key 为 brands 的数据。

5.2 代码演示

  • 定义 Servlet,封装数据并存储到Request域对象中并转发到 el-demo.jsp页面
@WebServlet("/demo1")
public class ServletDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 准备数据
        List brands = new ArrayList();
        brands.add(new Brand(1, "三只松鼠", "三只松鼠", 100, "三只松鼠,好吃不上火", 1));
        brands.add(new Brand(2, "优衣库", "优衣库", 200, "优衣库,服适人生", 0));
        brands.add(new Brand(3, "小米", "小米科技有限公司", 1000, "为发烧而生", 1));
        // 存储到request域中,参数为key-value
        request.setAttribute("brands", brands);
        // 转发到 el-demo.jsp
        request.getRequestDispatcher("/el-demo.jsp").forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

  • el-demo.jsp 中通过 EL表达式 获取数据

    使用EL表达式时,如果取不到数据,可能是因为JSP忽略了EL表达式,解决方式如下:

  • 在JSP中添加指令 <%@ page iselignored="false" %><!--%@-->

    Title

    ${brands}

5.3 域对象

EL表达式获取数据会依次从这四个域中寻找,直到找到为止(作用范围小的域优先级高)

  • JavaWeb中的四大域对象
  • page:当前页面有效
  • request:当前请求有效(一次请求的多个资源间有效)
  • session:当前会话有效
  • application:当前应用有效
    JSP快速上手与MVC模式和三层架构的知识点总结+综合案例

6、JSTL标签

6.1 概述

  • 引入JSTL
  • 导入依赖坐标

    jstl
    jstl
    1.2

    taglibs
    standard
    1.1.2

  • 使用指令在JSP中引入JSTL标签库

  • JSTL示例

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


    男

    女

  • JSTL标签标签 描述 <c out></c> 用于在JSP中显示数据,类似

6.2 if 标签

  • 示例

    注意: c if 标签的 test 中如果使用到 EL&#x8868;&#x8FBE;&#x5F0F;,则将的判断过程也写入到EL表达式中才能完成判断

  • 正确: <c:if test="${statusFlag == 1}"></c:if>
  • 错误: <c:if test="${statusFlag} == 1"></c:if>

    Title

        显示

        启用

        禁用

  • 其对应Servlet
@WebServlet("/demo2")
public class ServletDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 准备数据
        List brands = new ArrayList();
        brands.add(new Brand(1, "三只松鼠", "三只松鼠", 100, "三只松鼠,好吃不上火", 1));
        brands.add(new Brand(2, "优衣库", "优衣库", 200, "优衣库,服适人生", 0));
        brands.add(new Brand(3, "小米", "小米科技有限公司", 1000, "为发烧而生", 1));
        // 存储到request域中
        request.setAttribute("brands", brands);
        request.setAttribute("statusFlag", 1);

        System.out.println("开始转发");

        // 转发到 jstl-if.jsp
        request.getRequestDispatcher("/jstl-if.jsp").forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

6.3 forEach 标签

  • 示例一:增强 for 循环
  • 属性说明
    • items:被遍历的容器
    • var:遍历产生的临时变量名
    • varStatus:遍历状态对象

    Title

        序号
        品牌名称
        企业名称
        排序
        品牌介绍
        状态
        操作

            ${brand.id}--%>
            ${status.count}
            ${brand.name}
            ${brand.company}
            ${brand.order}
            ${brand.description}

                启用

                禁用

            修改 删除

  • 示例二:普通 for 循环

    begin:开始数 end:结束数 step:步长 var:循环变量名


    ${i}

7、MVC和三层架构

7.1 MVC模式

  • 概念
  • M:Model,业务模型,处理业务
  • V:View,视图,界面展示
  • C:Controller,控制器,处理请求,调用模型和视图
    JSP快速上手与MVC模式和三层架构的知识点总结+综合案例
  • 优势
  • 职责单一,互不影响。每个角色做它自己的事,各司其职。
  • 有利于分工协作。
  • 有利于组件重用

7.2 三层架构

三层架构是将我们的项目分成了三个层面,分别是 &#x8868;&#x73B0;&#x5C42;(表示层)、 &#x4E1A;&#x52A1;&#x903B;&#x8F91;&#x5C42;&#x6570;&#x636E;&#x8BBF;&#x95EE;&#x5C42;&#xFF08;&#x6301;&#x4E45;&#x5C42;&#xFF09;

  • 概念
  • 数据访问层:对数据库的CRUD基本操作
  • 业务逻辑层:对业务逻辑进行封装,组合数据访问层层中基本功能,形成复杂的业务逻辑功能。例如 &#x6CE8;&#x518C;&#x4E1A;&#x52A1;&#x529F;&#x80FD; ,我们会先调用 &#x6570;&#x636E;&#x8BBF;&#x95EE;&#x5C42;selectByName() 方法判断该用户名是否存在,如果不存在再调用 &#x6570;&#x636E;&#x8BBF;&#x95EE;&#x5C42;insert() 方法进行数据的添加操作
  • 表现层:接收请求,封装数据,调用业务逻辑层,响应数据
    JSP快速上手与MVC模式和三层架构的知识点总结+综合案例
  • 包名规范
  • 表现层(表示层): priv.dandelion.controller 或者 priv.dandelion.web
  • 业务逻辑层: priv.dandelion.service
  • 数据访问层(持久层): priv.dandelion.dao 或者 priv.dandelion.mapper
  • 一些框架是对不同层进行封装的,举例说明
  • 封装表示层: SpringMVCStruts2
  • 封装业务逻辑层: Spring
  • 封装数据访问层: MyBatisHibername

7.3 MVC 和 三层架构

MVC 和 三层架构容易混淆

  • MVC和三层架构的联系和区别
  • 图中上半部分是MVC模式,下半部分是三层架构
    JSP快速上手与MVC模式和三层架构的知识点总结+综合案例

8、综合案例

完成品牌数据的增删改查
新增 序号 品牌名称 企业名称 排序 品牌介绍 状态 操作 1 三只松鼠 三只松鼠 100 三只松鼠,好吃不上火 启用 修改 删除 2 优衣库 优衣库 200 优衣库,服适人生 禁用 修改 删除 3 小米 小米科技有限公司 1000 为发烧而生 启用 修改 删除

8.1 环境准备

  1. 创建项目模块。导入坐标
  2. 创建三层架构包结构
  3. 创建数据库表tb_brand
  4. 编写实体类Brand
  5. MyBatis环境
  6. 核心配置文件
  7. BrandMapper.xml
  8. BrandMapper接口

JSP快速上手与MVC模式和三层架构的知识点总结+综合案例
* pom.xml配置文件

  4.0.0
  priv.dandelion
  brand-demo
  1.0-SNAPSHOT
  war

    8
    8

      org.mybatis
      mybatis
      3.5.5

      mysql
      mysql-connector-java
      5.1.34

      javax.servlet
      javax.servlet-api
      3.1.0
      provided

      javax.servlet.jsp
      jsp-api
      2.2
      provided

      jstl
      jstl
      1.2

      taglibs
      standard
      1.1.2

        org.apache.tomcat.maven
        tomcat7-maven-plugin
        2.2

  • SQL
-- 删除tb_brand表
drop table if exists tb_brand;
-- 创建tb_brand表
create table tb_brand
(
    -- id 主键
    id           int primary key auto_increment,
    -- 品牌名称
    brand_name   varchar(20),
    -- 企业名称
    company_name varchar(20),
    -- 排序字段
    ordered      int,
    -- 描述信息
    description  varchar(100),
    -- 状态:0:禁用  1:启用
    status       int
);
-- 添加数据
insert into tb_brand (brand_name, company_name, ordered, description, status)
values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
       ('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1);
  • 实体类
package priv.dandelion.entity;

public class Brand {
    // id 主键
    private Integer id;
    // 品牌名称
    private String brand_name;
    // 企业名称
    private String company_name;
    // 排序字段
    private Integer ordered;
    // 描述信息
    private String description;
    // 状态:0:禁用  1:启用
    private Integer status;

    public Brand() {
    }

    public Brand(Integer id, String brand_name, String company_name, Integer ordered, String description, Integer status) {
        this.id = id;
        this.brand_name = brand_name;
        this.company_name = company_name;
        this.ordered = ordered;
        this.description = description;
        this.status = status;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBrand_name() {
        return brand_name;
    }

    public void setBrand_name(String brand_name) {
        this.brand_name = brand_name;
    }

    public String getCompany_name() {
        return company_name;
    }

    public void setCompany_name(String company_name) {
        this.company_name = company_name;
    }

    public Integer getOrdered() {
        return ordered;
    }

    public void setOrdered(Integer ordered) {
        this.ordered = ordered;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "Brand{" +
                "id=" + id +
                ", brand_name='" + brand_name + '\'' +
                ", company_name='" + company_name + '\'' +
                ", ordered=" + ordered +
                ", description='" + description + '\'' +
                ", status=" + status +
                '}';
    }
}
  • MyBatis配置
  • 核心配置文件 mybatis-config.xml

    数据库连接信息 <property name="url" value="jdbc:mysql:///db1?useSSL=false&useUnicode=true&characterEncoding=utf-8&useServerPrepStmts=true"></property> 无论多长 无论多长 一定不能换行!!!换行的内容不生效 qwq &#x8C03;&#x8BD5;&#x4E86;&#x4E00;&#x4E2A;&#x4E0B;&#x5348;


  • BrandMapper.xml映射配置文件(此处解决了数据库与实体类命名不一致问题)
    • 在Mapper接口中使用注解时需要额外加上下列注解
@ResultMap("brandResultMap")

  • 工具类
  • SqlSessionFactoryUtils工具类,用于创建和获取SqlSession工厂对象
package priv.dandelion.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class SqlSessionFactoryUtils {

    // 提升作用域,用于返回值
    private static SqlSessionFactory sqlSessionFactory;

    // 静态代码块会随着类的加载自动执行且只执行一次
    static {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    // 返回工厂对象
    public static SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }

}
  • 字符串重编码工具类,将字符串重新编码为UTF-8
package priv.dandelion.utils;

import java.nio.charset.StandardCharsets;

public class ReEncoding {

    public static String reEncodingToUtf8(String str) {
        // 使用ISO-8859-1编码将乱码字符编回二进制码,得到其字节数组
        byte[] bytes = str.getBytes(StandardCharsets.ISO_8859_1);
        // 将字节数组使用UTF-8重新编码
        return new String(bytes, StandardCharsets.UTF_8);
    }
}
package priv.dandelion.dao;

import org.apache.ibatis.annotations.*;
import priv.dandelion.entity.Brand;

import java.util.List;

public interface BrandMapper {

    @Select("select * from tb_brand;")
    @ResultMap("brandResultMap")
    public List selectAll();

    @Select("select * from tb_brand where id = #{id}")
    @ResultMap("brandResultMap")
    public Brand selectById(int id);

//    @Insert("insert into tb_brand " +
//            "(brand_name, company_name, ordered, description, status) " +
//            "values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});")
//    @ResultMap("brandResultMap")
//    public void addBrand(
//            @Param("brandName") String brandName,
//            @Param("companyName") String companyName,
//            @Param("ordered") int ordered,
//            @Param("description") String description,
//            @Param("status") int status
//    );

    @Insert("insert into tb_brand " +
            "values(null, #{brandName}, #{companyName}, " +
            "#{ordered}, #{description}, #{status})")
    void addBrand(Brand brand);

//    @Update("update tb_brand " +
//            "set brand_name = #{brandName}," +
//            "company_name = #{companyName}," +
//            "ordered = #{ordered}," +
//            "description = #{description}," +
//            "status = #{status} " +
//            "where id = #{id};")
//    @ResultMap("brandResultMap")
//    public void updateBrand(
//            @Param("id") int id,
//            @Param("brandName") String brandName,
//            @Param("companyName") String companyName,
//            @Param("ordered") int ordered,
//            @Param("description") String description,
//            @Param("status") int status
//    );

    @Update("update tb_brand " +
            "set brand_name = #{brandName}," +
            "company_name = #{companyName}," +
            "ordered = #{ordered}," +
            "description = #{description}," +
            "status = #{status} " +
            "where id = #{id};")
    @ResultMap("brandResultMap")
    public void updateBrand(Brand brand);

    @Delete("delete from tb_brand where id = #{id};")
    @ResultMap("brandResultMap")
    public void deleteBrand(@Param("id") int id);
}

8.2 查询所有

8.2.1 编写BrandMapper

添加 SelectAll()方法,见 8.1环境准备-成品 BrandMapper.java

8.2.2 编写工具类

编写工具类,用于加载 SqlSessionFactory,见8.1环境准备-

8.2.3 编写BrandService

package priv.dandelion.controller;

import priv.dandelion.entity.Brand;
import priv.dandelion.service.BrandService;

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.List;

@WebServlet("/selectAll")
public class SelectAllServlet extends HttpServlet {

    BrandService service = new BrandService();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 调用service中的查询方法
        List brands = service.selectAll();
        // 将返回的结果存储到request域中
        req.setAttribute("brands", brands);
        // 将请求转发到页面
        req.getRequestDispatcher("/brand.jsp").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

8.2.4 编写Servlet

package priv.dandelion.service;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import priv.dandelion.dao.BrandMapper;
import priv.dandelion.entity.Brand;
import priv.dandelion.utils.SqlSessionFactoryUtils;

import java.util.List;

public class BrandService {

    SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();

    public List selectAll() {
        // 获取SqlSession
        SqlSession sqlSession = factory.openSession();
        // 获取Mapper
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
        // 执行SQL
        List brands = mapper.selectAll();
        // 回收资源
        sqlSession.close();
        return brands;

    }
}

8.2.5 编写 brand.jsp 页面


    查询所有

        序号
        品牌名称
        企业名称
        排序
        品牌介绍
        状态
        操作

                ${brand.id}--%>
            ${status.count}
            ${brand.brandName}
            ${brand.companyName}
            ${brand.ordered}
            ${brand.description}

                启用

                禁用

            修改 删除

    document.getElementById("add").onclick = function (){
        location.href = "/brand_demo/addBrand.jsp";
    }

8.3 添加

重复数据的判定部分未实现

8.3.1 编写BrandMapper方法

添加 AddBrand()方法,见 8.1环境准备-成品 BrandMapper.java

8.3.2 编写BrandService方法

  • BrandService.java中添加如下方法
public void addBrand(Brand brand) {
    // 获取SqlSession
    SqlSession sqlSession = factory.openSession();
    // 获取Mapper
    BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
    // 执行SQL
    mapper.addBrand(brand);
    // 回收资源
    sqlSession.close();
}

8.3.3 改进brand.jsp

  • 在页面的表格前添加新增按钮

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

    document.getElementById("add").onclick = function (){
        location.href = "/brand-demo/addBrand.jsp";
    }

8.3.4 编写addBrand.jsp页面


    添加品牌

添加品牌

    品牌名称:
    企业名称:
    排序:
    描述信息:
    状态:
    禁用
    启用

8.3.5 编写Servlet

package priv.dandelion.controller;

import priv.dandelion.entity.Brand;
import priv.dandelion.service.BrandService;
import priv.dandelion.utils.ReEncoding;

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;

@WebServlet("/add")
public class AddServlet extends HttpServlet {

    BrandService service = new BrandService();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 解决中文乱码问题

        // POST请求的中文乱码问题解决方案
        // req.setCharacterEncoding("UTF-8");

        // 本项目已使用工具类实现对GET和POST请求的中文乱码的统一处理的方法,详见工具类priv.dandelion.utils.ReEncoding

        // 从request中取出数据
        String brandName = req.getParameter("brandName");
        String companyName = req.getParameter("companyName");
        String ordered = req.getParameter("ordered");
        String description = req.getParameter("description");
        String status = req.getParameter("status");

        // 解决中文乱乱码,封装为Brand对象
        Brand brand = new Brand(
                ReEncoding.makeReEncoding(brandName),
                ReEncoding.makeReEncoding(companyName),
                Integer.parseInt(ordered),
                ReEncoding.makeReEncoding(description),
                Integer.parseInt(status)
        );

        // 检查中文乱码
        System.out.println(brand);

        // 调用service中的添加方法
        service.addBrand(brand);

        // 转发到查询所有Servlet
        req.getRequestDispatcher("/selectAll").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

8.4 修改

8.4.1 回显数据

在点击修改后,页面的输入框中回显示目前数据库中存放的的数据
为实现此效果,点击修改按钮时不能直接跳转到 update.jsp页面,而是带着该数据的 id请求后端程序,将查询结果存储到域对象中再跳转到 update.jsp页面进行数据展示。

8.4.1.1 编写BrandMapper方法

添加 selectById()方法,见 8.1环境准备-成品 BrandMapper.java

8.4.1.2 编写BrandService方法
public Brand selectById(int id) {
    // 获取SqlSession
    SqlSession sqlSession = factory.openSession();
    // 获取Mapper
    BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
    // 执行SQL
    Brand brand = mapper.selectById(id);
    // 回收资源,返回数据
    sqlSession.close();
    return brand;
}
8.4.1.3 编写Servlet
package priv.dandelion.controller;

import priv.dandelion.entity.Brand;
import priv.dandelion.service.BrandService;

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;

@WebServlet("/selectById")
public class selectByIdt extends HttpServlet {

    private  BrandService service = new BrandService();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 接收id
        String id = req.getParameter("id");
        // 调用service
        Brand brand = service.selectById(Integer.parseInt(id));
        // 存储到request域中
        req.setAttribute("brand", brand);
        // 转发请求到页面
        req.getRequestDispatcher("/updateBrand.jsp").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

8.4.1.4 编写 update.jsp 页面
  • 回显注意事项
  • input 标签要进行数据回显,需要设置 value 属性
  • textarea 标签要进行数据回显,需要在标签体中使用 EL&#x8868;&#x8FBE;&#x5F0F;
  • 单选框使用 if 标签需要判断 brand.status 的值是 1 还是 0 在指定的单选框上使用 checked 属性,表示被选中状态
  • 代码

    添加品牌

修改品牌

    品牌名称:
    企业名称:
    排序:

    描述信息:${brand.description}

    状态:

        禁用
        启用

        禁用
        启用

8.4.2 修改数据

8.4.2.1 编写BrandMapper方法

添加 updateBrand()方法,见 8.1环境准备-成品 BrandMapper.java

8.4.2.2 编写BrandService方法
public void updateBrand(Brand brand) {
    // 获取SqlSession
    SqlSession sqlSession = factory.openSession(true);
    // 获取Mapper
    BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
    // 执行SQL
    mapper.updateBrand(brand);
    // 回收资源
    sqlSession.close();
}
8.4.2.3 编写Servlet
package priv.dandelion.controller;

import priv.dandelion.entity.Brand;
import priv.dandelion.service.BrandService;
import priv.dandelion.utils.ReEncoding;

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;

@WebServlet("/update")
public class UpdateServlet extends HttpServlet {

    BrandService service = new BrandService();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 解决中文乱码问题

        // POST请求的中文乱码问题解决方案
        // req.setCharacterEncoding("UTF-8");

        // 本项目已使用工具类实现对GET和POST请求的中文乱码的统一处理的方法,详见工具类priv.dandelion.utils.ReEncoding

        // 从req中取出数据
        String id = req.getParameter("id");
        String brandName = req.getParameter("brandName");
        String companyName = req.getParameter("companyName");
        String ordered = req.getParameter("ordered");
        String description = req.getParameter("description");
        String status = req.getParameter("status");

        // 封装为对象,解决中文乱码
        Brand brand = new Brand(
                Integer.parseInt(id),
                ReEncoding.reEncodingToUtf8(brandName),
                ReEncoding.reEncodingToUtf8(companyName),
                Integer.parseInt(ordered),
                ReEncoding.reEncodingToUtf8(description),
                Integer.parseInt(status)
        );

        // 调用service
        service.updateBrand(brand);

        // 转发到查询所有
        req.getRequestDispatcher("/selectAll").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

8.4.2.4 解决获取不到主键的问题 – 使用隐藏域
  • 存在问题
  • update.jsp 页面提交数据时是没有携带主键数据的,而后台修改数据需要根据主键进行修改
    • 不希望页面将主键id展示给用户看
    • 后台修改数据需要根据主键进行修改
  • update.jsp页面提交数据时没有携带主键数据
  • 可使用HTML隐藏域解决该问题

  • update.jsp 页面最终代码

    添加品牌

修改品牌

    品牌名称:
    企业名称:
    排序:

    描述信息:${brand.description}

    状态:

        禁用
        启用

        禁用
        启用

8.5 删除

删除功能不再赘述

8.5.1 编写BrandMapper方法

添加 deleteBrand()方法,见 8.1环境准备-成品 BrandMapper.java

8.5.2 编写BrandService方法

public void deleteBrand(int id) {
    // 获取SqlSession
    SqlSession sqlSession = factory.openSession(true);
    // 获取Mapper
    BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
    // 执行SQL
    mapper.deleteBrand(id);
    // 回收资源
    sqlSession.close();
}

8.5.3 编写Servlet

package priv.dandelion.controller;

import priv.dandelion.service.BrandService;

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;

@WebServlet("/delete")
public class DeleteServlet extends HttpServlet {
    BrandService service = new BrandService();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 接收id
        String id = req.getParameter("id");
        // 调用Service
        service.deleteBrand(Integer.parseInt(id));
        // 转发到查询所有
        req.getRequestDispatcher("/selectAll").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

8.5.4 修改页面中的删除按钮

删除

Original: https://www.cnblogs.com/dandelion-000-blog/p/16768856.html
Author: Dandelion_000
Title: JSP快速上手与MVC模式和三层架构的知识点总结+综合案例

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/713748/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 访问控制列表与SSH结合使用,为网络设备保驾护航,提高安全性

    通过之前的文章简单介绍了华为交换机如何配置SSH远程登录,在一些工作场景,需要特定的IP地址段能够SSH远程访问和管理网络设备,这样又需要怎么配置呢?下面通过一个简单的案例带着大家…

    技术杂谈 2023年6月21日
    080
  • 期末考试代码

    import javax.swing.*; import java.awt.*; //import java.awt.event.InputEvent; //import java…

    技术杂谈 2023年6月21日
    085
  • swap(a,b)异或骚操作方法

    众所周知,平日里我们如果要交换两个变量的时候,通常都是 void swap(int a, int b) { int temp = a; a = b; b = temp; } 通过创…

    技术杂谈 2023年7月24日
    071
  • 哪些纪录片可以称为「神作」?

    自然纪录片(这里面又大概分为地球、宇宙、人体三个大部分) 一、BBC地球篇首先是BBC三大”镇馆之宝”(自封的)《地球脉动》:几乎算是有史以来最好的生态纪录…

    技术杂谈 2023年5月31日
    084
  • typora最后的免费版本

    需要的阿里云盘自取 「typora最后的免费版本」https://www.aliyundrive.com/s/p3Ci2gbgwYh点击链接保存,或者复制本段内容,打开「阿里云盘」…

    技术杂谈 2023年7月11日
    084
  • 开源IPTV源服务程序使用教程

    前言 我的目标是将程序打造成属于每个人的直播源服务,且对每个人完全开源免费!可作为家庭影院电视、视频等流媒体的提供商,兼容全平台,只需使用视频播放器调用接口链接即可享用,不多说开始…

    技术杂谈 2023年6月21日
    0274
  • xhEditor实现ctrl+v粘贴word图片并上传

    这里分享的是它官网的一个收费插件powerpaste的旧版本源码,但也不影响功能使用。 以vue为例说明: 将tinymce下载后放到static目录下,不用npm安装。 powe…

    技术杂谈 2023年5月31日
    0104
  • Java后端开发——美团(牛客)

    Java的基本数据类型,各自的字节数 ​ 老生常谈,不多说了. 类型 字节数 byte 1字节 short 2字节 int 4字节 long 8字节 float 4字节 doubl…

    技术杂谈 2023年7月11日
    076
  • Python数据分析–Numpy常用函数介绍(8)–Numpy中几中常见的图形

    在NumPy中,所有的标准三角函数如sin、cos、tan等均有对应的通用函数。 一、利萨茹曲线 (Lissajous curve)利萨茹曲线是一种很有趣的使用三角函数的方式(示波…

    技术杂谈 2023年7月25日
    074
  • Kruskal算法求最小生成树

    例题链接 Kruskal算法的对比prim的区别是,前者使用了并查集的思路,而后者类似于Dijkskal算法。操作策略是,对所有边权进行从小到大的排序,然后从小到大遍历所有边权去选…

    技术杂谈 2023年6月21日
    081
  • 【赵渝强老师】HBase的体系架构

    一、什么是HBase? HBase是一个基于HDFS之上的分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文”BigTable大表…

    技术杂谈 2023年7月24日
    078
  • binary与进制转换

    规律数: 0111为4位补码的最大值,规律是1个0和3个1,可以推导出 32位补码的最大值:1个0和31个1——(011111111111111111111…

    技术杂谈 2023年7月10日
    054
  • Unity3D 预备知识:C#与Lua相互调用

    在使用Unity开发游戏以支持热更新的方案中,使用ULua是比较成熟的一种方案。那么,在使用ULua之前,我们必须先搞清楚,C#与Lua是怎样交互的了? 一.基本原理 简单地说,c…

    技术杂谈 2023年6月1日
    0100
  • 网络多人游戏架构与编程1

    【 网络多人游戏架构与编程1】 1、即使在今天,大多数的多人在线游戏在 每个游戏会话中仍然限制玩家的数量 ,一般支持4~32个玩家。然而,在 大规模多人在线游戏(massive m…

    技术杂谈 2023年5月31日
    0100
  • 【考研】C语言

    考研C语言 收录数据结构会用到的C语言知识,建议有基础的情况下再学习,针对性学习即可。 往后的学习要多从内存角度去学习计算机的知识 1. 数组 1.1 一维数值数组 具备相同的数据…

    技术杂谈 2023年7月10日
    079
  • 多带小孩去的地方

    科技、人文、艺术、博物、航空、航海、图书、高等学校等地 四川 成都博物馆 分南楼和北楼。位于天府广场西侧,与四川省图书馆、四川美术馆、四川科技馆、锦城艺术宫等建筑毗邻。 四川博物院…

    技术杂谈 2023年6月1日
    074
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球