Day58.Thmeleaf CRUD练习 — Sorldier 士兵表单

目录

一、项目架构图

二、需要实现的功能列表

三、实现代码

1. 动态网页(Template实现)

2. 表述层 (Servlet | Template)

3. 业务逻辑层 (service)

4. 持久化层(数据访问层 DAO)

5. 其他代码

web.xml配置参数

ViewBaseServlet (Template基础视图类)

JDBCUtils (Druid数据库连接池)

BaseDaoImpl (DAO通用的增删改查)

四、页面效果展示


难点:通过传递方法标识,反射获取方法,优化代码,将功能封装在一个Servlet 对象内。
           通过请求域,实现业务分层之间的数据传递。
           注意:定义Servlet时,不要写dogat、dopost方法,否则无法访问执行 ModelBase

一、项目架构图

二、需要实现的功能列表

  • 显示首页:浏览器通过index.html访问首页Servlet,然后再解析对应的模板视图

  • 显示列表:在首页点击超链接,跳转到目标页面把所有士兵的信息列表显示出来

  • 删除信息:在列表上点击删除超链接,执行信息的删除操作

  • 新增信息:

    • 在列表页面点击超链接跳转到新增士兵信息的表单页面

    • 在新增信息的表单页面点击提交按钮执行保存

  • 更新信息:

    • 在列表上点击更新超链接,跳转到更新士兵信息的表单页面:表单回显

    • 在更新信息的表单页面点击提交按钮执行更新

三、实现代码

1. 动态网页(Template实现)

首页 index.html
<html lang="en" xmlns:th="http://www.thymeleaf.org"> 空间声明
<body>
<h1>首页</h1>
<a th:href="@{/soldier(method='getAll')}">显示士兵列表</a>
</body>
士兵列表 AllSoldiers.html
<body>
<style 样式省略>

<h1>士兵列表</h1>

<table class="imagetable">
    <tr>
        <th>id</th>
        <th>名字</th>
        <th>武器</th>
        <th>删除</th>
        <th>更新</th>
    </tr>
    <tr th:each="s : ${soldiers}">
        <td th:text="${s.soldierId}"></td>
        <td th:text="${s.soldierName}"></td>
        <td th:text="${s.soldierWeapon}"></td>
        <!--携带id参数发起请求-->
        <td ><a th:href="@{/soldier(method='deleteSoldier',id=${s.soldierId})}">删除</a></td>
        <td><a th:href="@{/soldier(method='toUpdatePage',id=${s.soldierId})}">更新</a></td>
    </tr>
</table>
<!--因为Web—Inf内文件中无法直接访问,所以需要通过servlet跳转-->
<a th:href="@{/soldier(method='toAddPage')}">添加士兵</a>

</body>
<h1>添加士兵</h1>
<form action="soldier">
    <!--隐藏域,参数为调用的方法名-->
    <input type="hidden" name="method" value="addSoldier">

    <span>用户名</span><input type="text" name="soldierName">
    <spna>武器</spna><input type="text" name="soldierWeapon"> <br>
    <input type="submit">
</form>
<h1>修改士兵</h1>
<form action="soldier" align="center">
    <input type="hidden" name="method" value="updateSoldier">
    <!--隐藏域,不会显示到页面上,但是提交表单时会一起被提交-->
    <input type="hidden" name="soldierId" th:value="${soldier.soldierId}">
    <span>用户名</span><input type="text" name="soldierName" th:value="${soldier.soldierName}">
    <spna>武器</spna><input type="text" name="soldierWeapon" th:value="${soldier.soldierWeapon}">
    <input type="submit">
</form>

2. 表述层 (Servlet | Template)

优化:通过反射动态的获取Servlet,调用功能方法
public class ModelBaseServlet extends ViewBaseServlet {
    //通过反射获取、调用方法,优化Servlet结构
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            //解决乱码
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
            //1.this:当前正在请求的Servlet(关键)
            Class aClass = this.getClass();

            //2.获取方法名
            String method = request.getParameter("method");

            //3.通过反射获取方法,破坏私有结构
            Method declaredMethod = aClass.getDeclaredMethod(method,HttpServletRequest.class,HttpServletResponse.class);
            declaredMethod.setAccessible(true);

