spring项目篇12---网上商城之配置以及工具类的编写

Posted yangshixiong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring项目篇12---网上商城之配置以及工具类的编写相关的知识,希望对你有一定的参考价值。

这个项目用到jdbc技术,研究了一下,为了学习一下,对于执行sql语句,自己进行封装工具类来进行处理,这样便于进一步理解。

首先我们来看一下搭建的基本项目结构

技术图片

 

 我们接下来看一下相关的配置信息:

首先看一下web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--解决post乱码问题-->
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!--设置UTF-8编码-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--配置servlet的前端控制器-->
    <servlet>
        <servlet-name>mySpringMvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--指定servlet的配置文件,默认情况下servlet的配置文件在/WEB-INF/${servlet-name}-servlet.xml文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <!--这个就是指定项目初识启动时就要初始化-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--配置拦截请求-->
    <servlet-mapping>
        <!--指定控制器-->
        <servlet-name>mySpringMvc</servlet-name>
        <!--拦截所有请求,不包括jsp,但是包括所有js,css,png等-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

接下来看一下我们的spring 的配置文件applicationContext.xml

    <!--配置注解扫描-->
    <context:component-scan base-package="com.yang" />
    <!--因为配置了静态文件,spring不会自动为我们加载HandlerMapping与HandlerAdapter,因此需要进行初始化-->
    <mvc:annotation-driven />

    <!--配置静态文件-->
    <mvc:resources location="WEB-INF/static/images" mapping="/images/**" />
    <mvc:resources location="WEB-INF/static/js" mapping="/js/**" />
    <mvc:resources location="WEB-INF/static/css" mapping="/css/**" />

    <!--上传文件配置-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8" />
        <property name="maxUploadSize" value="5120" />
    </bean>
    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/page/" />
        <property name="suffix" value=".jsp" />
    </bean>

为了进行封装JDBC的增删改查,我们首先先封装一下JDBC查询出的结果集

首先定义一个接口,定义一下我们的这个结果集如何进行处理IResultSetHandler

package com.yang.handler;

import java.sql.ResultSet;

/**
 * 定义结果集的处理函数
 *
 * @param <T> 范型,指定处理类型
 */
public interface IResultSetHandler<T> {
    T handle(ResultSet rs) throws Exception;
}

接下来对于单一以及列表的Bean进行处理

BeanHandler

package com.yang.handler;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.sql.ResultSet;

/**
 * 设置查询单一类型的结果集处置方法
 *
 * @param <T> 范型
 */
public class BeanHandler<T> implements IResultSetHandler<T> {
    private Class<T> classType;

    // 构造函数,设置当前类型的类
    public BeanHandler(Class<T> classType) {
        this.classType = classType;
    }

    // 处理函数
    @Override
    public T handle(ResultSet rs) throws Exception {
        // 结果集有结果开始处理
        if (rs.next()) {
            // 1。实例化一个当前处理类型的对象
            T obj = this.classType.getDeclaredConstructor().newInstance();
            // 2。获取这个类型信息,属性, Object.class就是删除那个默认的class的属性
            BeanInfo beanInfo = Introspector.getBeanInfo(this.classType, Object.class);
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                // 从结果集中,获取对应的属性值
                Object object = rs.getObject(propertyDescriptor.getName());
                // 利用反射,调用set方法,为对象赋值
                propertyDescriptor.getWriteMethod().invoke(obj, object);
            }
            return obj;
        }
        return null;
    }
}

BeanListHandler

package com.yang.handler;


import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class BeanListHandler<T> implements IResultSetHandler<List<T>> {
    private Class<T> classType;

    public BeanListHandler(Class<T> classType) {
        this.classType = classType;
    }

    @Override
    public List<T> handle(ResultSet rs) throws Exception {
        // 1。初始化一个列表,存储我们的对象
        List<T> list = new ArrayList<>();
        while (rs.next()) {
            // 2。实例化一个当前处理类型的对象
            T obj = this.classType.getDeclaredConstructor().newInstance();

            // 3。获取这个类型信息,属性, Object.class就是删除那个默认的class的属性
            BeanInfo beanInfo = Introspector.getBeanInfo(this.classType, Object.class);
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                // 4。从结果集中,获取对应的属性值
                Object object = rs.getObject(propertyDescriptor.getName());
                // 5。利用反射,调用set方法,为对象赋值
                propertyDescriptor.getWriteMethod().invoke(obj, object);
            }
            // 6。向列表添加对象
            list.add(obj);
        }
        return list;
    }
}

我们使用的是德鲁伊连接池,我们直接将其的获取数据库连接以及关闭连接记性封装,避免进行重复操作

JdbcUtil

