Java+Servlet+Jsp(el, jstl)+MyBatis的CRUD练习小项目

1 概述

这篇博客主要是分享一个基于Servlet+Jsp(el, jstl)+MyBatis的CRUD练习小项目。包括项目的源码,以及项目的逻辑。通过这个项目能够学习Java web中最基础的servlet,jsp和mybatis的使用,为后续Spring的学习打下基础。项目源代码
关键词:javaweb基础,servlet,jsp,mybatis;

2 系统展示

在这里插入图片描述
(图片要是看不清可以右键新标签打开)

3 功能实现

基本的增删改查功能,项目采样web层、service层和dao层,三层架构。每个功能的实现都是从dao层开始,然后是web层,最后才是service层。

3.1 环境准备

  1. 创建web项目,导入依赖。(使用idea创建项目可以看我的这篇博客:IDEA创建Maven web项目以及Tomcat部署项目的方法
  2. 创建三层架构的包,web,service,dao
  3. 创建数据库表tb_brand
  4. 创建pojo类,Brand类
  5. 配置MyBatis的基础环境,主要三步:配置MyBatis-config.xml,SQL的映射文件BrandMapper.xml(本项目中的sql语句比较简单,用的是注解开发),创建BrandMapper接口。

3.2 查询-查询所有记录

逻辑:通过点击“查询所有”跳转到SelectAllServlet,然后调用service,service会调用mapper。
在这里插入图片描述
首先创建mapper接口,并编写selectAll()。

    @Select("select * from tb_brand")
    @ResultMap("brandResultMap")
    List<Brand> selectAll();

因为是简单的sql语句,所以使用注解开发。注意,select返回的数据库的字段与pojo的属性名并不一致,所以通过在BrandMapper.xml中的resultMap进行映射。

    <resultMap id="brandResultMap" type="Brand">
        <result column="brand_name" property="brandName"/>
        <result column="company_name" property="companyName"/>
    </resultMap>

column表示数据库中的字段,property表示brand类的属性名。
完成Dao层后,编写service层,创建一个BrandService类,添加一个selectAll()。

    public List<Brand> selectAll(){


        SqlSession sqlSession = sqlSessionFactory.openSession();

        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        List<Brand> brands = mapper.selectAll();

        sqlSession.close();

        return brands;
    }

这里使用了SqlSessionFactory工厂创建sqlSession,工厂只需要创建一次并且每个service方法中都要使用工厂,所以将这部分功能抽象成一个工具类SqlSessionFactoryUtils

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;}

service层完成后,先编写前端的jsp页面(brand.jsp)。在这里只展示关键部分。通过jstl的<c:forEach>标签从servlet中读取selectAll()方法的返回结果,并遍历出来。

    <c:forEach items="${brands}" var="brand" varStatus="status">
        <tr align="center">
                <%--      <td>${brand.id}</td>--%>
            <td>${status.count}</td>
            <td>${brand.brandName}</td>
            <td>${brand.companyName}</td>
            <td>${brand.ordered}</td>
            <td>${brand.description}</td>

            <c:if test="${brand.status == 1}">
                <td>启用</td>
            </c:if>
            <c:if test="${brand.status == 0}">
                <td>禁用</td>
            </c:if>
            <td><a href="#">修改</a> <a href="#">删除</a></td>
        </tr>
    </c:forEach>

最后实现servlet

@WebServlet("/selectAllServlet")
public class SelectAllServlet extends HttpServlet {
    
    private BrandService service = new BrandService();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 调用service的selectAll()
        List<Brand> brands = service.selectAll();
        // 将查询结果封装值req
        req.setAttribute("brands", brands);
        // 将req请求转发至brand.jsp,brand.jsp就能通过el表达式从req中读取数据
        req.getRequestDispatcher("/brand.jsp").forward(req, resp);
    }

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

3.3 增加-增加一条记录

逻辑:通过点击“修改”按钮,跳转到addBrand.jsp页面,在该页面中的表单填写新记录,最后通过“提交”按钮,将数据传到addServlet,addServlet会调用service,service会调用mapper接口中的add方法。
在这里插入图片描述
同样,先写Dao层。在mapper接口中创建add()方法。

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

在BrandService中编写add()方法

    public void add(Brand brand){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
        mapper.add(brand);
        sqlSession.commit();
        sqlSession.close();
    }

先写前端页面,在brand.jsp中的“新增”按钮绑定事件,然后事件触发后跳转到addBrand.jsp
按钮:

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

通过id绑定事件

<script>
    document.getElementById("add").onclick = function (){
        location.href = "/ServletAndJspCRUDDemo/addBrand.jsp"
    }