            //4.调用方法
            declaredMethod.invoke(this,request,response);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }
}
SoldierServlet 集成所有功能
public class SoldierServlet extends ModelBaseServlet {
    //由于不存在get方法,会自动调用父类 (ModelBaseServlet) 中的Get
    //通过反射获取调用对应功能方法

    //查看列表
    private void getAll(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("------- AllSoldierServlet -------");

        //1.创建业务层对象
        SoldierService soldierService = new SoldierServiceImpl();
        //2.调用业务层查询所有方法
        List<Soldier> allSolider = soldierService.fubdAllSolider();

        //3.将集合添加到请求域中
        request.setAttribute("soldiers",allSolider);
        processTemplate("AllSoldiers",request,response);
    }

    //跳转到修改页面的功能
    private void toUpdatePage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("------- ToUpDataSoldierServlet -------");

        //1.获取参数id,调用业务层查询对象,最终目的是将数据携带到更新页面
        String sid = request.getParameter("id");
        int id = Integer.parseInt(sid);

        //2.调用业务层查询该对象
        SoldierServiceImpl soldierService = new SoldierServiceImpl();
        Soldier soldier = soldierService.getSoldierId(id);


        //3.将查询到的对象封装到请求域
        request.setAttribute("soldier",soldier);

        //4.请求转发到更新界面
        processTemplate("upSoldier",request,response);
    }
    
    //修改功能
    private void updateSoldier(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("------- updataSoldierServlet -------");
        try {
            //二、获取全部参数,封装为对象
            Map<String, String[]> map = request.getParameterMap();
            Soldier soldier = new Soldier();
            BeanUtils.populate(soldier,map);
            //三、获取业务逻辑层service对象,调用更新方法
            SoldierService soldierService = new SoldierServiceImpl();
            soldierService.upDataSoldier(soldier);

            //五、使用重定向跳转到士兵列表 (修改代码后修改重定向)
            response.sendRedirect(request.getContextPath()+"/soldier?method=getAll");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    

    //删除士兵的功能
    private void deleteSoldier(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("------- ToUpDataSoldierServlet -------");
        //1.获取参数ID,转为int类型
        String sid = request.getParameter("id");
        int id = Integer.parseInt(sid);
        System.out.println(id);

        //2.调用Service 业务逻辑层删除方法,传参id
        SoldierService soldierService = new SoldierServiceImpl();
        soldierService.deleteSolider(id);

        //3.重定向到列表
        response.sendRedirect(request.getContextPath()+"/soldier?method=getAll");
    }

    //跳转到添加页面
    private void toAddPage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("------- ToAddSoldierPageServlet -------");

        processTemplate("addSoldier",request,response);
    }

    //添加士兵的功能
    private void addSoldier(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("------- AddSoldierServlet -------");
        //1.获取请求参数
        Map<String, String[]> map = request.getParameterMap();

        //2.将参数封装为对象
        Soldier soldier = new Soldier();
        try {
            BeanUtils.populate(soldier,map);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(soldier);

        //3.创建业务层,调用添加士兵方法
        SoldierService soldierService = new SoldierServiceImpl();
        soldierService.saveSoldier(soldier);

        //4.使用重定向跳转到 AllSoldierServlet 防止重复添加
        response.sendRedirect(request.getContextPath()+"/soldier?method=getAll");
    }
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request,response);
    }
}
IndexServlet
public class IndexServlet extends ViewBaseServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("------- indexServlet -------");

        processTemplate("index",request,response);
    }

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

3. 业务逻辑层 (service)

接口 规范
public interface SoldierService {
    //查询所有
    List<Soldier> fubdAllSolider();
    //根据id查询
    Soldier getSoldierId(int id);
    //删除操作
    void deleteSolider(int id);
    //添加操作
    void saveSoldier(Soldier soldier);
    //更新操作
    void upDataSoldier(Soldier soldier);
}
实现类
public class SoldierServiceImpl implements SoldierService {
    //创建Dao数据访问层对象
    SoldierDaoImpl soldierDao = new SoldierDaoImpl();
    //查询所有
    @Override
    public List<Soldier> fubdAllSolider() {
        List<Soldier> list = soldierDao.getAll();
        return list;
    }
    //根据id查询
    @Override
    public Soldier getSoldierId(int id) {
        Soldier soldier = soldierDao.getById(id);
        return soldier;
    }
    //删除士兵
    @Override
    public void deleteSolider(int id) {
        soldierDao.deleteById(id);
    }
    //添加士兵
    @Override
    public void saveSoldier(Soldier soldier) {
        soldierDao.insertSoldier(soldier);
    }
   