package com.yang.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JdbcUtil {
    // 声明一个数据库资源,方便后续进行操作
    public static DataSource ds = null;

    static {
        // 1. 初始化读取资源文件
        Properties properties = new Properties();
        try {
            // 2. 读取mysql的配置信息到内存中
            FileInputStream fileInputStream = new FileInputStream("resources/mysql.properties");
            // 3. 转化配置信息
            properties.load(fileInputStream);
            // 4。 生成德鲁伊数据库连接吃池
            ds = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 从数据库连接中获取连接对象
    public static Connection getConn(){
        try{
            return ds.getConnection();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 关闭数据库连接对象,释放资源,数据库连接池关闭对象就会把连接放回池中,而不是关闭
     * @param conn 连接对象
     * @param st  连接语句
     * @param rs  查询结果集
     */
    public  static void close(Connection conn, Statement st, ResultSet rs){
        // 关闭结果集
        if(rs!=null){
            try{
                rs.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        // 关闭查询
        if(st!=null){
            try{
                st.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        // 关闭连接对象
        if(conn!=null){
            try{
                conn.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
    }


}

为了对数据的增删改查进行封装,为进一步学习,我们自己进行封装

CRUDTemplete

package com.yang.util;

import com.yang.handler.IResultSetHandler;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**
 * 为了方便学习,自己封装一个JDBC的增删改查的工具类,等同于dbUtil
 */
public class CRUDTemplate {
    private static Connection conn = null;
    private static PreparedStatement ps = null;
    private static ResultSet rs = null;

    static {
        conn = JdbcUtil.getConn();
    }

    // 这个执行增删改操作,params必须与sql语句中的位置一一对应
    public static int executeUpdate(String sql, Object... params) {

        try {
            assert conn != null;
            ps = conn.prepareStatement(sql);
            // 使用prepareStatement的方法为指定位置添加传入参数
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i + 1, params[i]);
            }
            return ps.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 最终关闭资源
            JdbcUtil.close(conn, ps, rs);
        }
        // 如果有报错,则返回0
        return 0;
    }

    // 执行查询操作
    public static <T> T executeQuery(String sql, IResultSetHandler<T> rh, Object... params) {
        try {
            // 预执行sql语句
            ps = conn.prepareStatement(sql);
            // 将参数传入预执行语句
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i + 1, params[i]);
            }
            // 执行sql语句并获取结果集
            rs = ps.executeQuery();
            // 调用传入的结果集处理方法,进行处理
            return rh.handle(rs);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.close(conn, ps, rs);
        }
        return null;
    }
}

我们首先来看一下user的dao层对象应当如何编写

IUserDao

package com.yang.dao;

import com.yang.domain.User;

public interface IUserDao {
    // 保存用户
    boolean save(User user);

    // 删除用户,接受值int
    boolean delete(Integer id);

    // 更新用户
    boolean update(Integer id, User user);

    // 获取用户
    User get(Integer id);

    User get(String username);
}

接下来看一下UserDao的实现类

UserDaoImpl

package com.yang.dao.impl;

import com.yang.dao.IUserDao;
import com.yang.domain.User;
import com.yang.handler.BeanHandler;
import com.yang.handler.IResultSetHandler;
import com.yang.util.CRUDTemplate;

import java.sql.ResultSet;

public class UserDaoImpl implements IUserDao {
    // 新建用户
    @Override
    public boolean save(User user) {
        // 创建sql语句
        String sql = "insert into user(name, password, avatar_url, sex) values(?,?,?,?)";
        // 使用工具类进行查询
        int result = CRUDTemplate.executeUpdate(sql, user.getUsername(), user.getPassword(), user.getAvatarUrl(), user.getSex());
        return result == 1;
    }

    // 根据id删除用户
    @Override
    public boolean delete(Integer id) {
        String sql = "delete from user where id = ?";
        int result = CRUDTemplate.executeUpdate(sql, id);
        return result == 1;
    }

    // 根据用户id以及上传的用户信息,进行修改用户信息
    @Override
    public boolean update(Integer id, User user) {
        String sql = "update user set name = ?, password = ?, avatar_url = ?, sex = ? where id = ?";
        int result = CRUDTemplate.executeUpdate(sql, user.getUsername(), user.getPassword(), user.getAvatarUrl(), user.getSex(), id);
        return result == 1;
    }

    // 根据id查询单个用户信息
    @Override
    public User get(Integer id) {
        String sql = "select * from user where id = ?";
        return CRUDTemplate.executeQuery(sql, new BeanHandler<User>(User.class), id);
    }

    // 根据用户名查询单个用户信息
    @Override
    public User get(String username) {
        String sql = "select * from user where name = ?";
        return CRUDTemplate.executeQuery(sql, new BeanHandler<User>(User.class), username);
    }
}

这个就是简单的配置信息,如后续有需要,在添加其他配置。

github地址:GitHub

看一下引入的jar包

技术图片

 

以上是关于spring项目篇12---网上商城之配置以及工具类的编写的主要内容,如果未能解决你的问题,请参考以下文章

spring boot 项目登录模块之身份验证

spring项目篇15 --- 商城小项目创建订单以及查看所有订单

Spring Boot 入门之基础篇

Spring Cloud Alibaba商城实战项目基础篇(day03)

Spring Cloud Alibaba商城实战项目基础篇(day03)

一起学Spring之Web基础篇