隐藏

javaweb各种框架组合案例(一):maven+spring+springMVC+jdbcTemplate

发布:2021/7/29 17:53:01作者:管理员 来源:本站 浏览次数:760

为了体现spring jdbc对于单表操作的优势,我专门对dao层做了一个抽离,使得抽离出的核心dao具有通用性。主要技术难点是对于泛型的反射。注意:单表操作中,数据库表的字段要和实体类的属性名保持高度一致,否则可能会出错。


1.整体项目结构




2.pom.xml

复制代码


<project xmlns="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>com.xiaog</groupId>

 <artifactId>music4j</artifactId>

 <version>0.0.1-SNAPSHOT</version>

 <packaging>war</packaging>

 

 <properties>


   <file.encoding>UTF-8</file.encoding>

   <spring.version>4.2.2.RELEASE</spring.version>

   <mysql.version>5.1.29</mysql.version>

   <servlet.version>3.0-alpha-1</servlet.version>

   <aspectj.version>1.8.1</aspectj.version>

   <commons-codec.version>1.9</commons-codec.version>

   <commons-dbcp.version>1.4</commons-dbcp.version>

   <hibernate.validator.version>5.0.2.Final</hibernate.validator.version>

   <jetty.version>8.1.8.v20121106</jetty.version>

   <slf4j.version>1.7.5</slf4j.version>

   <testng.version>6.8.7</testng.version>

   <maven.compiler.source>1.7</maven.compiler.source>

   <maven.compiler.target>1.7</maven.compiler.target>

 </properties>


 <dependencies>

   <dependency>

     <groupId>junit</groupId>

     <artifactId>junit</artifactId>

     <version>4.11</version>

     <scope>test</scope>

   </dependency>



   <!-- spring 依赖-->

   <dependency>

     <groupId>org.springframework</groupId>

     <artifactId>spring-beans</artifactId>

     <version>${spring.version}</version>

   </dependency>

   <dependency>

     <groupId>org.springframework</groupId>

     <artifactId>spring-context</artifactId>

     <version>${spring.version}</version>

   </dependency>

   <dependency>

     <groupId>org.springframework</groupId>

     <artifactId>spring-context-support</artifactId>

     <version>${spring.version}</version>

   </dependency>

   <dependency>

     <groupId>org.springframework</groupId>

     <artifactId>spring-jdbc</artifactId>

     <version>${spring.version}</version>

   </dependency>

   <dependency>

     <groupId>org.springframework</groupId>

     <artifactId>spring-webmvc</artifactId>

     <version>${spring.version}</version>

   </dependency>


   <dependency>

     <groupId>commons-dbcp</groupId>

     <artifactId>commons-dbcp</artifactId>

     <version>${commons-dbcp.version}</version>

   </dependency>

   <dependency>

     <groupId>mysql</groupId>

     <artifactId>mysql-connector-java</artifactId>

     <version>${mysql.version}</version>

   </dependency>

   <dependency>

     <groupId>javax.servlet</groupId>

     <artifactId>servlet-api</artifactId>

     <version>${servlet.version}</version>

     <scope>provided</scope>

   </dependency>

   <dependency>

     <groupId>org.aspectj</groupId>

     <artifactId>aspectjweaver</artifactId>

     <version>${aspectj.version}</version>

   </dependency>



   <dependency>

     <groupId>org.testng</groupId>

     <artifactId>testng</artifactId>

     <version>${testng.version}</version>

     <scope>test</scope>

   </dependency>

   <dependency>

     <groupId>org.springframework</groupId>

     <artifactId>spring-test</artifactId>

     <version>${spring.version}</version>

     <scope>test</scope>

   </dependency>


   <!-- https://mvnrepository.com/artifact/jstl/jstl -->

   <dependency>

     <groupId>jstl</groupId>

     <artifactId>jstl</artifactId>

     <version>1.1.2</version>

   </dependency>

   

    <!-- Logback -->

    <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->

    <dependency>

        <groupId>ch.qos.logback</groupId>

        <artifactId>logback-classic</artifactId>

        <version>1.2.3</version>

    </dependency>

    <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core -->

    <dependency>

        <groupId>ch.qos.logback</groupId>

        <artifactId>logback-core</artifactId>

        <version>1.2.3</version>

    </dependency>

    <!-- https://mvnrepository.com/artifact/org.logback-extensions/logback-ext-spring -->

    <dependency>

        <groupId>org.logback-extensions</groupId>

        <artifactId>logback-ext-spring</artifactId>

        <version>0.1.4</version>

    </dependency>

    <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->

    <dependency>

        <groupId>org.slf4j</groupId>

        <artifactId>slf4j-api</artifactId>

        <version>1.7.25</version>

    </dependency>

    <!-- https://mvnrepository.com/artifact/org.slf4j/jcl-over-slf4j -->

    <dependency>

        <groupId>org.slf4j</groupId>

        <artifactId>jcl-over-slf4j</artifactId>

        <version>1.7.25</version>

    </dependency>

 </dependencies>


 <build>

 <defaultGoal>compile</defaultGoal>

     <plugins>

        <plugin>

           <groupId>org.apache.maven.plugins</groupId>

           <artifactId>maven-compiler-plugin</artifactId>

           <version>3.1</version>

           <configuration>

           <source>1.8</source>

           <target>1.8</target>            

               <encoding>UTF-8</encoding>

           </configuration>

        </plugin>

       <plugin>

                   

                      <groupId>org.apache.tomcat.maven</groupId>

           <artifactId>tomcat7-maven-plugin</artifactId>

           <version>2.1</version>

           <configuration>

               <port>9999</port>

               <path>/music4j</path>

               <uriEncoding>UTF-8</uriEncoding>

               <finalName>music4j</finalName>

               <server>tomcat7</server>

           </configuration>

       </plugin>    

     

     </plugins>

 </build>

