java从入门到精通二十三(三层架构完成增删改查)
前言
这里是看了一点jsp的,顺便过了一下,不是特别熟悉,因为现在这种技术是比较落后了,但是作为学习的过程也就学了下。
因为技术不是现在很常用,所以我没有单独做出笔记。将前段的一些知识,后端的一些知识简单结合一下,作为这个阶段的一个简单的练习。
虽然简单但是知识还是很值得注意,因为实现的前后端涉及到原理性的东西,还有零碎的知识点,所以自己就记录下来。
简单看了下mvc和三层架构的思想。我没有研究很深,但是看的出来是一种分而治之得思想,就是各自实现各自的功能,使得功能之间的服务更加有条理,而不是混在一块。
上面的是mvn模式,下面对应的是三层架构。我们就是从数据访问层和业务逻辑层和表现层的思维去进行编程。
我们的目的是实现一个前后端结合的项目,完成一个增删改查的操作,将表单在前端页面上进行展示。
具体的可以看下面的展示。
环境准备
创建web项目结构
这里当然可以选择骨架
我选择不用骨架
这是创建好后这个pom配置文件
然后我们给它配置war打包方式。
这是我们目前的结构,然后我们需要补齐一些目录和配置
我们打开项目结构来看,然后选中Facets,然后我们看到我们新建的这个没有被认作是web模块。
那我们就添加上去,点击加号,然后选择web。
然后把你的模块添加进去
连续点击确认
然后我们点击这里。
然后下面最好选择3.0之后的版本
然后后面的确认就好。
现在我们再看项目目录,在做小的改造。这个项目结构还是不太正确
我们先把web拖到main下
然后将WEB-INF拖到web下面
这样就基本改造完成。
这里我们在说明了一遍自己创建web项目结构的过程。之前我们都说过,包括骨架。这里就再复习一遍。
导入依赖和配置文件
下面这个是我们目前项目需要使用的所有依赖。
需要注意的是,一定要注意scope的作用域,非常重要,设置不当可能会导致冲突还有就是检测不到等异常。
需要操作数据库。mysql的驱动包
要使用mybatis框架。mybaits的依赖包
web项目需要用到servlet和jsp。servlet和jsp的依赖包需要使用 jstl 进行数据展示。jstl的依赖包
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>brand-demo01</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.9</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.29</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version><scope>provided</scope></dependency><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><plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.2</version></plugin></plugins></build></project>
需要一个mybatis核心配置文件,我们把它放到rescorces下面。
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPEconfigurationPUBLIC"-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><settings><!-- 开启自动驼峰命名规则映射 --><settingname="mapUnderscoreToCamelCase"value="true"/></settings><!--起别名--><typeAliases><packagename="com.jgdabc.pojo"/></typeAliases><environmentsdefault="development"><environmentid="development"><transactionManagertype="JDBC"/><dataSourcetype="POOLED"><propertyname="driver"value="com.mysql.cj.jdbc.Driver"/><propertyname="url"value="jdbc:mysql:///mysql?serverTimezone=GMT"/><propertyname="username"value="root"/><propertyname="password"value="123456"/></dataSource></environment></environments><mappers><!--扫描mapper--><packagename="com.jgdabc.mapper"/></mappers></configuration>
基本的两个配置,其他的配置我们还有在构建mapper的还需要一个xml文件。
创建层次模型
然后我们创建这样的层次包结构。
webapp下面存放jsp等前端页面。在java下面创建存放接口mapper的接口代码,还有一个实体pojo下存放brand类作为包装类。我们的属性在这里写。service里面就傻逼我们可以从这里调用的服务代码。util报下是将加载数据库核心配置文件单独封装。web下面就是我们的Servlet代码,具体实现后端的功能,包括增删改查等功能。
我们的web下面的Servlet和webapp下面的jsp等前端页面展示构成了表现层。像html或者jsp我们可以认为是视图,然后Servlet是控制器。我们的service包下的类提供业务逻辑的功能。mapper下面的接口类作为数据访问层。
我们的数据库的配置文件时一定要有的,因为将来我们需要去连接数据库,配置驱动等等。然后mapperMapper.xml在本次项目中没有发挥作用,因为简单的sql语句就在接口里面按照注解写好了。但是我们最好养成这样的习惯,因为将来我们的sql语句实际并没有这么简单。我们还是用到了代理。映射文件和接口文件的位置相对位置类位置一样。
实现查询
这些操作我们都需要和前后端结合,也就是需要在页面上展示,并不是仅仅在控制台输出。
创建一张数据库表。
-- 删除tb_brand表droptableifexists tb_brand;-- 创建tb_brand表createtable tb_brand
(-- id 主键
id intprimarykeyauto_increment,-- 品牌名称
brand_name varchar(20),-- 企业名称
company_name varchar(20),-- 排序字段
ordered int,-- 描述信息
description varchar(100),-- 状态:0:禁用 1:启用statusint);-- 添加数据insertinto tb_brand (brand_name, company_name, ordered, description,status)values('三只松鼠','三只松鼠股份有限公司',5,'好吃不上火',0),('华为','华为技术有限公司',100,'华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界',1),('小米','小米科技有限公司',50,'are you ok',1);SELECT*FROM tb_brand;
这是之前创建表表的代码,不过填写什么并没有关系,以为之后可以自己进行增删改查,并且删除的话,虽然在数据库中会出现id断层,但是在我前端展示还是非常正常。原因往后看。
我的数据库表现在被我已经删该为这样了。
这是我多次操作的结果,但是前端展示id还是连续的。
表创建以后我们需要一个实体类
packagecom.jgdabc.pojo;/**
* 品牌实体类
*/publicclassBrand{// id 主键privateInteger id;// 品牌名称privateString brandName;// 企业名称privateString companyName;// 排序字段privateInteger ordered;// 描述信息privateString description;// 状态:0:禁用 1:启用privateInteger status;publicBrand(){}publicBrand(Integer id,String brandName,String companyName,String description){this.id = id;this.brandName = brandName;this.companyName = companyName;this.description = description;}publicBrand(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;}publicIntegergetId(){return id;}publicvoidsetId(Integer id){this.id = id;}publicStringgetBrandName(){return brandName;}publicvoidsetBrandName(String brandName){this.brandName = brandName;}publicStringgetCompanyName(){return companyName;}publicvoidsetCompanyName(String companyName){this.companyName = companyName;}publicIntegergetOrdered(){return ordered;}publicvoidsetOrdered(Integer ordered){this.ordered = ordered;}publicStringgetDescription(){return description;}publicvoidsetDescription(String description){this.description = description;}publicIntegergetStatus(){return status;}publicvoidsetStatus(Integer status){this.status = status;}@OverridepublicStringtoString(){return"Brand{"+"id="+ id +", brandName='"+ brandName +'\''+", companyName='"+ companyName +'\''+", ordered="+ ordered +", description='"+ description +'\''+", status="+ status +'}';}}
mybatis 核心配置文件
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPEconfigurationPUBLIC"-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><settings><!-- 开启自动驼峰命名规则映射 --><settingname="mapUnderscoreToCamelCase"value="true"/></settings><!--起别名--><typeAliases><packagename="com.jgdabc.pojo"/></typeAliases><environmentsdefault="development"><environmentid="development"><transactionManagertype="JDBC"/><dataSourcetype="POOLED"><propertyname="driver"value="com.mysql.cj.jdbc.Driver"/><propertyname="url"value="jdbc:mysql:///mysql?serverTimezone=GMT"/><propertyname="username"value="root"/><propertyname="password"value="123456"/></dataSource></environment></environments><mappers><!--扫描mapper--><packagename="com.jgdabc.mapper"/></mappers></configuration>
映射文件,这个可有可无,只是因为我没有在这里面写sql。
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.jgdabc.mapper.BrandMapper"></mapper>
我们写BrandMapper这个接口,作为Dao层。
packagecom.jgdabc.mapper;importcom.jgdabc.pojo.Brand;importorg.apache.ibatis.annotations.Delete;importorg.apache.ibatis.annotations.Insert;importorg.apache.ibatis.annotations.Select;importorg.apache.ibatis.annotations.Update;importjava.util.List;publicinterfaceBrandMapper{@Select("select * from tb_brand")List<Brand>selectAll();}
做一个工具类
packagecom.jgdabc.util;importorg.apache.ibatis.io.Resources;importorg.apache.ibatis.session.SqlSessionFactory;importorg.apache.ibatis.session.SqlSessionFactoryBuilder;importjava.io.IOException;importjava.io.InputStream;publicclassSqlSessionFactoryUtils{privatestaticSqlSessionFactory sqlSessionFactory;static{//静态代码块会随着类的加载而自动执行,且只执行一次try{String resource ="mybatis-config.xml";InputStream inputStream =Resources.getResourceAsStream(resource);
sqlSessionFactory =newSqlSessionFactoryBuilder().build(inputStream);}catch(IOException e){
e.printStackTrace();}}publicstaticSqlSessionFactorygetSqlSessionFactory(){return sqlSessionFactory;}}
然后service包下,我们创建一个BrandService
packagecom.jgdabc.service;importcom.jgdabc.mapper.BrandMapper;importcom.jgdabc.pojo.Brand;importcom.jgdabc.util.SqlSessionFactoryUtils;importorg.apache.ibatis.session.SqlSession;importorg.apache.ibatis.session.SqlSessionFactory;importjava.util.List;publicclassBrandService{SqlSessionFactory factory =SqlSessionFactoryUtils.getSqlSessionFactory();publicList<Brand>selectAll(){SqlSession sqlSession = factory.openSession();BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);List<Brand> brands = mapper.selectAll();
sqlSession.close();return brands;}}
然后创建一个Servlet类
packagecom.jgdabc.web;importcom.jgdabc.pojo.Brand;importcom.jgdabc.service.BrandService;importjavax.servlet.*;importjavax.servlet.http.*;importjavax.servlet.annotation.*;importjava.io.IOException;importjava.util.List;@WebServlet("/selectAllServlet")publicclassSelectAllServletextendsHttpServlet{BrandService service =newBrandService();@OverrideprotectedvoiddoGet(HttpServletRequest request,HttpServletResponse response)throwsServletException,IOException{List<Brand> brands = service.selectAll();System.out.println(brands);// 存入request区域当中
request.setAttribute("brands",brands);// 转发到brand.jsp
request.getRequestDispatcher("/brand.jsp").forward(request,response);}@OverrideprotectedvoiddoPost(HttpServletRequest request,HttpServletResponse response)throwsServletException,IOException{this.doGet(request,response);}}
然后创建brand.jsp。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><body><inputtype="button"value="新增"id="add"><br><hr><tableborder="1"cellspacing="0"width="80%"><tr><th>序号</th><th>品牌名称</th><th>企业名称</th><th>排序</th><th>品牌介绍</th><th>状态</th><th>操作</th></tr><c:forEachitems="${brands}"var="brand"varStatus="status"><tralign="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:iftest="${brand.status == 1}"><td>启用</td></c:if><c:iftest="${brand.status != 1}"><td>禁用</td></c:if><td><ahref="/brand-demo01/selectByIdServlet?id=${brand.id}">修改</a><ahref="/brand-demo01/selectDeleteServlet?id=${brand.id}">删除</a></td></tr></c:forEach></table><script>
document.getElementById("add").onclick=function(){
location.href ="/brand-demo01/addBrand.jsp";}</script></body></html>
启动!
我们启动服务后默认会打开index.html,所以初始化我们就写在这里面
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><body><ahref="/brand-demo01/selectAllServlet">查询所有</a></body></html>
点击查询所有
我在核心配置文件中这样写就可以自动开启驼峰规则,这样就可以避免数据库字段和idea实体类字段不匹配导致查询不到结果的问题。
如果不这样处理的话,我们就需要在映射文件中这样写。
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.itheima.mapper.BrandMapper"><resultMapid="brandResultMap"type="brand"><resultcolumn="brand_name"property="brandName"></result><resultcolumn="company_name"property="companyName"></result></resultMap></mapper>
然后在接口中写一下返回类型(用注解)
@Select("select * from tb_brand")@ResultMap("brandResultMap")List<Brand>selectAll();
这样我们也可以将数据库字段和java驼峰命名法匹配起来。
未完续更
实现添加
我们首先在Dao层也就是mapper层写出这个接口方法。
packagecom.jgdabc.mapper;importcom.jgdabc.pojo.Brand;importorg.apache.ibatis.annotations.Delete;importorg.apache.ibatis.annotations.Insert;importorg.apache.ibatis.annotations.Select;importorg.apache.ibatis.annotations.Update;importjava.util.List;publicinterfaceBrandMapper{@Select("select * from tb_brand")List<Brand>selectAll();@Insert("insert into tb_brand values(null,#{brandName},#{companyName},#{ordered},#{description},#{status})")voidadd(Brand brand);@Select("select * from tb_brand where id = #{id}")}
然后在service里面调用
publicvoidadd(Brand brand){SqlSession sqlSession = factory.openSession();BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
mapper.add(brand);
sqlSession.commit();
sqlSession.close();}
记住我们的工具类封装。
packagecom.jgdabc.util;importorg.apache.ibatis.io.Resources;importorg.apache.ibatis.session.SqlSessionFactory;importorg.apache.ibatis.session.SqlSessionFactoryBuilder;importjava.io.IOException;importjava.io.InputStream;publicclassSqlSessionFactoryUtils{privatestaticSqlSessionFactory sqlSessionFactory;static{//静态代码块会随着类的加载而自动执行,且只执行一次try{String resource ="mybatis-config.xml";InputStream inputStream =Resources.getResourceAsStream(resource);
sqlSessionFactory =newSqlSessionFactoryBuilder().build(inputStream);}catch(IOException e){
e.printStackTrace();}}publicstaticSqlSessionFactorygetSqlSessionFactory(){return sqlSessionFactory;}}
然后我们需要写出这个添加的jsp
<%--
Created by IntelliJ IDEA.
User: jgdabc
Date: 2022/5/11
Time: 17:33
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>添加品牌</title></head><body><h3>添加品牌</h3><formaction="/brand-demo/addServlet"method="post"enctype="application/x-www-form-urlencoded">
品牌名称:<inputname="brandName"><br>
企业名称:<inputname="companyName"><br>
排序:<inputname="ordered"><br>
描述信息:<textarearows="5"cols="20"name="description"></textarea><br>
状态:
<inputtype="radio"name="status"value="0">禁用
<inputtype="radio"name="status"value="1">启用<br><inputtype="submit"value="提交"></form></body></html>
然后我们写这个Servlet。我们的Servlet从jsp前端获取到数据后我们再次回到查看全部数据的页面,这样可以查看到更新的数据。
packagecom.jgdabc.web;importcom.jgdabc.pojo.Brand;importcom.jgdabc.service.BrandService;importjavax.servlet.ServletException;importjavax.servlet.annotation.WebServlet;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;@WebServlet("/addServlet")publicclassAddServletextendsHttpServlet{privateBrandService service =newBrandService();@OverrideprotectedvoiddoGet(HttpServletRequest request,HttpServletResponse response)throwsServletException,IOException,IOException{//接收表单提交的数据,封装为brand对象// 处理乱码问题
request.setCharacterEncoding("utf-8");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");System.out.println("brandName"+brandName);//封装为一个Brand对象Brand brand =newBrand();
brand.setBrandName(brandName);
brand.setCompanyName(companyName);
brand.setOrdered(Integer.parseInt(ordered));
brand.setDescription(description);
brand.setStatus(Integer.parseInt(status));
service.add(brand);// 转发到查询所有Servlet//request.getRequestDispatcher("/selectAllServlet").forward(request, response);
response.sendRedirect("selectAllServlet");System.out.println("request");}@OverrideprotectedvoiddoPost(HttpServletRequest request,HttpServletResponse response)throwsServletException,IOException{System.out.println("post");doGet(request, response);}}
后面索性给brand.jsp加了个背景css。
属实比较丑陋
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title><linkhref="css/login.css"rel="stylesheet"></head><body><inputtype="button"value="新增"id="add"style="margin-left: -100px;margin-top: -300px;color: #50afeb"><br><hr><tableborder="1"cellspacing="0"width="80%"><tr><th>序号</th><th>品牌名称</th><th>企业名称</th><th>排序</th><th>品牌介绍</th><th>状态</th><th>操作</th></tr><c:forEachitems="${brands}"var="brand"varStatus="status"><tralign="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:iftest="${brand.status == 1}"><td>启用</td></c:if><c:iftest="${brand.status != 1}"><td>禁用</td></c:if><td><ahref="/brand-demo01/selectByIdServlet?id=${brand.id}">修改</a><ahref="/brand-demo01/selectDeleteServlet?id=${brand.id}">删除</a></td></tr></c:forEach></table><script>
document.getElementById("add").onclick=function(){
location.href ="/brand-demo01/addBrand.jsp";}</script></body></html>
具体的css还是我们之前用过的css布局
* {
margin: 0;
padding: 0;
}
html {
height: 100%;
width: 100%;
overflow: hidden;
margin: 0;
padding: 0;
background: url(../imgs/Desert.jpg) no-repeat 0px 0px;
background-repeat: no-repeat;
background-size: 100% 100%;
-moz-background-size: 100% 100%;
}
body {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
#loginDiv {
width: 37%;
display: flex;
justify-content: center;
align-items: center;
height: 300px;
background-color: rgba(75, 81, 95, 0.3);
box-shadow: 7px 7px 17px rgba(52, 56, 66, 0.5);
border-radius: 5px;
}
#name_trip {
margin-left: 50px;
color: red;
}
p {
margin-top: 30px;
margin-left: 20px;
color: azure;
}
input {
margin-left: 15px;
border-radius: 5px;
border-style: hidden;
height: 30px;
width: 140px;
background-color: rgba(216, 191, 216, 0.5);
outline: none;
color: #f0edf3;
padding-left: 10px;
}
#username{
width: 200px;
}
#password{
width: 202px;
}
.button {
border-color: cornsilk;
background-color: rgba(100, 149, 237, .7);
color: aliceblue;
border-style: hidden;
border-radius: 5px;
width: 100px;
height: 31px;
font-size: 16px;
}
#subDiv {
text-align: center;
margin-top: 30px;
}
#loginMsg{
text-align: center;color: aliceblue;
}
然后我们启动一下。
我们进行添加的话,可以在这里添加成功。
我们对启用禁用这样进行数据回显。我在添加这个jsp页面这样做。当我点击禁用的话,就给值为0,当我点击启用给值为1。然后这样提交给Servlet进行处理,然后在brand.jsp里面根据这些数值做一些回显。
注:未完续更
我相信总结逻辑细节十分重要的。
版权归原作者 兰舟千帆 所有, 如有侵权,请联系我们删除。