    //更新
    @Override
    public void upDataSoldier(Soldier soldier) {
        soldierDao.updateSoldier(soldier);
    }
}

4. 持久化层(数据访问层 DAO)

public interface SoldierDao {
    //删除
    void deleteById(int soldierId);
    //新增
    void insertSoldier(Soldier soldier);
    //更新
    void updateSoldier(Soldier soldier);
    //查询所有
    List<Soldier> getAll();
    //根据id查询
    Soldier getById(int soldierId);
}
public class SoldierDaoImpl extends BaseDaoImpl implements SoldierDao {
    //删除
    @Override
    public void deleteById(int soldierId) {
        //注意 ? 没有引号
        String sql = "delete from t_soldier where soldier_id = ?";
        update(sql,soldierId);
    }
    //添加
    @Override
    public void insertSoldier(Soldier soldier) {
        String sql = "insert into t_soldier values(null,?,?)";
        update(sql,soldier.getSoldierName(),soldier.getSoldierWeapon());
    }
    //更新
    @Override
    public void updateSoldier(Soldier soldier) {
        String sql = "update t_soldier set soldier_name=?,soldier_weapon=? where soldier_id =?";
        update(sql,soldier.getSoldierName(),soldier.getSoldierWeapon(),soldier.getSoldierId());
    }
    //查询所有
    @Override
    public List<Soldier> getAll() {
        String sql = "select soldier_id soldierid,soldier_name soldiername,soldier_weapon soldierweapon from t_soldier";
        List<Soldier> all = findAll(Soldier.class, sql);
        return all;
    }
    //根据id查询
    @Override//起别名是为了令数据库的字段名 与 实体类属性名保持一致!
    public Soldier getById(int soldierId) {
        String sql = "SELECT soldier_id soldierid,soldier_name soldiername,soldier_weapon soldierweapon FROM t_soldier WHERE soldier_id=?";
        Soldier soldier = findOneBean(Soldier.class, sql, soldierId);
        return soldier;
    }
}

5. 其他代码

web.xml配置参数

    <!--配置Thymeleaf前后缀-->
    <context-param>
        <param-name>prefix</param-name>
        <param-value>/WEB-INF/view/</param-value>
    </context-param>
    <context-param>
        <param-name>suffix</param-name>
        <param-value>.html</param-value>
    </context-param>
    <!--万能士兵Servlet-->
    <servlet>
        <servlet-name>SoldierServlet</servlet-name>
        <servlet-class>com.atguigu.servlet.SoldierServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SoldierServlet</servlet-name>
        <url-pattern>/soldier</url-pattern>
    </servlet-mapping>
    <!--首页-->
    <servlet>
        <servlet-name>IndexServlet</servlet-name>
        <servlet-class>com.atguigu.servlet.IndexServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>IndexServlet</servlet-name>
        <url-pattern>/index.html</url-pattern>
    </servlet-mapping>

ViewBaseServlet (Template基础视图类)

/**
 * 视图基础类 本质还是一个Servlet
 */
public class ViewBaseServlet extends HttpServlet {

    private TemplateEngine templateEngine;

    @Override//在初始化中 读取全局上下文参数
    public void init() throws ServletException {

        // 1.获取ServletContext对象
        ServletContext servletContext = this.getServletContext();

        // 2.创建Thymeleaf解析器对象
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);

        // 3.给解析器对象设置参数
        // ①HTML是默认模式,明确设置是为了代码更容易理解
        templateResolver.setTemplateMode(TemplateMode.HTML);

        // ②设置前缀 (重要)
        String viewPrefix = servletContext.getInitParameter("prefix");

        templateResolver.setPrefix(viewPrefix);

        // ③设置后缀 (重要)
        String viewSuffix = servletContext.getInitParameter("suffix");

        templateResolver.setSuffix(viewSuffix);

        // ④设置缓存过期时间(毫秒)
        templateResolver.setCacheTTLMs(60000L);

        // ⑤设置是否缓存
        templateResolver.setCacheable(true);