</project>    


复制代码






3.各配置文件


(1)spring-context.xml

复制代码


<?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.springframework.org/schema/beans"

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"

      xmlns:context="http://www.springframework.org/schema/context"

      xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"

      xsi:schemaLocation="http://www.springframework.org/schema/beans

      http://www.springframework.org/schema/beans/spring-beans-4.0.xsd

      http://www.springframework.org/schema/context

      http://www.springframework.org/schema/context/spring-context-4.0.xsd

      http://www.springframework.org/schema/tx

      http://www.springframework.org/schema/tx/spring-tx-4.0.xsd

      http://www.springframework.org/schema/aop

      http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">


   <!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 -->

   <context:component-scan base-package="com.music4j.dao"/>

   <context:component-scan base-package="com.music4j.service"/>


   <!-- 配置数据源 -->

   <bean id="dataSource"

         class="org.apache.commons.dbcp.BasicDataSource"

         destroy-method="close"

         p:driverClassName="com.mysql.jdbc.Driver"

         p:url="jdbc:mysql://localhost:3306/ssjdbc"

         p:username="root"

         p:password="root"

   />


   <!-- 配置Jdbc模板  -->

   <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"

         p:dataSource-ref="dataSource" />


   <!-- 配置事务管理器 -->

   <bean id="transactionManager"

         class="org.springframework.jdbc.datasource.DataSourceTransactionManager"

         p:dataSource-ref="dataSource" />


   <!-- 通过AOP配置提供事务增强,让service包下所有Bean的所有方法拥有事务 -->

   <aop:config proxy-target-class="true">

       <aop:pointcut id="serviceMethod"

                     expression="(execution(* com.music4j.service..*(..))) and (@annotation(org.springframework.transaction.annotation.Transactional))" />

       <aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" />

   </aop:config>

   <tx:advice id="txAdvice" transaction-manager="transactionManager">

       <tx:attributes>

           <tx:method name="*" />

       </tx:attributes>

   </tx:advice>


