最近刚入门后端,对不起,我背叛了游戏【哭】
跟着写了一个这样的案例
网页界面是这样的
没写删除,里面带有增加行和修改表单数据的功能
web方面就三个页面,里面涉及到了Mybatis,Tomcat,JSP,Servlet,Maven,前端三剑客等知识,东西比较杂,我也是速通选手,掌握不太稳固,所以写个文章巩固一下知识点,以便自己能够更好地理解代码以及运行逻辑。
项目结构是这样的,需要配置mybatis-config.xml文件,pom.xml需要引入tomcat、Servlet,mybatis,JSP,Maven写个标识就能自动下载了,Maven好方便
以及Mapper配置文件和web配置文件,不是很复杂。
我们的代码方面
一、前端页面
三个前端页面分别是这样的
brand:主页面
<%@ 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> <input type="button" value="新增" id="add"><br> <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"> //items:被遍历的容器 //var:遍历产生的临时变量 //varStatus:遍历状态对象 //我们这里是从SelectAllServlet跳转过来的,所以接收了request域,我们只管调brand对象输出数据就行 <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}">//这里是JSP,就是if判断 <td>启用</td> </c:if> <c:if test="${brand.status != 1}"> <td>禁用</td> </c:if> <td><a href="/brandDemo/selectByIdServlet?id=${brand.id}">修改</a> <a href="#">删除</a></td> </tr> </c:forEach> </table> <script> document.getElementById("add").onclick = function (){ location.href = "/brandDemo/addBrand.jsp"; }//这里使用getElementById设置了按钮的点击事件。 </script> </body> </html>
addBrand:新增数据
<%@ 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="/brandDemo/addServlet" method="post">//这里我们提交到addServlet服务,还是以POST形式,然后addServlet再转发到brand.jsp页面 品牌名称:<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>
update:修改数据
<%@ 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="/brandDemo/updateServlet" method="post">//这里还是一样的,提交到updateServlet服务当中 //这里跟新增表单页面没什么大的不同,但是Servlet方面就要先查询再修改,还是比新增麻烦的 <%--隐藏域,提交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: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>
二、mybatis操作方面
既然处理数据肯定是要学习mybatis的
操作不难,写几个接口就行
这里则是使用到mapper的知识,不得不说,javaweb学的东西是真的杂,学的时候天天导包配文件,累。
BrandMapper:
package com.itheima.mapper; import com.itheima.pojo.Brand; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.ResultMap; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import java.util.List; public interface BrandMapper {//这里也没啥好说的,以注解形式操纵数据库,都是一些基础操作语句 //唯一值得注意的是当我们两种模式命名有冲突的时候我们要配置ResultMap //使得我们Brand查询的时候能找到对应的变量 /* 查询所有 @return */ @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); /** * 修改 * @param 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); }
brand数据类:
package com.itheima.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; //提供了三种构造方法以备不同情况,是一些面向对象的特性,Java学过的都能懂 public Brand() { } public Brand(Integer id, String brandName, String companyName, String description) { this.id = id; this.brandName = brandName; this.companyName = companyName; this.description = description; } 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 + '}'; } }
三、Servlet服务
这里就是处理数据的大头了
因为创建工厂类只用一次就能最节省资源,所以我们用一个SqlSessionFactoryUtils静态类来封装好,下次直接调函数就行了,这里还是操作mybatis的东西
package com.itheima.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{//这里是数据库连接必写的三句 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); }catch (IOException e){ e.printStackTrace(); } } public static SqlSessionFactory getSqlSessionFactory(){ return sqlSessionFactory;//用的时候直接调这个方法 } }
随后写BrandService,这里是将对数据的操作全都封装好,免得到时候麻烦
代码是这样的
package com.itheima.service; import com.itheima.mapper.BrandMapper; import com.itheima.pojo.Brand; import com.itheima.util.SqlSessionFactoryUtils; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import java.util.List; 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();//这里就是操作数据库,然后封装到一个brands列表里 sqlSession.close(); return brands;//返回查询到的值 } /** * 添加 * @param brand */ public void add(Brand brand){//这里是添加 //2. 获取SqlSession SqlSession sqlSession = factory.openSession(); //3. 获取BrandMapper BrandMapper mapper = sqlSession.getMapper(BrandMapper.class); //4. 调用方法 mapper.add(brand);//往数据库里添加一个brand对象 //提交事务 sqlSession.commit(); //释放资源 sqlSession.close(); } /** * 根据id查询 * @return */ public Brand selectById(int id){//依靠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; } /** * 修改 * @param 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(); } }
然后是Servlet服务类
通过这些服务我们来操作网页里的数据
SelectAllServlet:
package com.itheima.web; import com.itheima.pojo.Brand; import com.itheima.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("/selectAllServlet")//这里我们通过标签访问Servlet public class SelectAllServlet extends HttpServlet { private BrandService service = new BrandService();//先创建一个Brand服务对象 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1、调用BrandService完成查询 List<Brand> brands = service.selectAll();//这里我们直接调用查询 //2、存入request域中 req.setAttribute("brands",brands);//存入request域,到时候发出去的就是这个,要查询的话只要调用键查值就行了,request域都是键值对。 //3、转发到brand.jsp req.getRequestDispatcher("/brand.jsp").forward(req,resp);//这里我们调用getrequestDispatcher方法转发到brand.jsp页面中,再通过JSP代码把数据显示出来。 } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp);//这样写能同时响应POST请求和GET请求 } }
AddServlet:
package com.itheima.web; import com.itheima.pojo.Brand; import com.itheima.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("/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); } }
SelectById:
package com.itheima.web; import com.itheima.pojo.Brand; import com.itheima.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("/selectByIdServlet") public class SelectByIdServlet extends HttpServlet { private BrandService service = new BrandService(); @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1、接受id String id = req.getParameter("id"); //2、调用service查询 Brand brand = service.selectById(Integer.parseInt(id)); //3、存储到request中 req.setAttribute("brand",brand); //4、转发到update.jsp req.getRequestDispatcher("/update.jsp").forward(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
Updateservlet:
package com.itheima.web; import com.itheima.pojo.Brand; import com.itheima.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("/updateServlet") public class UpdateServlet extends HttpServlet { private BrandService service = new BrandService(); @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //处理POST请求的乱码问题 req.setCharacterEncoding("utf-8"); //1、接受表单提交的数据 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 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、调用serice完成修改 service.update(brand); //3、转发到查询所有Servlet req.getRequestDispatcher("/selectAllServlet").forward(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req, resp); } }
代码差不多就这样了,做完发现东西还挺多的,面向对象要写的东西还是挺多的。
下面是逻辑的梳理,说实话梳理逻辑确实是要花上一些时间
展现brand页面:通过查询tb_brand和JSP以及HTML、CSS来展现出数据库里的数据
访问顺序:SelectAll.class->brand.jsp
新增数据:填写表单数据->在数据库中实现添加->addServlet->selectAllServlet->发送到brand.jsp->展现数据
访问顺序:brand.jsp->AddServlet.class->update.jsp->SelectAllServlet.class->brand.jsp
修改数据:通过查询当前id所对应的表将其发送到update.jsp0界面->填写修改后的数据->提交表单数据->在数据库中实现修改->查询所有->brand.jsp展现数据
访问顺序:brand.jsp->SelectByIdServlet->update.jsp->updateServlet->SelectAllServlet->brand.jsp