        // ⑥设置服务器端编码方式
        templateResolver.setCharacterEncoding("utf-8");

        // 4.创建模板引擎对象
        templateEngine = new TemplateEngine();

        // 5.给模板引擎对象设置模板解析器
        templateEngine.setTemplateResolver(templateResolver);

    }

    /**
     * 进行视图解析(渲染)的方法
     * @param templateName 逻辑视图
     * @param req 请求
     * @param resp 响应
     * @throws IOException
     */
    protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 1.设置响应体内容类型和字符集
        resp.setContentType("text/html;charset=UTF-8");

        // 2.创建WebContext对象
        WebContext webContext = new WebContext(req, resp, getServletContext());

        // 3.处理模板数据
        templateEngine.process(templateName, webContext, resp.getWriter());
    }
}

JDBCUtils (Druid数据库连接池)

public class JDBCUtils {
    static DataSource dataSource;
    //ThreadLocal,每个线程独有,用于存储共享变量
    static ThreadLocal<Connection> local = new ThreadLocal<>();

    //静态代码块
    static {
        //属性集对象
        Properties pro = new Properties();
        try {
            //将配置文件信息 读取到属性集内  (将配置文件信息转为 字节流)
            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties"));
            //通过配置文件创建了链接对象
            dataSource = DruidDataSourceFactory.createDataSource(pro);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //通过连接池获取链接
    public static Connection getConnection() throws SQLException {

        Connection connection = local.get();
        //如果ThreadLocalMap内不存在,用连接池获取,存在则直接返回
        if(connection==null){
            //连接池获取
            connection = dataSource.getConnection();
            //放入ThreadLocal内
            local.set(connection);
        }
        return connection;
    }
    //关闭链接方法
    public static void closeConnectiopn() throws Exception{
        Connection connection = JDBCUtils.getConnection();
        //事务关闭,防止后面复用出现问题
        connection.setAutoCommit(true);
        //删除线程内存储的链接
        local.remove();

        connection.close();
    }
}

BaseDaoImpl (DAO通用的增删改查)

public class BaseDaoImpl {
    //通用的BaseDao 通用的增 删 改 查方法
    public void update(String sql,Object...params) {
        try {
            //1.获取链接
            Connection connection = JDBCUtils.getConnection();
            //2.创建queryRunner
            QueryRunner queryRunner = new QueryRunner();

            //3.执行操作
            queryRunner.update(connection,sql,params);

        } catch (SQLException e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 通用的查询多条数据
     * @param clazz  集合的泛型类型
     * @param sql
     * @param params 参数
     * @param <T>
     * @return
     */
    //不确定查询哪张表,加入泛型!!!!
    public <T> List<T> findAll(Class<T> clazz, String sql, Object... params) {
        try {
            //1.获取链接
            Connection connection = JDBCUtils.getConnection();
            //2.创建queryRunner
            QueryRunner queryRunner = new QueryRunner();

            List<T> query = queryRunner.query(connection, sql, new BeanListHandler<>(clazz), params);

            return query;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }
    /**
     * 通用的返回单个对象
     * @param clazz   bean的链接类型
     * @param sql
     * @param params  参数
     * @param <T>
     * @return
     */
    public <T> T findOneBean(Class<T> clazz, String sql, Object... params) {
        try {
            //1.获取链接
            Connection connection = JDBCUtils.getConnection();
            //2.创建queryRunner
            QueryRunner queryRunner = new QueryRunner();

            T bean = queryRunner.query(connection, sql, new BeanHandler<>(clazz), params);

            return bean;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }
    /**
     * 通用的查询单个值,暂未用到
     * @param sql
     * @param params
     * @return
     */
    public Object getSingleValue(String sql,Object...params){
        try {
            //1.获取链接
            Connection connection = JDBCUtils.getConnection();
            //2.创建queryRunner
            QueryRunner queryRunner = new QueryRunner();

            Object query = queryRunner.query(connection, sql, new ScalarHandler<>(), params);

            return query;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }
}

Mysql 建表 

CREATE TABLE t_soldier(
    soldier_id INT PRIMARY KEY AUTO_INCREMENT,
    soldier_name CHAR(100),
    soldier_weapon CHAR(100)
);

四、页面效果展示


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值