</beans>


复制代码






(2)spring-mvc.xml

复制代码


<?xml version="1.0" encoding="UTF-8" ?>

<beans xmlns="http://www.springframework.org/schema/beans"

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xmlns:p="http://www.springframework.org/schema/p"

      xmlns:context="http://www.springframework.org/schema/context"

      xsi:schemaLocation="http://www.springframework.org/schema/beans

      http://www.springframework.org/schema/beans/spring-beans-4.0.xsd

      http://www.springframework.org/schema/context

      http://www.springframework.org/schema/context/spring-context-4.0.xsd">


   <!--配置组件扫描 应用 sprnig 注解-->

   <context:component-scan base-package="com.music4j.controller"/>


   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"

         p:viewClass="org.springframework.web.servlet.view.JstlView"

         p:prefix="/"

         p:suffix=".jsp"

   />



</beans>


复制代码






(3)logback.xml

复制代码


<?xml version="1.0" encoding="UTF-8"?>

<configuration>

   <!-- 控制台输出 -->  

   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

      <!-- 日志输出编码 -->  

      <Encoding>UTF-8</Encoding>  

       <layout class="ch.qos.logback.classic.PatternLayout">  

            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->

           <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n  

           </pattern>  

       </layout>  

   </appender>  

   <!-- 日志输出级别 -->

   <root level="INFO">

       <appender-ref ref="STDOUT" />  

   </root>

</configuration>


复制代码






(4)web.xml

复制代码


<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">

 <display-name>music4j</display-name>

 

 <!-- spring配置文件 -->

     <context-param>

       <param-name>contextConfigLocation</param-name>

       <param-value>classpath:spring-context.xml</param-value>

   </context-param>  

 <!-- spring监听器 -->

     <listener>

       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

   </listener>

   