</script>

addBrand.jsp就是一个表单,信息填完后,表单会提交到AddServlet

<form action="/ServletAndJspCRUDDemo/addservlet" method="post">
    品牌名称:<input name="brandName"><br>
    企业名称:<input name="companyName"><br>
    排序:<input name="ordered"><br>
    描述信息:<textarea rows="5" cols="20" name="description"></textarea><br>
    状态:
    <input type="radio" name="status" value="0">禁用
    <input type="radio" name="status" value="1">启用<br>

    <input type="submit" value="提交">
</form>

最后编写AddServlet

@WebServlet("/addservlet")
public class AddServlet extends HttpServlet {
    private BrandService service = new BrandService();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // addBrand.jsp的表单通过req传递到servlet,servlet从req获取相应的参数,参数的键就是表单的name。
        req.setCharacterEncoding("utf-8");  // 防止中文乱码
        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");

        // 从req中获取的参数,封装成一个brand实例
        Brand brand = new Brand();
        brand.setBrandName(brandName);
        brand.setCompanyName(companyName);
        brand.setOrdered(Integer.parseInt(ordered));
        brand.setDescription(description);
        brand.setStatus(Integer.parseInt(status));

        // 调用service的方法
        service.add(brand);

        // 处理完后重新将请求转发到“查询所有”页面
        req.getRequestDispatcher("/selectAllServlet").forward(req,resp);
    }

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

3.4 修改-修改记录

修改功能的实现分两步,第一步是点击修改按钮后,要重新读取数据,然后在前端页面显示出来。第二步是修改完成后,重新提交。

3.4.1 数据返显

在这里插入图片描述
Dao层

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

Service层

    public Brand selectById(int id){

        SqlSession sqlSession = sqlSessionFactory.openSession();

        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        Brand brand = mapper.selectById(id);

        sqlSession.close();

        return brand;
    }

先写前端。
点击修改按钮后,首先要获得当条记录的id,所以在brand.jsp中的“修改”按钮中传递id

<a href="/ServletAndJspCRUDDemo/selectByIdServlet?id=${brand.id}">修改</a>

SelectByIdServlet

@WebServlet("/selectByIdServlet")
public class SelectByIdServlet extends HttpServlet {

    private BrandService service = new BrandService();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String id = req.getParameter("id");
        Brand brand = service.selectById(Integer.parseInt(id));
        req.setAttribute("brand", brand);
        req.getRequestDispatcher("/update.jsp").forward(req, resp);

    }

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

最后会将请求转发至update.jsp

<form action="/ServletAndJspCRUDDemo/updateServlet" method="post">

    <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>

这是个表单,通过el表达式从req中读取数据,还使用了jstl的<c:if>标签做判断。

3.4.2 修改提交

在这里插入图片描述
在前端页面完成信息编辑后,通过点击提交按钮,将新记录提交到后台,实质使用的是update sql。
Dao层

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

Service层

    public void update(Brand brand){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
        mapper.update(brand);
        sqlSession.commit();
        sqlSession.close();
    }

update.jsp中的表单会提交到UpdateServlet

@WebServlet("/updateServlet")
public class UpdateServlet extends HttpServlet {
    private BrandService service = new BrandService();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        req.setCharacterEncoding("utf-8");

        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();
        brand.setId(Integer.parseInt(id));
        brand.setBrandName(brandName);
        brand.setCompanyName(companyName);
        brand.setOrdered(Integer.parseInt(ordered));
        brand.setDescription(description);
        brand.setStatus(Integer.parseInt(status));

        service.update(brand);

        req.getRequestDispatcher("/selectAllServlet").forward(req,resp);
    }

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

3.4 删除-删除一条记录

Dao层

    @Delete("delete from tb_brand where id = #{id}")
    void delete(int id);

Service层

    public void delete(int id){

        SqlSession sqlSession = sqlSessionFactory.openSession();

        BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);

        mapper.delete(id);
        sqlSession.commit();
        sqlSession.close();
    }

前端页面,与“修改”类似,需要获取当条记录的id,通过brand.jsp页面的删除按钮绑定。

<a href="/ServletAndJspCRUDDemo/deleteServlet?id=${brand.id}">删除</a></td>

DeleteServlet

@WebServlet("/deleteServlet")
public class DeleteServlet extends HttpServlet {
    private BrandService brandService = new BrandService();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String id = req.getParameter("id");
        brandService.delete(Integer.parseInt(id));
        req.getRequestDispatcher("/selectAllServlet").forward(req, resp);
    }

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

4 小结

完结撒花!
项目比较简单,但涵盖了web端最基本的增删改查功能,可以用来练习。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值