赞
踩
定义
简单示例
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>JSP,HELLO WORLD!!!</h1>
<%
System.out.println("Hello JSP");
%>
</body>
</html>
其中html标签代码最终会被浏览器解析并显示在页面上;而java代码会显示在服务器的控制台上,运行截图如下
注意:若利用Tomcat插件运行导致jsp文件无法在浏览器解析,出现如图所示页面错误,代表当前所用的JDK版本太高了
JavaWeb------Tomcat
中的IDEA中使用Tomcat
那一部分内容)步骤
Step1:在pom.xml文件中导入JSP坐标依赖
provided
,即该坐标在编译和测试时有效
因为Tomcat中已经提供好了JSP的jar包,所以在打包后应该排除掉自己所设置的jar包,若不排除则会报错
注意Servlet坐标依赖也是需要设置坐标依赖范围为provided
,原因与其相同
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
- 完整pom.xml文件如下 ```xml <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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>JspDemo</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>JspDemo Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!--JSP坐标依赖 注意别忘了加上坐标依赖范围--> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> </dependencies> <build> <finalName>JspDemo</finalName> <plugins> <!-- Tomcat插件 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> </plugin> </plugins> </build> </project> ```
Step2:创建JSP文件
Step3:编写HTML标签和Java代码(该步骤省略可详见JSP快速入门)
<% 这中间写Java代码 %>
中间JSP本质上就是一个Servlet。
详解如下
Servlet
java文件(这个过程是Tomcat自动完成的),然后在由Tomcat自动进行编译最终向浏览器发出响应
JSP工作流程
HttpJspBase
。
HttpJspBase
,JSP 页面的 servlet 能够有效地利用 servlet 的生命周期方法,并且使 JSP 页面能够与 servlet 容器集成,处理 HTTP 请求和响应。jspInit()
方法进行初始化。service()
方法,进而调用 _jspService()
方法来处理请求。jspDestroy()
方法进行清理。示例(以JSP快速入门的hello.jsp文件为例),hello.jsp代码如下
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>JSP,HELLO WORLD!!!</h1>
<%
System.out.println("Hello JSP");
%>
</body>
</html>
Step1:代开当前Web项目的目录
Step2:打开当前项目目录下的target目录→tomcat→work→然后一直进入到jsp目录下
Step3:会发现有一个java文件,该文件就是JSP文件所生成的对应Java文件,打开该hello_jsp.java文件,代码如下
package org.apache.jsp; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent { private static final javax.servlet.jsp.JspFactory _jspxFactory = javax.servlet.jsp.JspFactory.getDefaultFactory(); private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants; private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.tomcat.InstanceManager _jsp_instancemanager; public java.util.Map<java.lang.String,java.lang.Long> getDependants() { return _jspx_dependants; } public void _jspInit() { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig()); } public void _jspDestroy() { } public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException { final javax.servlet.jsp.PageContext pageContext; javax.servlet.http.HttpSession session = null; final javax.servlet.ServletContext application; final javax.servlet.ServletConfig config; javax.servlet.jsp.JspWriter out = null; final java.lang.Object page = this; javax.servlet.jsp.JspWriter _jspx_out = null; javax.servlet.jsp.PageContext _jspx_page_context = null; try { response.setContentType("text/html;charset=UTF-8"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("\r\n"); out.write("\r\n"); out.write("<html>\r\n"); out.write(" <head>\r\n"); out.write(" <title>Title</title>\r\n"); out.write(" </head>\r\n"); out.write(" <body>\r\n"); out.write(" <h1>JSP,HELLO WORLD!!!</h1>\r\n"); out.write(" "); System.out.println("Hello JSP"); out.write("\r\n"); out.write(" </body>\r\n"); out.write("</html>\r\n"); } catch (java.lang.Throwable t) { if (!(t instanceof javax.servlet.jsp.SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { out.clearBuffer(); } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); else throw new ServletException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } }
在该代码中我们发现,Tomcat将jsp文件代码以java代码的形式写了出来
Tomcat将JSP文件转换为Java文件后,该文件extends org.apache.jasper.runtime.HttpJspBase
,HttpJspBase
类继承自 HttpServlet
,所以该Java文件属于Servlet类
对HttpJspBase
类详解
HttpJspBase
提供了 jspInit()
和 jspDestroy()
方法,分别对应 servlet 的 init()
和 destroy()
方法。这些方法允许 JSP 页面在初始化和销毁时执行特定的代码。HttpJspBase
类会覆盖 service()
方法,以便调用 _jspService(HttpServletRequest request, HttpServletResponse response)
方法,这是每个 JSP 页面必须实现的一个方法,用于处理请求和生成响应。HttpJspBase
的 servlet 类。生成的 servlet 类会实现 _jspService()
方法,该方法包含了 JSP 页面中的实际代码。作用:用于在JSP页面内定义Java代码
JSP脚本分类
分类 | 解释 |
---|---|
<%...%> | 内容会直接放到_jspService() 方法之中 |
<%=...%> | 内容会放到out.print() 之中,作为out.print() 的参数 |
<%!...%> | 内容会直接放到_jspService() 方法之外,被类继续包含。即跟属性、方法属于同一级 |
示例
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h1>JSP,HELLO WORLD!!!</h1> <!--第一种脚本--> <% System.out.println("Hello JSP"); int i = 3; %> <!--第二种脚本--> <%="i为" + 3%> <!--第三种脚本--> <%! void show(){} String name = "zhangsan"; %> </body> </html>
第一种脚本<%...%>
,会在生成的java文件的_jspService()
方法之中,如下代码所示(注意:博主把该_jspService
方法内的无关代码均已删除,这样能清楚看出来该脚本内的代码在该方法之中)(html代码也在_jspService()
方法之中, 如下代码所示 )
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException { try { out.write("\r\n"); out.write("\r\n"); out.write("<html>\r\n"); out.write(" <head>\r\n"); out.write(" <title>Title</title>\r\n"); out.write(" </head>\r\n"); out.write(" <body>\r\n"); out.write(" <h1>JSP,HELLO WORLD!!!</h1>\r\n"); out.write(" <!--第一种脚本-->\r\n"); out.write(" "); System.out.println("Hello JSP"); int i = 3; out.write("\r\n"); out.write(" <!--第二种脚本-->\r\n"); out.write(" "); out.print("i为" + i); out.write("\r\n"); out.write(" <!--第三种脚本-->\r\n"); out.write(" "); out.write("\r\n"); out.write(" </body>\r\n"); out.write("</html>\r\n"); } }
第二种脚本<%=...%>
,也会在生成的java文件的_jspService()
方法之中,不过它的内容会放到out.print()
之中,作为out.print()
的参数,最终输出到页面上,代码详见第一种脚本处的代码,Tomcat运行该Web项目后,页面显示如下
第三种脚本<%!...%>
,内容会直接放到_jspService()
方法之外,被类继续包含。即跟属性、方法属于同一级,如下所示(注意:代码均为省略形式,以便明了)
public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
void show(){}
String name = "zhangsan";
}
将数据库中的商品显示在浏览器页面
brand对象类
package at.guigu.pojo; public class Brand { // id 主键 private Integer id; // 品牌名称 private String brandName; // 企业名称 private String companyName; // 排序字段 用于将某个品牌显示在最前面让消费者看到 private Integer ordered; // 描述信息 private String description; // 状态:0:禁用 1:启用 private Integer status; public Brand() {} public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) { this.id = id; this.brandName = brandName; this.companyName = companyName; this.ordered = ordered; this.description = description; this.status = status; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getBrandName() { return brandName; } public void setBrandName(String brandName) { this.brandName = brandName; } public String getCompanyName() { return companyName; } public void setCompanyName(String companyName) { this.companyName = companyName; } 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 + ", brandName='" + brandName + '\'' + ", companyName='" + companyName + '\'' + ", ordered=" + ordered + ", description='" + description + '\'' + ", status=" + status + '}'; } }
brand.jsp文件
<%@ page import="at.guigu.pojo.Brand" %> <%@ page import="java.util.ArrayList" %> <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <% //模拟查询数据库 List<Brand> brands = new ArrayList<>(); brands.add(new Brand(1, "三只松鼠", "三只松鼠", 100, "三只松鼠,好吃不上火", 1)); brands.add(new Brand(2, "优衣库", "优衣库", 200, "优衣库,服适人生", 0)); brands.add(new Brand(3, "小米", "小米科技有限公司", 1000, "为发烧而生", 1)); %> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input type="button" value="新增"><br> <hr> <table border="1" cellspacing="0" width="800"> <tr> <th>序号</th> <th>品牌名称</th> <th>企业名称</th> <th>排序</th> <th>品牌介绍</th> <th>状态</th> <th>操作</th> </tr> <% for (int i = 0; i < brands.size(); i++) { Brand brand = brands.get(i);//获取第i个对象 %> <tr align="center"> <td><%=brand.getId()%></td> <td><%=brand.getBrandName()%></td> <td><%=brand.getCompanyName()%></td> <td><%=brand.getOrdered()%></td> <td><%=brand.getDescription()%></td> <td> <% if (brand.getStatus() == 0) { %> <%="禁用"%> <% }else { %> <%="启用"%> <% } %> </td> <td><a href="#">修改</a> <a href="#">删除</a></td> </tr> <% } %> </table> </body> </html>
注意以下这一部分代码可改为
<td> <% if (brand.getStatus() == 0) { %> <%="禁用"%> <% }else { %> <%="启用"%> <% } %> </td> <!--等同于--> <% if (brand.getStatus() == 0) { %> <td><%="禁用"%></td> <% }else { %> <td><%="启用"%></td> <% } %>
Tomcat运行该Web项目后页面运行截图如下
注意事项
在JSP文件中Java代码可跟Html代码可嵌套来写,但是Java代码要写在JSP脚本中,Html代码不能写在脚本中,如下所示
<%
if (brand.getStatus() == 0) {
%>
<td><%="禁用"%></td>
<%
}else {
%>
<td><%="启用"%></td>
<%
}
%>
列举部分缺点如下:
Html+AJAX
逐渐代替解决方式
定义
主要功能:获取数据
语法:${key}
${brands}
:获取request
域中存储的key为brands的数据JavaWeb中四大域对象
简单示例
Step1:在at.guigu.web包下创建ServletDemo1
类,将准备数据放入,最终代码如下
package at.guigu.web; import at.guigu.pojo.Brand; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; import java.util.ArrayList; import java.util.List; @WebServlet("/eldemo1") public class ServletDemo1 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1 准备数据:模拟查询数据库并获取数据 List<Brand> brands = new ArrayList<>(); 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); } }
Step2:创建el-demo.jsp文件,具体代码如下
<%@...%>
标签体内加上isELIgnored="false"
,作用是防止Tomcat配置禁用EL表达式<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!--获取request域中存储brands的数据-->
${brands}
</body>
</html>
Tomcat运行该Web项目后运行截图如下
定义
JSTL标签
标签 | 解释 |
---|---|
<c:out> | 用于在JSP中显示数据,相当于<%=...> |
<c:set> | 用于保存数据 |
<c:remove> | 用于删除数据 |
<c:catch> | 用来处理产生错误的异常情况,并将错误信息储存起来 |
<c:if> | 与java中的if一样 |
<c:choose> | 本身只当作<c:when> 和<c:otherwise> 的父标签 |
<c:when> | <c:choose> 的子标签,用来判断条件是否成立 |
<c:otherwise> | <c:choose> 的子标签,接在<c:when> 标签后,当<c:when> 标签判断为false时被执行 |
<c:import> | 检索一个绝对或相对URL,然后将其内容暴露给页面 |
<c:forEach> | 基础迭代标签,接受多种集合类型 |
<c:forTokens> | 根据指定的分隔符来分割内容并迭代输出 |
<c:param> | 用来给包含或重定向的页面传递参数 |
<c:redirect> | 重定向至一个新的URL |
<c:url> | 使用可选的查询参数来创造一个URL |
JSTL标签使用步骤
Step1: 在Web项目的pom.xml文件中导入坐标依赖
<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>
Step2: 在JSP页面上引入JSTL标签库<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
,如下所示
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
</body>
</html>
Step3: 使用标签
<c:if>
标签该标签中必有的属性 | 解释 |
---|---|
test | 该属性的属性值为逻辑表达式,结果若为true则执行该标签体中的内容 |
简单示例,jstl-demo1.jsp文件代码如下
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<c:if test="true">
<h1>判断为true</h1>
</c:if>
</body>
</html>
<c:if>
标签通常与EL表达式联合使用来执行对应的代码,代码示例如下
ServletDemo1.java代码如下
package at.guigu.web; import at.guigu.pojo.Brand; 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("/jstldemo2") public class ServletDemo2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1 准备数据:模拟查询数据库并获取数据 List<Brand> brands = new ArrayList<>(); 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); //用来测试<c:if>标签 request.setAttribute("status", 1); //3 转发到el-demo.jsp request.getRequestDispatcher("/jstl-demo2.jsp").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
jstl-demo2.jsp文件代码如下:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<c:if test="${status==1}">
<h1>满足status==1则输出该条html语句</h1>
</c:if>
</body>
</html>
<c:choose>
、<c:when>
、<c:otherwise>
以上三个标签联合使用用于实现多条件分支的逻辑控制,类似于 Java 中的 switch
语句或 if-else-if 结构。
三个标签解释
<c:choose>
<c:when>
标签,可以选择性 地包含一个 <c:otherwise>
标签<c:when>
标签
test
<c:otherwise>
标签
<c:when>
条件都不满足时应该执行的代码块<c:choose>
标签内,并且通常放在所有 <c:when>
标签之后<c:when>
条件都为 false 时执行代码示例1
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<c:choose>
<c:when test="${user.age < 18}">
<p>您是未成年人。</p>
</c:when>
<c:when test="${user.age >= 18 and user.age <= 65}">
<p>您是成年人。</p>
</c:when>
<c:otherwise>
<p>您是老年人。</p>
</c:otherwise>
</c:choose>
user.age
小于 18,则显示“您是未成年人。user.age
在 18 到 65 之间(含),则显示“您是成年人。user.age
大于 65),则显示“您是老年人。代码示例2
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<c:choose>
<c:when test="${user.role == 'admin'}">
<p>欢迎管理员!</p>
</c:when>
<c:when test="${user.role == 'user'}">
<p>欢迎普通用户!</p>
</c:when>
<c:otherwise>
<p>欢迎访客,请登录。</p>
</c:otherwise>
</c:choose>
user.role
是 admin
,则显示“欢迎管理员!”user.role
是 user
,则显示“欢迎普通用户!”<c:otherwise>
标签内的内容,显示“欢迎访客,请登录。<c:forEach>
该标签的属性 | 解释 |
---|---|
items | 要迭代的集合(即被遍历的容器)。可以是数组、集合、映射等 |
var | 每次迭代时存储当前项的变量名(即遍历产生的临时变量) |
varStatus | 一个变量,用于存储迭代状态(即遍历状态对象)(可选)(注意: 该属性的属性值字符串可随意写,属性值.index :序号从0开始;属性值.count :序号从1开始) |
begin | 迭代的起始索引(可选) |
end | 迭代的结束索引(可选) |
step | 每次迭代的步长(可选) |
增强for循环代码示例
Brand类代码
package at.guigu.pojo; public class Brand { // id 主键 private Integer id; // 品牌名称 private String brandName; // 企业名称 private String companyName; // 排序字段 用于将某个品牌显示在最前面让消费者看到 private Integer ordered; // 描述信息 private String description; // 状态:0:禁用 1:启用 private Integer status; public Brand() {} public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) { this.id = id; this.brandName = brandName; this.companyName = companyName; this.ordered = ordered; this.description = description; this.status = status; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getBrandName() { return brandName; } public void setBrandName(String brandName) { this.brandName = brandName; } public String getCompanyName() { return companyName; } public void setCompanyName(String companyName) { this.companyName = companyName; } 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 + ", brandName='" + brandName + '\'' + ", companyName='" + companyName + '\'' + ", ordered=" + ordered + ", description='" + description + '\'' + ", status=" + status + '}'; } }
JstlServletDemo3代码
package at.guigu.web; import at.guigu.pojo.Brand; 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("/jstldemo3") public class JstlServletDemo3 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1 准备数据:模拟查询数据库并获取数据 List<Brand> brands = new ArrayList<>(); 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); //用来测试<c:if>标签 request.setAttribute("status", 1); //3 转发到el-demo.jsp request.getRequestDispatcher("/jstl-demo3.jsp").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
jstl-demo3.jsp代码
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <input type="button" value="新增"><br> <hr> <table border="1" cellspacing="0"> <tr> <th>序号</th> <th>品牌名称</th> <th>企业名称</th> <th>排序</th> <th>品牌介绍</th> <th>状态</th> <th>操作</th> </tr> <c:forEach items="${brands}" var="brand"> <tr align="center"> <td>${brand.id}</td> <td>${brand.brandName}</td> <td>${brand.companyName}</td> <td>${brand.ordered}</td> <td>${brand.description}</td> <c:choose> <c:when test="${brand.status==1}"> <td>启用</td> </c:when> <c:otherwise> <td>禁用</td> </c:otherwise> </c:choose> <td><a href="#">修改</a> <a href="#">删除</a></td> </tr> </c:forEach> </table> </body> </html>
注意
EL表达式${对象名.属性名}
会被系统自动解析并调用对应的getXXX()
方法来返回对应的值
上述运行截图中序号对应的是数据库中的主键id,这就会有一个弊端,如果删除优衣库则由于主键是唯一的,不会分配给其它品牌,所以最终浏览器的页面上的品牌三只松鼠和小米的序号仍为1、3,并不会变成1、2
为了解决该问题可使用varStatus
属性,如下jsp文件代码所示
示例一:序号从0开始
<%-- Created by IntelliJ IDEA. User: 10195 Date: 2024/6/28 Time: 9:19 To change this template use File | Settings | File Templates. --%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <input type="button" value="新增"><br> <hr> <table border="1" cellspacing="0"> <tr> <th>序号</th> <th>品牌名称</th> <th>企业名称</th> <th>排序</th> <th>品牌介绍</th> <th>状态</th> <th>操作</th> </tr> <c:forEach items="${brands}" var="brand" varStatus="xuhao"> <tr align="center"> <td>${xuhao.index}</td> <td>${brand.brandName}</td> <td>${brand.companyName}</td> <td>${brand.ordered}</td> <td>${brand.description}</td> <c:choose> <c:when test="${brand.status==1}"> <td>启用</td> </c:when> <c:otherwise> <td>禁用</td> </c:otherwise> </c:choose> <td><a href="#">修改</a> <a href="#">删除</a></td> </tr> </c:forEach> </table> </body> </html>
示例二:序号从1开始
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <input type="button" value="新增"><br> <hr> <table border="1" cellspacing="0"> <tr> <th>序号</th> <th>品牌名称</th> <th>企业名称</th> <th>排序</th> <th>品牌介绍</th> <th>状态</th> <th>操作</th> </tr> <c:forEach items="${brands}" var="brand" varStatus="xuhao"> <tr align="center"> <td>${xuhao.count}</td> <td>${brand.brandName}</td> <td>${brand.companyName}</td> <td>${brand.ordered}</td> <td>${brand.description}</td> <c:choose> <c:when test="${brand.status==1}"> <td>启用</td> </c:when> <c:otherwise> <td>禁用</td> </c:otherwise> </c:choose> <td><a href="#">修改</a> <a href="#">删除</a></td> </tr> </c:forEach> </table> </body> </html>
作用:可用来定义分页工具条
代码示例
Brand及JstlServletDemo3代码与增强for循环一样,此处省略
jstl-demo3.jsp代码
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <input type="button" value="新增"><br> <hr> <table border="1" cellspacing="0"> <tr> <th>序号</th> <th>品牌名称</th> <th>企业名称</th> <th>排序</th> <th>品牌介绍</th> <th>状态</th> <th>操作</th> </tr> <c:forEach items="${brands}" var="brand" varStatus="xuhao"> <tr align="center"> <td>${xuhao.count}</td> <td>${brand.brandName}</td> <td>${brand.companyName}</td> <td>${brand.ordered}</td> <td>${brand.description}</td> <c:choose> <c:when test="${brand.status==1}"> <td>启用</td> </c:when> <c:otherwise> <td>禁用</td> </c:otherwise> </c:choose> <td><a href="#">修改</a> <a href="#">删除</a></td> </tr> </c:forEach> </table> <hr> <c:forEach begin="1" end="10" step="1" var="i"> <a href="#">${i}</a> </c:forEach> </body> </html>
定义:MVC是一种分层开发的模式
MVC模式实现过程
浏览器向服务器端请求数据时会先请求控制器,控制器调用模型来获取数据,之后控制器会将数据传给视图,并由视图响应给浏览器,实现最终的页面展示
特点
解释:将一个完整的项目分为三个层面
at.guigu.web
或at.guigu.controller
SpringMVC
或Struts2
at.guigu.service
Spring
at.guigu.dao
或at.guigu.mapper
MyBatis
或Hibername
三层架构实现过程
浏览器向服务器端请求数据时会先请求表现层的控制器(即Servlet),然后控制器会调用业务逻辑层的代码(这些代码组装了数据访问层的CRUD等基本功能)来获取数据库中的数据,并将数据返回给表现层中的控制器(即Swervlet),然后再由控制器(即Servlet)对数据进行封装,放到request域中传给视图(即JSP),最终由视图(即JSP)将响应数据返回给浏览器,使其展现在页面上
MVC模式和三层架构的区别
注意:本案例已提交到Gitee,可自行下载:https://gitee.com/cgrs572/brand-demo.git
创建新的Web项目BrandDemo,引入坐标(在pom.xml文件中引入坐标依赖),并配置Tomcat(可详见Tomcat部分)
需要的坐标依赖有mybatis、mysql驱动、servlet、jsp、jstl
需要的插件有Tomcat插件
完整pom.xml文件如下
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>BrandDemo</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>BrandDemo Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!--MyBatis依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.16</version> </dependency> <!--mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> <!--Servlet依赖--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> <!--依赖范围关键字provided:在编译环境和测试环境有效,但在真正运行时就不会在使用该jar包--> </dependency> <!--JSP依赖--> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> <scope>provided</scope> </dependency> <!--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> </dependencies> <build> <finalName>BrandDemo</finalName> <plugins> <!-- Tomcat插件 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> </plugin> </plugins> </build> </project>
创建三层架构包结构
创建数据库表tb_brand并使IDEA与数据库建立连接,SQL代码如下
DROP TABLE IF EXISTS tb_brand; -- 创建品牌表brand CREATE TABLE IF NOT EXISTS 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); SELECT * FROM tb_brand;
创建实体类Brand
(此为Pojo类 :存放对数据库中数据封装的对象),代码如下
package at.guigu.pojo; public class Brand { // id 主键 private Integer id; // 品牌名称 private String brandName; // 企业名称 private String companyName; // 排序字段 用于将某个品牌显示在最前面让消费者看到 private Integer ordered; // 描述信息 private String description; // 状态:0:禁用 1:启用 private Integer status; public Brand() {} public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) { this.id = id; this.brandName = brandName; this.companyName = companyName; this.ordered = ordered; this.description = description; this.status = status; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getBrandName() { return brandName; } public void setBrandName(String brandName) { this.brandName = brandName; } public String getCompanyName() { return companyName; } public void setCompanyName(String companyName) { this.companyName = companyName; } 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 + ", brandName='" + brandName + '\'' + ", companyName='" + companyName + '\'' + ", ordered=" + ordered + ", description='" + description + '\'' + ", status=" + status + '}'; } }
MyBrtis基础环境配置
在mapper包下创建BrandMapper
接口
在项目的源代码配置文件目录(即main包下的resources目录下)创建多层目录,多层目录对应Mapper接口所在的多层包,然后再该包中创建BrandMapper.xml
SQL映射文件,基本代码如下
<?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"> <!-- namespace:名称空间 --> <mapper namespace="at.guigu.mapper.BrandMapper"> <!--结果映射--> <resultMap id="brandResultMap" type="brand"> <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可--> <result column="brand_name" property="brandName"/> <result column="company_name" property="companyName"/> </resultMap> </mapper>
在项目的源代码配置文件目录(即main包下的resources目录下)创建MyBatis核心配置文件mybatis-config.xml
,代码如下
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!--设置别名--> <typeAliases> <package name="at.guigu.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <!--数据库 连接信息--> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <!--加载SQL映射文件:传入sql映射文件的路径--> <!-- <mapper resource="at/guigu/mapper/BrandMapper.xml"/>--> <package name="at.guigu.mapper"/> </mappers> </configuration>
解释:页面上有一个“查询所有”的超链接,单击该链接即显示出查询数据,如图所示
要完成该问则需满足三层架构,各层需要做的工作如下所示
Dao层/Map层
Step1: BrandMapper
接口中写入查询所有数据的方法
package at.guigu.mapper;
import at.guigu.pojo.Brand;
import java.util.List;
public interface BrandMapper {
//查询并返回所有商品
/*@Select("select * from tb_brand")
@ResultMap("brandResultMap")*/
List<Brand> selectAll();
}
@ResultMap("brandResultMap")
,才能使结果映射生效(结果映射可详见MyBatis那一节)Step2: 在对应的SQL映射文件BrandMapper.xml
中写入SQL语句
<?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"> <!-- namespace:名称空间 --> <mapper namespace="at.guigu.mapper.BrandMapper"> <!--结果映射--> <resultMap id="brandResultMap" type="brand"> <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可--> <result column="brand_name" property="brandName"/> <result column="company_name" property="companyName"/> </resultMap> <!-- id:为sql语句的唯一标识 resultType:为对应sql语句执行完毕后返回结果的类型 --> <select id="selectAll" resultMap="brandResultMap"> select * from tb_brand; </select> </mapper>
Service层
由于Service层中的类均需要调用Mapper接口中的方法,那么该层中的类就都需要载核心配置文件,来获取SqlSessionFactory
SQL连接工厂对象,所以就可以将SqlSessionFactory
封装为一个工具类。所以在完善Service
层之前需要先在util
包下将工具类SqlSessionFactoryUtils
创建好,代码如下:
package at.guigu.util; 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 { //静态代码快会随着类的加载而自动执行,且只执行一次 try { //配置mybatis-config.xml文件路径。注意:若该文件直接在resources目录下,则直接写文件名即可 String resource = "mybatis-config.xml"; //利用Resources类中的静态方法将配置文件加载到内存 InputStream inputStream = Resources.getResourceAsStream(resource); //获取SqlSessionFactory对象 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } public static SqlSessionFactory getSqlSessionFactory() { return sqlSessionFactory; } }
Step1: 在service
包下创建BrandService
类来调用mapper
包下的BrandMapper
接口中的方法,代码如下
注意:获取SqlSessionFactory对象的代码放在了成员变量的位置,这样所有方法可共用该对象,并不需要重复获取
package at.guigu.service; import at.guigu.mapper.BrandMapper; import at.guigu.pojo.Brand; import at.guigu.util.SqlSessionFactoryUtils; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import java.io.IOException; import java.util.List; public class BrandService { //1 获取SqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory(); public List<Brand> getAll() throws IOException { //2 获取SqlSession对象,执行SQL语句 //2.1 获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //2.2 获取Mapper接口UserMapper的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //2.3 执行sql语句 List<Brand> brands = brandMapper.selectAll(); sqlSession.close(); return brands; } }
Web层
Step1:由于是通过单击页面index.html
上查询所有
从而显示出查询数据,所以首先要创建一个index.html
页面,代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/BrandDemo/selectAllServlet">查询所有</a>
</body>
</html>
Step2:创建SelectAllServlet
类,且代码如下
BrandService
对象应将其放在成员变量的位置,因为对于大工程来说可能会多次用到Service
对象package at.guigu.web; import at.guigu.pojo.Brand; import at.guigu.service.BrandService; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; import java.util.List; @WebServlet("selectAllServlet") public class SelectAllServlet extends HttpServlet { //1 创建一个私有的BrandService对象 private BrandService brandService = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //2 调用BrandService中的方法查询所有数据 List<Brand> brands = brandService.getAll(); //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); } }
Step3:在Web项目核心目录下创建brand.jsp,且代码如下
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <input type="button" value="新增"><br> <hr> <table border="1" cellspacing="0"> <tr> <th>序号</th> <th>品牌名称</th> <th>企业名称</th> <th>排序</th> <th>品牌介绍</th> <th>状态</th> <th>操作</th> </tr> <c:forEach items="${brands}" var="brand" varStatus="xuhao"> <tr align="center"> <td>${xuhao.count}</td> <td>${brand.brandName}</td> <td>${brand.companyName}</td> <td>${brand.ordered}</td> <td>${brand.description}</td> <c:choose> <c:when test="${brand.status==1}"> <td>启用</td> </c:when> <c:otherwise> <td>禁用</td> </c:otherwise> </c:choose> <td><a href="#">修改</a> <a href="#">删除</a></td> </tr> </c:forEach> </table> </body> </html>
三层架构都准备完毕后Tomcat启动该Web项目,Web项目启动成功后会默认运行index.html文件,然后单击查询所有
即可跳转到另一页面显示出查询数据,如图所示
解释
单击新增
按钮后跳转到添加品牌的页面(该页面为addBrand.jsp
),然后输入要添加的品牌信息后单击提交,提交后浏览器将请求数据提交到服务器的Servlet,然后将数据保存到数据库中,最后重新展示一下查询所有的页面,即可显示出最新的所有数据
各层需要做的工作如图所示
Dao层/Map层
Step1: BrandMapper
接口中写入添加数据的方法
package at.guigu.mapper; import at.guigu.pojo.Brand; import at.guigu.service.BrandService; import org.apache.ibatis.annotations.ResultMap; import org.apache.ibatis.annotations.Select; import java.util.List; public interface BrandMapper { //查询并返回所有商品 /*@Select("select * from tb_brand") @ResultMap("brandResultMap")*/ List<Brand> selectAll(); //添加商品 /* @Select("insert into tb_brand values(#{brandName},#{companyName},#{ordered},#{description},#{status})") */ void add(Brand brand); }
@ResultMap("brandResultMap")
,才能使结果映射生效(结果映射可详见MyBatis那一节)Step2: 在对应的SQL映射文件BrandMapper.xml
中写入SQL语句
<?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"> <!-- namespace:名称空间 --> <mapper namespace="at.guigu.mapper.BrandMapper"> <!--结果映射--> <resultMap id="brandResultMap" type="brand"> <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可--> <result column="brand_name" property="brandName"/> <result column="company_name" property="companyName"/> </resultMap> <!-- id:为sql语句的唯一标识 resultType:为对应sql语句执行完毕后返回结果的类型 --> <select id="selectAll" resultMap="brandResultMap"> select * from tb_brand; </select> <insert id="add"> insert into tb_brand values (null, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status}); </insert> </mapper>
Service层
工具类SqlSessionFactoryUtils
代码省略,详见查询所有中的SqlSessionFactoryUtils
代码
Step1: 在service包下创建BrandService类来调用mapper包下的BrandMapper接口中的方法,代码如下
package at.guigu.service; import at.guigu.mapper.BrandMapper; import at.guigu.pojo.Brand; import at.guigu.util.SqlSessionFactoryUtils; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import java.io.IOException; import java.util.List; public class BrandService { //1 获取SqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory(); /** * 查询所有 * @return * @throws IOException */ public List<Brand> getAll() throws IOException { //2 获取SqlSession对象,执行SQL语句 //2.1 获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //2.2 获取Mapper接口UserMapper的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //2.3 执行sql语句 List<Brand> brands = brandMapper.selectAll(); sqlSession.close(); return brands; } /** * 添加品牌 * @param brand */ public void add(Brand brand){ //2 获取SqlSession对象,执行SQL语句 //2.1 获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //2.2 获取Mapper接口UserMapper的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //2.3 执行添加品牌的sql语句 brandMapper.add(brand); //3 注意:增删改的SQL语句需要手动提交事务让其生效 sqlSession.commit(); //释放资源 sqlSession.close(); } }
Web层
Step1:在Web项目核心目录下创建addBrand.jsp
,且代码如下
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>添加品牌</title> </head> <body> <h3>添加品牌</h3> <!--action的属性值为浏览器提交到服务器的资源路径--> <form action="/BrandDemo/addServlet" method="post"> 品牌名称:<input name="brandName"><br> 企业名称:<input name="companyName"><br> 排序:<input name="ordered"><br> 描述信息:<testarea rows="5" cols="20" name="description"></testarea><br> 状态: <input type="radio" name="status" value="0">禁用 <input type="radio" name="status" value="1">禁用<br> <input type="submit" value="提交"> </form> </body> </html>
Step2:通过JavaScript
代码来为brand.jsp
中的新增
按钮添加鼠标单击事件 (可详见前端知识点汇总),单击新增
按钮后页面跳转到添加品牌的页面(即addBrand.jsp
)代码如下所示
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <input type="button" value="新增" id="add"><br> <hr> <table border="1" cellspacing="0"> <tr> <th>序号</th> <th>品牌名称</th> <th>企业名称</th> <th>排序</th> <th>品牌介绍</th> <th>状态</th> <th>操作</th> </tr> <c:forEach items="${brands}" var="brand" varStatus="xuhao"> <tr align="center"> <td>${xuhao.count}</td> <td>${brand.brandName}</td> <td>${brand.companyName}</td> <td>${brand.ordered}</td> <td>${brand.description}</td> <c:choose> <c:when test="${brand.status==1}"> <td>启用</td> </c:when> <c:otherwise> <td>禁用</td> </c:otherwise> </c:choose> <td><a href="#">修改</a> <a href="#">删除</a></td> </tr> </c:forEach> </table> <script> document.getElementById("add").onclick = function () { //addBrand.jsp的路径 location.href = "/BrandDemo/addBrand.jsp"; } </script> </body> </html>
Step3:创建AddServlet
类,且代码如下
package at.guigu.web; import at.guigu.pojo.Brand; import at.guigu.service.BrandService; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet("/addServlet") public class AddServlet extends HttpServlet { //1 创建一个私有的BrandService对象 private BrandService brandService = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //添加数据时注意要处理中文乱码问题 //处理post请求乱码 request.setCharacterEncoding("UTF-8"); //2 接收表单提交的数据并封装为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 = new Brand(); brand.setBrandName(brandName); brand.setCompanyName(companyName); //将字符串数字先转换为Integer类型在存入Brand中 brand.setOrdered(Integer.parseInt(ordered)); brand.setDescription(description); brand.setStatus(Integer.parseInt(status)); //3 调用brandService完成添加 brandService.add(brand); //转发到查询所有的Servlet request.getRequestDispatcher("/selectAllServlet").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
三层架构都准备完毕后Tomcat启动该Web项目,Web项目启动成功后会默认运行index.html
文件,然后单击查询所有
即可跳转到另一页面显示出查询数据,之后单击新增
按钮,填写完新增数据后单击提交按钮,数据被提交到数据库保存,然后页面会自动跳转到查询所有的页面,显示出所有品牌数据,如图所示
解释
单击对应品牌的修改
按钮后,会跳转到新的页面(该页面为update.jsp
),该页面会显示你要修改的品牌上次所保存的内容
各层需要做的工作如图所示
Dao层/Map层
Step1: BrandMapper
接口中写入修改数据的方法
package at.guigu.mapper; import at.guigu.pojo.Brand; import at.guigu.service.BrandService; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.ResultMap; import org.apache.ibatis.annotations.Select; import java.util.List; public interface BrandMapper { /*@Select("select * from tb_brand") @ResultMap("brandResultMap")*/ List<Brand> selectAll(); //@Insert("insert into tb_brand values (null, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status})") void add(Brand brand); //修改——回显数据 void selectById(int id); }
Step2: 在对应的SQL映射文件BrandMapper.xml
中写入SQL语句
<?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"> <!-- namespace:名称空间 --> <mapper namespace="at.guigu.mapper.BrandMapper"> <!--结果映射--> <resultMap id="brandResultMap" type="brand"> <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可--> <result column="brand_name" property="brandName"/> <result column="company_name" property="companyName"/> </resultMap> <!-- id:为sql语句的唯一标识 resultType:为对应sql语句执行完毕后返回结果的类型 --> <!--查询所有品牌--> <select id="selectAll" resultMap="brandResultMap"> select * from tb_brand; </select> <!--添加品牌--> <insert id="add"> insert into tb_brand values (null, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status}); </insert> <!--修改——回显数据:根据id查询--> <select id="selectById" resultMap="brandResultMap"> select * from tb_brand where id = #{id}; </select> </mapper>
Service层
工具类SqlSessionFactoryUtils
代码省略,详见查询所有中的SqlSessionFactoryUtils
代码
Step1: 在service包下创建BrandService类来调用mapper包下的BrandMapper接口中的方法,代码如下
package at.guigu.service; import at.guigu.mapper.BrandMapper; import at.guigu.pojo.Brand; import at.guigu.util.SqlSessionFactoryUtils; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import java.io.IOException; import java.util.List; public class BrandService { //1 获取SqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory(); /** * 查询所有 * @return * @throws IOException */ public List<Brand> getAll() throws IOException { //2 获取SqlSession对象,执行SQL语句 //2.1 获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //2.2 获取Mapper接口UserMapper的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //2.3 执行sql语句 List<Brand> brands = brandMapper.selectAll(); sqlSession.close(); return brands; } /** * 添加品牌 * @param brand */ public void add(Brand brand){ //2 获取SqlSession对象,执行SQL语句 //2.1 获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //2.2 获取Mapper接口UserMapper的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //2.3 执行添加品牌的sql语句 brandMapper.add(brand); //3 注意:增删改的SQL语句需要手动提交事务让其生效 sqlSession.commit(); //释放资源 sqlSession.close(); } /** * 修改——回显数据:根据id查询 * @param id * @return * @throws IOException */ public Brand selectById(int id) throws IOException { //2 获取SqlSession对象,执行SQL语句 //2.1 获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //2.2 获取Mapper接口UserMapper的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //2.3 执行修改——回显数据的sql语句 Brand brand = brandMapper.selectById(id); //释放资源 sqlSession.close(); return brand; } }
Web层
Step1:在Web项目核心目录下创建update.jsp
,且代码如下
<%-- Created by IntelliJ IDEA. User: 10195 Date: 2024/6/30 Time: 16:49 To change this template use File | Settings | File Templates. --%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>修改品牌</title> </head> <body> <h3>修改品牌</h3> <!--action的属性值为浏览器提交到服务器的资源路径--> <form action="/BrandDemo/addServlet" 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:choose> <c:when test="${brand.status == 0}"> <input type="radio" name="status" value="0" checked>禁用 <input type="radio" name="status" value="1">启用<br> </c:when> <c:otherwise> <input type="radio" name="status" value="0">禁用 <input type="radio" name="status" value="1" checked>启用<br> </c:otherwise> </c:choose> <input type="submit" value="提交"> </form> </body> </html>
Step2:通过JavaScript
代码来为brand.jsp
中的修改
按钮添加鼠标单击事件 (可详见前端知识点汇总),单击修改
按钮后页面会根据id
跳转到对应品牌的页面(即.jsp
),代码如下所示
<%-- Created by IntelliJ IDEA. User: 10195 Date: 2024/6/28 Time: 19:40 To change this template use File | Settings | File Templates. --%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>Title</title> </head> <body> <input type="button" value="新增" id="add"><br> <hr> <table border="1" cellspacing="0"> <tr> <th>序号</th> <th>品牌名称</th> <th>企业名称</th> <th>排序</th> <th>品牌介绍</th> <th>状态</th> <th>操作</th> </tr> <c:forEach items="${brands}" var="brand" varStatus="xuhao"> <tr align="center"> <td>${xuhao.count}</td> <td>${brand.brandName}</td> <td>${brand.companyName}</td> <td>${brand.ordered}</td> <td>${brand.description}</td> <c:choose> <c:when test="${brand.status==1}"> <td>启用</td> </c:when> <c:otherwise> <td>禁用</td> </c:otherwise> </c:choose> <td><a href="/BrandDemo/selectByIdServlet?id=${brand.id}">修改</a> <a href="#">删除</a></td> </tr> </c:forEach> </table> <script> document.getElementById("add").onclick = function () { //addBrand.jsp的路径 location.href = "/BrandDemo/addBrand.jsp"; } </script> </body> </html>
Step3:创建SelectByIdServlet
类,且代码如下
package at.guigu.web; import at.guigu.pojo.Brand; import at.guigu.service.BrandService; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet("/selectByIdServlet") public class SelectByIdServlet extends HttpServlet { //1 创建一个私有的BrandService对象 private BrandService brandService = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //2 接收id String id = request.getParameter("id"); //3 调用对应的Service查询 Brand brand = brandService.selectById(Integer.parseInt(id)); //4 将该Brand对象存储到request域中 request.setAttribute("brand", brand); //5 转发到update.jsp中 request.getRequestDispatcher("/update.jsp").forward(request,response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
三层架构都准备完毕后Tomcat启动该Web项目,Web项目启动成功后会默认运行index.html
文件,然后单击查询所有
即可跳转到另一页面显示出查询数据,之后单击修改
按钮后会自动跳转到修改品牌页面,如图所示
解释:修改数据是在回显数据的基础上进行操作的,即对update.jsp
页面的表单进行修改后单击提交
按钮,将数据保存到数据库中,最后重现展示一下查询所有的页面,即可显示出最新的所有数据
各层需要做的工作如图所示
Dao层/Map层
Step1: BrandMapper
接口中写入修改数据的方法
package at.guigu.mapper; import at.guigu.pojo.Brand; import at.guigu.service.BrandService; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.ResultMap; import org.apache.ibatis.annotations.Select; import java.util.List; public interface BrandMapper { /*@Select("select * from tb_brand") @ResultMap("brandResultMap")*/ List<Brand> selectAll(); //@Insert("insert into tb_brand values (null, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status})") void add(Brand brand); /** * //修改——回显数据:根据id查询 * @param id * @return */ /*@Select("select * from tb_brand where id = #{id}") @ResultMap("brandResultMap")*/ Brand selectById(int id); //修改——修改数据 void update(Brand brand); }
Step2: 在对应的SQL映射文件BrandMapper.xml
中写入SQL语句
<?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"> <!-- namespace:名称空间 --> <mapper namespace="at.guigu.mapper.BrandMapper"> <!--结果映射--> <resultMap id="brandResultMap" type="brand"> <!--由于id为主键,且数据库中的字段名和对应结果映射的目标类中的属性名一样,所以此处不需要主键映射,只需进行非主键映射即可--> <result column="brand_name" property="brandName"/> <result column="company_name" property="companyName"/> </resultMap> <!-- id:为sql语句的唯一标识 resultType:为对应sql语句执行完毕后返回结果的类型 --> <!--查询所有品牌--> <select id="selectAll" resultMap="brandResultMap"> select * from tb_brand; </select> <!--添加品牌--> <insert id="add"> insert into tb_brand values (null, #{brandName}, #{companyName}, #{ordered}, #{description}, #{status}); </insert> <!--修改——回显数据:根据id查询--> <select id="selectById" resultMap="brandResultMap"> select * from tb_brand where id = #{id}; </select> <!--修改——修改数据--> <update id="update"> update tb_brand set brand_name=#{brandName}, company_name=#{companyName}, ordered=#{ordered}, description=#{description}, status=#{status} where id=#{id}; </update> </mapper>
Service层
工具类SqlSessionFactoryUtils
代码省略,详见查询所有中的SqlSessionFactoryUtils
代码
Step1: 在service包下创建BrandService类来调用mapper包下的BrandMapper接口中的方法,代码如下
package at.guigu.service; import at.guigu.mapper.BrandMapper; import at.guigu.pojo.Brand; import at.guigu.util.SqlSessionFactoryUtils; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import java.io.IOException; import java.util.List; public class BrandService { //1 获取SqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory(); /** * 查询所有 * @return * @throws IOException */ public List<Brand> getAll() throws IOException { //2 获取SqlSession对象,执行SQL语句 //2.1 获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //2.2 获取Mapper接口UserMapper的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //2.3 执行sql语句 List<Brand> brands = brandMapper.selectAll(); sqlSession.close(); return brands; } /** * 添加品牌 * @param brand */ public void add(Brand brand){ //2 获取SqlSession对象,执行SQL语句 //2.1 获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //2.2 获取Mapper接口UserMapper的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //2.3 执行添加品牌的sql语句 brandMapper.add(brand); //3 注意:增删改的SQL语句需要手动提交事务让其生效 sqlSession.commit(); //释放资源 sqlSession.close(); } /** * 修改——回显数据:根据id查询 * @param id * @return */ public Brand selectById(int id){ //2 获取SqlSession对象,执行SQL语句 //2.1 获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //2.2 获取Mapper接口UserMapper的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //2.3 执行修改——回显数据的sql语句 Brand brand = brandMapper.selectById(id); //释放资源 sqlSession.close(); return brand; } /** * 修改——修改数据 * @param brand */ public void update(Brand brand) { //2 获取SqlSession对象,执行SQL语句 //2.1 获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); //2.2 获取Mapper接口UserMapper的代理对象 BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class); //2.3 执行修改——修改数据的sql语句 brandMapper.update(brand); //3 注意:增删改的SQL语句需要手动提交事务让其生效 sqlSession.commit(); //释放资源 sqlSession.close(); } }
Web层
Step1:修改在回显数据内容中的update.jsp
,代码如下
<%-- Created by IntelliJ IDEA. User: 10195 Date: 2024/6/30 Time: 16:49 To change this template use File | Settings | File Templates. --%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>修改品牌</title> </head> <body> <h3>修改品牌</h3> <!--action的属性值为浏览器提交到服务器的资源路径--> <form action="/BrandDemo/updateServlet" method="post"> <%--通过隐藏域提交id,作用:隐藏id的提交--%> <input type="hidden" name="id" value="${brand.id}"> 品牌名称:<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:choose> <c:when test="${brand.status == 0}"> <input type="radio" name="status" value="0" checked>禁用 <input type="radio" name="status" value="1">启用<br> </c:when> <c:otherwise> <input type="radio" name="status" value="0">禁用 <input type="radio" name="status" value="1" checked>启用<br> </c:otherwise> </c:choose> <input type="submit" value="提交"> </form> </body> </html>
Step2:通过JavaScript
代码来为brand.jsp
中的修改
按钮添加鼠标单击事件 (可详见前端知识点汇总),单击修改
按钮后页面会根据id
跳转到对应品牌的页面(即.jsp
),代码详见回显数据部分内容
Step3:创建UpdateServlet
类,且代码如下
package at.guigu.web; import at.guigu.pojo.Brand; import at.guigu.service.BrandService; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.IOException; @WebServlet("/updateServlet") public class UpdateServlet extends HttpServlet { //1 创建一个私有的BrandService对象 private BrandService brandService = new BrandService(); @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //添加数据时注意要处理中文乱码问题 //处理post请求乱码 request.setCharacterEncoding("UTF-8"); //2 接收表单提交的修改数据并封装为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 = new Brand(); brand.setId(Integer.parseInt(id)); brand.setBrandName(brandName); brand.setCompanyName(companyName); //将字符串数字先转换为Integer类型在存入Brand中 brand.setOrdered(Integer.parseInt(ordered)); brand.setDescription(description); brand.setStatus(Integer.parseInt(status)); //3 调用brandService完成修改 brandService.update(brand); //转发到查询所有的Servlet request.getRequestDispatcher("/selectAllServlet").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
三层架构都准备完毕后Tomcat启动该Web项目,Web项目启动成功后会默认运行index.html
文件,然后单击查询所有
即可跳转到另一页面显示出查询数据,之后单击修改
按钮后会自动跳转到修改品牌页面,修改完数据后单击提交
按钮,数据被提交到数据库保存,然后页面会自动跳转到查询所有的页面,显示出所有品牌数据,如图所示
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。