<!-- 字符编码过滤器   spring web自动提供一个 -->

   <filter>

       <filter-name>encodingFilter</filter-name>

       <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

       <init-param>

           <param-name>encoding</param-name>

           <param-value>UTF-8</param-value>

       </init-param>

       <init-param>

           <param-name>forceEncoding</param-name>

           <param-value>true</param-value>

       </init-param>

   </filter>

   <filter-mapping>

       <filter-name>encodingFilter</filter-name>

       <url-pattern>/*</url-pattern>

   </filter-mapping>

   

       


   <!-- spring  mvc 配置  【中央控制器/前端控制器/总控】 -->

   <servlet>  

       <servlet-name>spring-mvc</servlet-name>  

       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  

        <!-- 配置Spring mvc下的配置文件的位置和名称 -->

       <init-param>

            <param-name>contextConfigLocation</param-name>

            <param-value>classpath:spring-mvc.xml</param-value>

        </init-param>

       <load-on-startup>1</load-on-startup>

   </servlet>

   <!-- 可以配置扩展名,*.do -->  

   <servlet-mapping>  

       <servlet-name>spring-mvc</servlet-name>  

       <url-pattern>/</url-pattern>  

   </servlet-mapping>

 

      <!-- 添加日志监听器 -->  

   <context-param>  

       <param-name>logbackConfigLocation</param-name>  

       <param-value>classpath:logback.xml</param-value>  

   </context-param>  

   <listener>  

       <listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class>  

   </listener>

 

 <welcome-file-list>

   <welcome-file>index.jsp</welcome-file>

 </welcome-file-list>

 

</web-app>


复制代码






4.数据库

复制代码


create database ssjdbc;//创建ssjdbc数据库


//创建user表

CREATE TABLE `user` (

 `id` int(11) NOT NULL AUTO_INCREMENT,

 `username` varchar(32) DEFAULT NULL,

 `password` varchar(32) DEFAULT NULL,

 PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;


//插入数据3条

insert into user(username,password) values (1001,123),(1002,456),(1003,789);


复制代码




5.编写工具类SqlFactory,用于生成动态sql语句,类似mybatis的动态sql语句

复制代码


package com.music4j.util;


import java.lang.reflect.Field;

import java.util.HashMap;

import java.util.Map;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;


public class SqlFactory {


   private String tableName;

   

   public Object[] params;

   

   public SqlFactory(Class<?> clazz) {

       tableName = clazz.getSimpleName().toLowerCase();

   }

   

   private final static Logger logger = LoggerFactory.getLogger(SqlFactory.class);

   

   private Map<String,Object> objectToMap(Object entity) {

       Field[] fields = entity.getClass().getDeclaredFields();

       Map<String,Object> map = new HashMap<String,Object>();

       for(Field field : fields) {

           field.setAccessible(true);//设置属性可访问

           Object value = null;

           try {

               value = field.get(entity);

           } catch (IllegalArgumentException | IllegalAccessException e) {

               e.printStackTrace();

           }

           if(value != null) {

               map.put(field.getName(), value);

           }

       }

       return map;

   }

   

   public String getDeleteSql() {

       StringBuilder sql = new StringBuilder("delete from ").append(tableName).append(" where id = ?");

       logger.info(sql.toString());

       return sql.toString();

   }

   

   public String getSelectOneSql() {

       StringBuilder sql = new StringBuilder("select * from ").append(tableName).append(" where id = ?");

       logger.info(sql.toString());

       return sql.toString();

   }

   

   public String getInsertSql(Object entity) {

       Map<String,Object> map = this.objectToMap(entity);

       map.remove("id");

       params = new Object[map.size()];

       StringBuilder stringBuiler = new StringBuilder("insert into ").append(tableName).append("(");

       for(String key : map.keySet()) {

           stringBuiler.append(key).append(",");

       }

       stringBuiler.deleteCharAt(stringBuiler.length()-1).append(") values (");

       int i = 0;

       for(String key : map.keySet()) {

           stringBuiler.append("?,");

           params[i] = map.get(key);

           i++;

       }

       stringBuiler.deleteCharAt(stringBuiler.length()-1).append(")");

       map = null;

       logger.info(stringBuiler.toString());

       return stringBuiler.toString();

   }

   

   public String getUpdateSql(Object entity) {

       Map<String,Object> map = this.objectToMap(entity);

       params = new Object[map.size()];

       params[params.length-1] = map.remove("id");

       StringBuilder stringBuiler = new StringBuilder("update ").append(tableName).append(" set ");

       int i = 0;

       for(String key : map.keySet()) {

           stringBuiler.append(key).append("=?,");

           params[i] = map.get(key);

           i++;

       }

       stringBuiler.deleteCharAt(stringBuiler.length()-1).append(" where id = ?");

       map = null;

       logger.info(stringBuiler.toString());

       return stringBuiler.toString();

   }

   

   public String getSelectList(Object entity) {

       Map<String,Object> map = this.objectToMap(entity);

       map.remove("id");

       params = new Object[map.size()];

       StringBuilder stringBuiler = new StringBuilder("select * from ").append(tableName).append(" where ");

       int i = 0;

       for(String key : map.keySet()) {

           stringBuiler.append(key).append("=? and ");

           params[i] = map.get(key);

           i++;

       }

       stringBuiler.delete(stringBuiler.length()-4, stringBuiler.length());

       map = null;

       logger.info(stringBuiler.toString());

       return stringBuiler.toString();

   }

}


复制代码






6.编写核心dao接口及其实现类

复制代码


package com.music4j.core.dao;


import java.util.List;


public interface CoreDao<T> {

   int insert(T t);

   int delete(int id);

   int update(T t);

   T getOne(int id);

   List<T> getList(T t);

}


复制代码

复制代码


package com.music4j.core.dao.impl;


import java.lang.reflect.ParameterizedType;

import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.jdbc.core.BeanPropertyRowMapper;

import org.springframework.jdbc.core.JdbcTemplate;


import com.music4j.core.dao.CoreDao;

import com.music4j.util.SqlFactory;


public class CoreDaoImpl<T> implements CoreDao<T> {


   @Autowired

   private JdbcTemplate jdbcTemplate;

   

   private SqlFactory sqlFactory;

   

   private Class<T> clazz;

   

   @SuppressWarnings("unchecked")

   public CoreDaoImpl() {

       this.clazz =  (Class<T>)((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

       sqlFactory = new SqlFactory(this.clazz);

   }

   

   @Override

   public int insert(T t) {

       return jdbcTemplate.update(sqlFactory.getInsertSql(t),sqlFactory.params);

   }


   @Override

   public int delete(int id) {

       return jdbcTemplate.update(sqlFactory.getDeleteSql(),id);

   }


   @Override

   public int update(T t) {

       return jdbcTemplate.update(sqlFactory.getUpdateSql(t),sqlFactory.params);

   }


   @Override

   public T getOne(int id) {

       return jdbcTemplate.queryForObject(sqlFactory.getSelectOneSql(), new BeanPropertyRowMapper<T>(clazz),id);

   }


   @Override

   public List<T> getList(T t) {

       return jdbcTemplate.query(sqlFactory.getSelectList(t),new BeanPropertyRowMapper<T>(clazz),sqlFactory.params);

   }


}


复制代码






7.编写实体类dao接口及其实现,因为已经有了核心接口和实现,所以只需继承即可

复制代码


package com.music4j.dao;


import com.music4j.core.dao.CoreDao;

import com.music4j.entity.User;


public interface UserDao extends CoreDao<User> {

}


复制代码

复制代码


package com.music4j.dao.impl;


import org.springframework.stereotype.Repository;


import com.music4j.core.dao.impl.CoreDaoImpl;

import com.music4j.dao.UserDao;

import com.music4j.entity.User;


@Repository

public class UserDaoImpl extends CoreDaoImpl<User> implements UserDao {


}


复制代码






8.编写service接口及其实现

复制代码


package com.music4j.service;


import com.music4j.entity.User;


public interface UserService {

   User login(User user);

}


复制代码

复制代码


package com.music4j.service.impl;


import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;


import com.music4j.dao.UserDao;

import com.music4j.entity.User;

import com.music4j.service.UserService;


@Service

public class UserServiceImpl implements UserService {


   @Autowired

   private UserDao userDao;

   

   @Override

   public User login(User user) {

       List<User> users = userDao.getList(user);

       if(users!=null&&users.size()>0) {

           return users.get(0);

       }else {

           return null;

       }

   }


}


复制代码






9.编写controller

复制代码


package com.music4j.controller;


import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping;


import com.music4j.entity.User;

import com.music4j.service.UserService;


@Controller

@RequestMapping("/user")

public class UserController {

   

   @Autowired

   private UserService userService;

   

   @RequestMapping(value = "/login",params= {"username","password","username!=","password!="})

   public String login(Model model,User user) {

       user = userService.login(user);

       System.out.println("user="+user);

       model.addAttribute("user", user);

       return "result";

   }

   

}


复制代码






10.编写jsp页面测试登录


(1)index.jsp

复制代码


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!doctype html>

<html>

<head>

<meta charset="UTF-8">

<title>Insert title here</title>

</head>

<body>

   <form action="user/login" method="post">

       <div>

           <label>username</label>

           <input type="text" name="username"/>

       </div>

       <div>

           <label>password</label>

           <input type="password" name="password"/>

       </div>

       <div>

           <input type="submit" value="登录">

       </div>

   </form>

</body>

</html>


复制代码






(2)result.jsp

复制代码


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!doctype html>

<html>

<head>

<meta charset="UTF-8">

<title></title>

</head>

<body>

   username=${user}

</body>

</html>


复制代码