zoukankan      html  css  js  c++  java
  • 使用纯Java配置SSM框架实现基本的增删改查(不使用spring XML)

    前言

    本文不使用spring XML,而是采用Java配置SSM框架的形式实现了基本的增删改查。

    本文中的源码继承自https://www.cnblogs.com/hanzx/p/10016468.html中的程序,删除掉了webapp文件夹,里面的模板全部转移到resources下,其余文件均已删除。

    核心框架已升级。spring系列已升级使用5.0.1,mybatis使用3.4.5,mybatis-spring使用1.3.1。

    名词解释

    SSM框架:springMVC、spring、mybatis

    thymeleaf:一个与Velocity、FreeMarker类似的模板引擎

    jquery:一个快速、简洁的JavaScript框架

    程序结构

     

    程序源码

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <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>org.hanzx</groupId>
      <artifactId>webssmwithoutxml</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>war</packaging>
    
      <name>webssmwithoutxml Maven Webapp</name>
      <!-- FIXME change it to the project's website -->
      <url>http://www.example.com</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <spring.version>5.0.1.RELEASE</spring.version>
        <slf4j.version>1.6.6</slf4j.version>
        <log4j.version>1.2.12</log4j.version>
        <mysql.version>5.1.35</mysql.version>
        <jackson.version>2.9.2</jackson.version>
      </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-core</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-aop</artifactId>
          <version>${spring.version}</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aspects</artifactId>
          <version>${spring.version}</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-tx</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-web</artifactId>
          <version>${spring.version}</version>
        </dependency>
        <!--spring单元测试依赖 -->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-test</artifactId>
          <version>${spring.version}</version>
          <scope>test</scope>
        </dependency>
    
        <!-- spring webmvc相关jar -->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>${spring.version}</version>
        </dependency>
    
        <!-- mysql驱动包 -->
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>${mysql.version}</version>
        </dependency>
    
        <!-- alibaba data source 相关jar包-->
        <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>0.2.23</version>
        </dependency>
    
        <!-- alibaba fastjson 格式化对 -->
        <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>fastjson</artifactId>
          <version>1.1.41</version>
        </dependency>
    
        <!-- logback start -->
        <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>${log4j.version}</version>
        </dependency>
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
          <version>${slf4j.version}</version>
        </dependency>
        <dependency>
          <groupId>ch.qos.logback</groupId>
          <artifactId>logback-classic</artifactId>
          <version>1.1.2</version>
        </dependency>
        <dependency>
          <groupId>ch.qos.logback</groupId>
          <artifactId>logback-core</artifactId>
          <version>1.1.2</version>
        </dependency>
        <dependency>
          <groupId>org.logback-extensions</groupId>
          <artifactId>logback-ext-spring</artifactId>
          <version>0.1.1</version>
        </dependency>
    
        <!--mybatis依赖 -->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis</artifactId>
          <version>3.4.5</version>
        </dependency>
    
        <!-- mybatis/spring包 -->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis-spring</artifactId>
          <version>1.3.1</version>
        </dependency>
        <!-- 添加servlet3.0核心包 -->
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.0.1</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>javax.servlet.jsp-api</artifactId>
          <version>2.3.2-b01</version>
        </dependency>
        <!-- jstl -->
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
        </dependency>
        <!--thymeleaf-->
        <dependency>
          <groupId>org.thymeleaf</groupId>
          <artifactId>thymeleaf-spring5</artifactId>
          <version>3.0.9.RELEASE</version>
        </dependency>
    
    
        <!-- json -->
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-core</artifactId>
          <version>${jackson.version}</version>
        </dependency>
        <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <version>${jackson.version}</version>
        </dependency>
      </dependencies>
    
      <build>
        <finalName>webssmwithoutxml</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
          <plugins>
            <plugin>
              <artifactId>maven-clean-plugin</artifactId>
              <version>3.1.0</version>
            </plugin>
            <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
            <plugin>
              <artifactId>maven-resources-plugin</artifactId>
              <version>3.0.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.8.0</version>
            </plugin>
            <plugin>
              <artifactId>maven-surefire-plugin</artifactId>
              <version>2.22.1</version>
            </plugin>
            <plugin>
              <artifactId>maven-war-plugin</artifactId>
              <version>3.2.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-install-plugin</artifactId>
              <version>2.5.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-deploy-plugin</artifactId>
              <version>2.8.2</version>
            </plugin>
          </plugins>
        </pluginManagement>
      </build>
    </project>

    package-info.java(使用new-file创建的,用java class无法创建)

    /**package级别的注解。。。不配置的话,WebInitializer里的getServletMappings方法报黄*/
    @NonNullApi
    package org.hanzx.config;
    
    import org.springframework.lang.NonNullApi;

    springConfig.java

    package org.hanzx.config;
    
    import org.springframework.context.annotation.*;
    import org.springframework.stereotype.Controller;
    
    /**spring配置类
     * 注解扫描基础package,排除controller
     */
    @Configuration
    @ComponentScan(basePackages = {"org.hanzx"},
            excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class})})
    @Import(value = SpringMybatisConfig.class)
    public class SpringConfig {
    
    
    }

    SpringMvcConfig.java

    package org.hanzx.config;
    
    import org.hanzx.interceptors.CORSInterceptor;
    import org.springframework.context.annotation.*;
    import org.springframework.http.MediaType;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.accept.ContentNegotiationManagerFactoryBean;
    import org.springframework.web.servlet.config.annotation.*;
    import org.thymeleaf.spring5.SpringTemplateEngine;
    import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
    import org.thymeleaf.spring5.view.ThymeleafViewResolver;
    
    import java.util.Properties;
    
    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages = {"org.hanzx.controller"}, useDefaultFilters = false,
        includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class})})
    public class SpringMvcConfig implements WebMvcConfigurer {
    
        @Bean
        public ContentNegotiationManagerFactoryBean contentNegotiationManagerFactoryBean(){
            ContentNegotiationManagerFactoryBean contentNegotiationManagerFactoryBean = new ContentNegotiationManagerFactoryBean();
            //扩展名至mimeType的映射,即 /userEntity.json => application/json
            contentNegotiationManagerFactoryBean.setFavorPathExtension(true);
            //用于开启 /userinfo/123?format=json 的支持
            contentNegotiationManagerFactoryBean.setFavorParameter(true);
            contentNegotiationManagerFactoryBean.setParameterName("format");
            //是否忽略Accept Header
            contentNegotiationManagerFactoryBean.setIgnoreAcceptHeader(false);
            //扩展名到MIME的映射;favorPathExtension, favorParameter是true时起作用
            Properties properties = new Properties();
            properties.setProperty("json", "application/json");
            properties.setProperty("xml", "application/xml");
            properties.setProperty("html", "text/html");
            contentNegotiationManagerFactoryBean.setMediaTypes(properties);
            //默认的content type
            contentNegotiationManagerFactoryBean.setDefaultContentType(MediaType.TEXT_HTML);
            return contentNegotiationManagerFactoryBean;
        }
    
    //    这个是旧版用的,新版不要它
    //    /**当在web.xml 中   DispatcherServlet使用 <url-pattern>/</url-pattern> 映射时,能映射静态资源*/
    //    @Override
    //    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    //
    //    }
    
        /**静态资源映射*/
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/static/**").addResourceLocations("/static/");
        }
    
        /**对模型视图添加前后缀及其他*/
        @Bean
        public SpringResourceTemplateResolver springResourceTemplateResolver(){
            SpringResourceTemplateResolver springResourceTemplateResolver = new SpringResourceTemplateResolver();
            springResourceTemplateResolver.setPrefix("/templates/");
            springResourceTemplateResolver.setSuffix(".html");
            springResourceTemplateResolver.setCharacterEncoding("UTF-8");
            springResourceTemplateResolver.setOrder(1);
            springResourceTemplateResolver.setTemplateMode("HTML5");
            springResourceTemplateResolver.setCacheable(false);
            return springResourceTemplateResolver;
        }
    
        @Bean
        public SpringTemplateEngine springTemplateEngine(){
            SpringTemplateEngine springTemplateEngine = new SpringTemplateEngine();
            springTemplateEngine.setTemplateResolver(springResourceTemplateResolver());
            return springTemplateEngine;
        }
    
        @Bean
        public ThymeleafViewResolver thymeleafViewResolver(){
            ThymeleafViewResolver thymeleafViewResolver = new ThymeleafViewResolver();
            thymeleafViewResolver.setTemplateEngine(springTemplateEngine());
            thymeleafViewResolver.setCharacterEncoding("UTF-8");
            return thymeleafViewResolver;
        }
    
        /**拦截器 跨域拦截器*/
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new CORSInterceptor());
        }
    
    
        /**
         * 默认首页的设置,当输入域名是可以自动跳转到默认指定的网页
         */
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/").setViewName("index");
        }
    }

    SpringMybatisConfig.java

    package org.hanzx.config;
    
    import com.alibaba.druid.pool.DruidDataSource;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.annotation.MapperScan;
    import org.mybatis.spring.mapper.MapperScannerConfigurer;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.context.annotation.PropertySources;
    import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    import org.springframework.core.io.support.ResourcePatternResolver;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    import java.io.IOException;
    import java.sql.SQLException;
    
    
    @Configuration
    @PropertySource("classpath:jdbc.properties")
    @EnableTransactionManagement
    @MapperScan("org.hanzx.dao")//扫描mapper
    public class SpringMybatisConfig {
        @Value("${jdbc_driverClassName}")
        private String driverClassName;
        @Value("${jdbc_url}")
        private String url;
        @Value("${jdbc_username}")
        private String userName;
        @Value("${jdbc_password}")
        private String password;
        @Value("${initialSize}")
        private Integer initialSize;
        @Value("${minIdle}")
        private Integer minIdle;
        @Value("${maxActive}")
        private Integer maxActive;
        @Value("${maxWait}")
        private Long maxWait;
        @Value("${timeBetweenEvictionRunsMillis}")
        private Long timeBetweenEvictionRunsMillis;
        @Value("${minEvictableIdleTimeMillis}")
        private Long minEvictableIdleTimeMillis;
        @Value("${validationQuery}")
        private String validationQuery;
        @Value("${testWhileIdle}")
        private Boolean testWhileIdle;
        @Value("${testOnBorrow}")
        private Boolean testOnBorrow;
        @Value("${testOnReturn}")
        private Boolean testOnReturn;
        @Value("${poolPreparedStatements}")
        private Boolean poolPreparedStatements;
        @Value("${maxPoolPreparedStatementPerConnectionSize}")
        private Integer maxPoolPreparedStatementPerConnectionSize;
        @Value("${filters}")
        private String filters;
    
    //    这个无须使用,直接配@PropertySource注解就可以了
    //    /** 这个bean必须配置而且必须是静态方法,如果不配置就不能进行@Value的属性注入*/
    //    @Bean
    //    public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
    //        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
    //        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
    //        configurer.setLocation(resourcePatternResolver.getResource("classpath:jdbc.properties"));
    //        return configurer;
    //    }
    
    //    这个旧了,不再使用了,spring 3.1以后推荐使用PropertySourcesPlaceholderConfigurer
    //    @Deprecated
    //    @Bean
    //    public static PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() throws IOException {
    //        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
    //        PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
    //        configurer.setLocation(resourcePatternResolver.getResource("classpath:jdbc.properties"));
    //        return configurer;
    //    }
    
        /**配置数据源 ,使用的alibba的数据库*/
        @Bean(initMethod = "init", destroyMethod = "close")
        public DruidDataSource dataSource() throws SQLException {
            DruidDataSource druidDataSource = new DruidDataSource();
            druidDataSource.setDriverClassName(driverClassName);
            druidDataSource.setUrl(url);
            druidDataSource.setUsername(userName);
            druidDataSource.setPassword(password);
            druidDataSource.setInitialSize(initialSize);
            druidDataSource.setMinIdle(minIdle);
            druidDataSource.setMaxActive(maxActive);
            druidDataSource.setMaxWait(maxWait);
            druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
            druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
            druidDataSource.setValidationQuery(validationQuery);
            druidDataSource.setTestWhileIdle(testWhileIdle);
            druidDataSource.setTestOnBorrow(testOnBorrow);
            druidDataSource.setTestOnReturn(testOnReturn);
            druidDataSource.setPoolPreparedStatements(poolPreparedStatements);
            druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
            druidDataSource.setFilters(filters);
            return druidDataSource;
        }
    
        /** spring和MyBatis完美整合,不需要mybatis的配置映射文件 */
        @Bean
        public SqlSessionFactoryBean sqlSessionFactoryBean() throws SQLException, IOException {
            ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(dataSource());
            sqlSessionFactoryBean.setMapperLocations(resourcePatternResolver.getResources("classpath:mapper/*.xml"));
            return sqlSessionFactoryBean;
        }
    
        //不能使用这个,这东西先于properties加载,会导致properties文件读不出数据,改用@MapperScan扫描dao
    //    /**DAO接口所在包名,Spring会自动查找其下的类 ,自动扫描了所有的XxxxMapper.xml对应的mapper接口文件,
    //     * 只要Mapper接口类和Mapper映射文件对应起来就可以了*/
    //    @Bean
    //    public MapperScannerConfigurer mapperScannerConfigurer(){
    //        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
    //        mapperScannerConfigurer.setBasePackage("org.hanzx.dao");
    //        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean");
    //        return mapperScannerConfigurer;
    //    }
    
        /**(事务管理)transaction manager, use JtaTransactionManager for global tx 配置事务管理器*/
        @Bean
        public DataSourceTransactionManager dataSourceTransactionManager() throws SQLException {
            DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
            dataSourceTransactionManager.setDataSource(dataSource());
            return dataSourceTransactionManager;
        }
    }

    WebInitializer.java

    package org.hanzx.config;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
    
    /**
     * 在Servlet3.0以上的环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类,如果发现则用它来配置 * Servlet容器,Spring提供了这个接口的实现名为SpringServletContainerInitializer,这个类反过来又会查找实现了 * WebApplicationInitializer的类并把配置任务交给它们来完成,AbstractAnnotationConfigDispatcherServletInitializer的祖先类已 * 对该接口进行了实现
     */
    public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
        private final static Logger LOG = LoggerFactory.getLogger(WebInitializer.class);
    
    /**     * 该方法用于配置ContextLoaderListener创建的应用上下文的bean,相当于web.xml配置中的
     * * <listener>org.springframework.web.ContextLoaderListener</listener> 差异:
     * * 注解配置需要添加的是配置类<br>
     * * 文件配置ContextLoaderListener在创建时自动查找WEB-INF下的applicationContext.xml文件,
     * 当文件不止1个时需通过设置     * 上下文参数(context-param)配置contextConfigLocation的值
     * *      * @return 带有@Configuration注解的类(这些类将会用来配置ContextLoaderListener创建的应用上下文的bean)
     */
        @Override
        protected Class<?>[] getRootConfigClasses() {
            LOG.info("------root配置类初始化------");
            return new Class<?>[]{SpringConfig.class};
        }
    
        /**     * 该方法用于配置DispatcherServlet所需bean,配置类一般用于生成控制层的bean(因Controller中一般包含对参数的设置及数据的返回)     * 相当于web.xml对Spring     * MVC的配置…<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>…<br>     * 配置类如WebConfig.class相当于DispatcherServlet中contetConfigLocation参数对应的配置文件     *      * @return 带有@Configuration注解的类(这些类将会用来配置DispatcherServlet应用上下文中的bean)     */
        @Override
        protected Class<?>[] getServletConfigClasses() {
            LOG.info("------web配置类初始化------");
            return new Class<?>[]{SpringMvcConfig.class};
        }
    
        @Override
        protected String[] getServletMappings() {
            LOG.info("------映射根路径初始化------");
            return new String[]{"/"};// 请求路径映射,将路径映射到DispatcherServlet上,这里可以配置成/* 拦截所有
        }
    
    }

    UserController.java

    package org.hanzx.controller;
    
    import org.hanzx.model.UserModel;
    import org.hanzx.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.ModelMap;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        private final UserService userService;
        private String prefix = "user/";
    
        @Autowired
        public UserController(UserService userService) {
            this.userService = userService;
        }
    
    
    
    //    @RequestMapping(value="/getAllUser")
    //    @ResponseBody
    //    public List<UserModel> getAllUser(){
    //        return userService.getAllUser();
    //    }
    //
    //    @RequestMapping(value="/addUser")
    //    @ResponseBody
    //    public boolean addUser(UserModel userModel){
    //        userService.addUser(userModel);
    //        return true;
    //    }
    //
    //    @RequestMapping(value="/updateUser")
    //    @ResponseBody
    //    public boolean updateUser(UserModel userModel){
    //        userService.updateUser(userModel);
    //        return true;
    //    }
    //
    //    @RequestMapping(value="/deleteUser")
    //    @ResponseBody
    //    public boolean deleteUser(@RequestParam(value = "ids[]") Integer[] ids){
    //        userService.deleteUser(ids);
    //        return true;
    //    }
    
    
    //    @RequestMapping(value="/getUserListForm")
    //    public String getUserListForm(){
    //        return prefix + "user_list";
    //    }
    
        @RequestMapping(value="/getAllUser")
        public String getAllUser(ModelMap modelMap){
            modelMap.put("userModelList", userService.getAllUser());
            return prefix + "user_list";
        }
    
        @RequestMapping(value="/getUserDetailForm")
        public String getUserDetailForm(ModelMap modelMap, Integer id){
            if (id != null){
                modelMap.put("userModel", userService.getUserById(id));
            }
            return prefix + "user_detail";
        }
    
        @RequestMapping(value="/addUser")
        public String addUser(UserModel userModel){
            userService.addUser(userModel);
            return "redirect:getAllUser";
        }
    
        @RequestMapping(value="/updateUser")
        public String updateUser(UserModel userModel){
            userService.updateUser(userModel);
            return "redirect:getAllUser";
        }
    
        @RequestMapping(value="/deleteUser")
        @ResponseBody
        public boolean deleteUser(@RequestParam(value = "ids[]") Integer[] ids){
            userService.deleteUser(ids);
            return true;
        }
    
    
    }

    UserDao.java

    package org.hanzx.dao;
    
    
    import org.hanzx.entity.UserEntity;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    @Repository
    public interface UserDao {
    
        List<UserEntity> getAllUser();
    
        void addUser(UserEntity userEntity);
    
        UserEntity getUserById(Integer id);
    
        void updateUser(UserEntity userEntity);
    
        void deleteUserById(Integer id);
    }

    UserEntity.java

    package org.hanzx.entity;
    
    
    
    public class UserEntity {
    
        private Integer id;
    
        private String name;
    
        private Integer age;
    
        private String password;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }

    CORSInterceptor.java

    package org.hanzx.interceptors;
    
    
    import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class CORSInterceptor extends HandlerInterceptorAdapter {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("拦截请求: " + request.getServletPath());
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            response.setHeader("Access-Control-Max-Age", "0");
            response.setHeader("Access-Control-Allow-Headers",
                    "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("XDomainRequestAllowed", "1");
            return true;
        }
    }

    UserModel.java

    package org.hanzx.model;
    
    
    
    public class UserModel {
    
        private Integer id;
    
        private String name;
    
        private Integer age;
    
        private String password;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }

    UserServiceImpl.java

    package org.hanzx.service.impl;
    
    import org.hanzx.dao.UserDao;
    import org.hanzx.entity.UserEntity;
    import org.hanzx.model.UserModel;
    import org.hanzx.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.ArrayList;
    import java.util.List;
    
    @Service
    public class UserServiceImpl implements UserService{
    
        private final UserDao userDao;
    
        @Autowired
        public UserServiceImpl(UserDao userDao) {
            this.userDao = userDao;
        }
    
        @Override
        public List<UserModel> getAllUser() {
            List<UserEntity> userEntityList = userDao.getAllUser();
            List<UserModel> userModelList = new ArrayList<>();
            for (UserEntity userEntity : userEntityList){
                UserModel userModel = new UserModel();
                userModel.setName(userEntity.getName());
                userModel.setId(userEntity.getId());
                userModel.setAge(userEntity.getAge());
                userModelList.add(userModel);
            }
            return userModelList;
        }
    
        @Override
        public void addUser(UserModel userModel) {
            UserEntity userEntity = new UserEntity();
            userEntity.setName(userModel.getName());
            userEntity.setAge(userModel.getAge());
            userEntity.setPassword(userModel.getPassword());
            userDao.addUser(userEntity);
        }
    
        @Override
        public UserModel getUserById(Integer id) {
            UserEntity userEntity = userDao.getUserById(id);
            UserModel userModel = new UserModel();
            userModel.setAge(userEntity.getAge());
            userModel.setId(userEntity.getId());
            userModel.setName(userEntity.getName());
            userModel.setPassword(userEntity.getPassword());
            return userModel;
        }
    
        @Override
        public void updateUser(UserModel userModel) {
            UserEntity userEntity = userDao.getUserById(userModel.getId());
            userEntity.setPassword(userModel.getPassword());
            userEntity.setAge(userModel.getAge());
            userEntity.setName(userModel.getName());
            userDao.updateUser(userEntity);
        }
    
        @Override
        public void deleteUser(Integer[] ids) {
            for (Integer id : ids){
                userDao.deleteUserById(id);
            }
        }
    }

    UserService.java

    package org.hanzx.service;
    
    
    import org.hanzx.model.UserModel;
    
    import java.util.List;
    
    public interface UserService {
    
        List<UserModel> getAllUser();
    
        void addUser(UserModel userModel);
    
        UserModel getUserById(Integer id);
    
        void updateUser(UserModel userModel);
    
        void deleteUser(Integer[] ids);
    }

    UserMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    
    <mapper namespace="org.hanzx.dao.UserDao">
        <resultMap id="BaseResultMap" type="org.hanzx.entity.UserEntity" >
            <id column="id" property="id" jdbcType="INTEGER" />
            <result column="name" property="name" jdbcType="VARCHAR" />
            <result column="password" property="password" jdbcType="VARCHAR" />
            <result column="age" property="age" jdbcType="INTEGER" />
        </resultMap>
        <select id="getAllUser" resultMap="BaseResultMap" >
          SELECT * FROM user;
        </select>
    
        <insert id="addUser">
            INSERT USER VALUES (null, #{name}, #{age}, #{password});
        </insert>
    
        <select id="getUserById" resultMap="BaseResultMap">
            SELECT * FROM user WHERE user.id = #{id};
        </select>
    
        <update id="updateUser">
            UPDATE user SET name = #{name}, age = #{age}, password = #{password} WHERE id = #{id};
        </update>
    
        <delete id="deleteUserById">
            DELETE FROM user where id = #{id};
        </delete>
    
    </mapper>

    user_detail.html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <div th:if="${userModel} eq null">
            <form th:action="addUser" th:method="post">
        </div>
        <div th:if="${userModel} ne null">
            <form th:action="updateUser" th:method="post">
        </div>
            <table>
                <tr>
                    <th>用户名</th>
                    <td><input th:type="text" th:name="name" th:value="${userModel == null? '' : userModel.name}" th:title="请输入用户名"/></td>
                </tr>
                <tr>
                    <th>密码</th>
                    <td><input th:type="password" th:name="password" th:title="请输入密码"/></td>
                </tr>
                <tr>
                    <th>年龄</th>
                    <td><input th:type="number" th:name="age" th:value="${userModel == null? '' : userModel.age}" th:title="请输入年龄"/></td>
                </tr>
                <tr><td th:colspan="2" ><input th:type="submit" th:value="提交" /></td></tr>
            </table>
            <input th:type="hidden" th:name="id" th:value="${userModel == null? null : userModel.id}" />
        </form>
    </body>
    </html>

    user_list.html

    <!DOCTYPE html>
    <html lang="cn" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>userEntityList</title>
        <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js" ></script>
        <script type="text/javascript">
            $(function () {
                //全选
                $("#selectAll").click(function () {
                    if (this.checked) {
                        $("input[name=deleteId]").prop("checked", true);
                    } else {
                        $("input[name=deleteId]").prop("checked", false);
                    }
                });
    
                $("input[name=deleteId]").click(function () {
                    var allChecked = true;
                    $("input[name=deleteId]").each(function(){
                        if(!$(this).prop("checked")){
                            allChecked = false;
                        }
                    });
                    if(allChecked){
                        $("#selectAll").prop("checked",true);
                    } else {
                        $("#selectAll").prop("checked",false);
                    }
                });
    
                //删除用户
                $("#delete").click(function () {
                    var ids = [];
                    $("input[name=deleteId]:checked").each(function(index){
                        ids[index] = $(this).val();
                    });
                    if (ids.length === 0){
                        alert("没有选中的选项");
                        return false;
                    }
                    $.ajax({
                        url : "deleteUser",
                        data: {"ids": ids},
                        cache : false,
                        async : false,
                        type : "GET",
                        success:function(data){
                            if (data === true){
                                window.location.reload();
                            }
                        }
                    });
                });
    
            });
    
        </script>
    </head>
    <body>
        <a th:href="getUserDetailForm">添加</a>
        <a th:id="delete" href="#" >删除</a>
        <table>
            <tr>
                <th><input th:type="checkbox" th:id="selectAll" title="点击全选/取消"/></th>
                <th>用户名</th>
                <th>年龄</th>
                <th>操作</th>
            </tr>
            <tr th:each="userModel : ${userModelList}">
                <td><input th:type="checkbox" th:value="${userModel.id}" th:name="deleteId"/></td>
                <td th:text="${userModel.name}">abc</td>
                <td th:text="${userModel.age}">15</td>
                <td><a th:href="'getUserDetailForm?id=' + ${userModel.id}">修改</a></td>
            </tr>
        </table>
    </body>
    </html>

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    index
    </body>
    </html>

    jdbc.properties

    jdbc_driverClassName=com.mysql.jdbc.Driver
    jdbc_url=jdbc:mysql://localhost:3306/web_test?useUnicode=true&characterEncoding=utf8
    jdbc_username=root
    jdbc_password=root
    #配置初始化大小、最小、最大
    initialSize=10
    minIdle=10
    maxActive=50
    #配置获取连接等待超时的时间
    maxWait=60000
    #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis=60000
    #配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis=300000
    validationQuery=SELECT 'x'
    testWhileIdle=true
    testOnBorrow=false
    testOnReturn=false
    #打开PSCache,并且指定每个连接上PSCache的大小  如果用Oracle,则把poolPreparedStatements配置为true,mysql可以配置为false。
    poolPreparedStatements=false
    maxPoolPreparedStatementPerConnectionSize=20
    #配置监控统计拦截的filters
    filters=wall,stat

    logback.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <!-- 尽量别用绝对路径,如果带参数不同容器路径解释可能不同,以下配置参数在pom.xml里 -->
        <property name="log.root.level" value="${log.root.level}" /> <!-- 日志级别 -->
        <property name="log.other.level" value="${log.other.level}" /> <!-- 其他日志级别 -->
        <property name="log.base" value="${log.base}" /> <!-- 日志路径,这里是相对路径,web项目eclipse下会输出到eclipse的安装目录下,如果部署到linux上的tomcat下,会输出到tomcat/bin目录 下 -->
        <property name="log.moduleName" value="${log.moduleName}" />  <!-- 模块名称, 影响日志配置名,日志文件名 -->
        <property name="log.max.size" value="100MB" /> <!-- 日志文件大小,超过这个大小将被压缩 -->
    
        <!--控制台输出 -->
        <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
            <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                <Pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method():%L -%msg%n</Pattern>
            </encoder>
        </appender>
    
        <!-- 用来保存输出所有级别的日志 -->
        <appender name="file.all" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <File>${log.base}/${log.moduleName}.log</File><!-- 设置日志不超过${log.max.size}时的保存路径,注意如果
                是web项目会保存到Tomcat的bin目录 下 -->
            <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。 -->
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <FileNamePattern>${log.base}/archive/${log.moduleName}_all_%d{yyyy-MM-dd}.%i.log.zip
                </FileNamePattern>
                <!-- 文件输出日志 (文件大小策略进行文件输出,超过指定大小对文件备份) -->
                <timeBasedFileNamingAndTriggeringPolicy
                        class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>${log.max.size}</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <!-- 日志输出的文件的格式 -->
            <layout class="ch.qos.logback.classic.PatternLayout">
                <pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%thread]%logger{56}.%method():%L -%msg%n</pattern>
            </layout>
        </appender>
    
        <!-- 这也是用来保存输出所有级别的日志 -->
        <appender name="file.all.other" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <File>${log.base}/${log.moduleName}_other.log</File>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <FileNamePattern>${log.base}/archive/${log.moduleName}_other_%d{yyyy-MM-dd}.%i.log.zip
                </FileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy
                        class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>${log.max.size}</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <layout class="ch.qos.logback.classic.PatternLayout">
                <pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{56}.%method():%L -%msg%n</pattern>
            </layout>
        </appender>
    
        <!-- 只用保存输出error级别的日志 -->
        <appender name="file.error"
                  class="ch.qos.logback.core.rolling.RollingFileAppender">
            <File>${log.base}/${log.moduleName}_err.log</File>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <FileNamePattern>${log.base}/archive/${log.moduleName}_err_%d{yyyy-MM-dd}.%i.log.zip
                </FileNamePattern>
                <timeBasedFileNamingAndTriggeringPolicy
                        class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                    <maxFileSize>${log.max.size}</maxFileSize>
                </timeBasedFileNamingAndTriggeringPolicy>
            </rollingPolicy>
            <layout class="ch.qos.logback.classic.PatternLayout">
                <pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{56}.%method():%L - %msg%n</pattern>
            </layout>
            <!-- 下面为配置只输出error级别的日志 -->
            <filter class="ch.qos.logback.classic.filter.LevelFilter">
                <level>ERROR</level>
                <onMatch>ACCEPT</onMatch>
                <onMismatch>DENY</onMismatch>
            </filter>
        </appender>
    
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender name="file.async" class="ch.qos.logback.classic.AsyncAppender">
            <discardingThreshold>0</discardingThreshold>
            <queueSize>256</queueSize>
            <includeCallerData>true</includeCallerData>
            <appender-ref ref="file.all" />
        </appender>
    
        <appender name="file.async.other" class="ch.qos.logback.classic.AsyncAppender">
            <discardingThreshold>0</discardingThreshold>
            <queueSize>256</queueSize>
            <includeCallerData>true</includeCallerData>
            <appender-ref ref="file.all.other" />
        </appender>
    
        <!-- 为某个包下的所有类的指定Appender 这里也可以指定类名称例如:com.aa.bb.ClassName -->
        <logger name="com.lin" additivity="false">
            <level value="${log.root.level}" />
            <appender-ref ref="stdout" />
            <appender-ref ref="file.async" /><!-- 即com.lin包下级别为 ${log.root.level}的才会使用file.async来打印 -->
            <appender-ref ref="file.error" />
        </logger>
    
        <!-- root将级别为${log.root.level}及大于${log.root.level}的日志信息交给已经配置好的名为“Console”的appender处理,“Console”appender将信息打印到Console,其它同理 -->
        <root level="${log.root.level}">
            <appender-ref ref="stdout" /> <!--  标识这个appender将会添加到这个logger -->
            <appender-ref ref="file.async.other" />
            <appender-ref ref="file.error" />
        </root>
    </configuration>

    效果图

    存在的问题

    1、MapperScannerConfigurer不能使用。因为这东西会先于PropertySourcesPlaceholderConfigurer加载,并调用datasource,导致jdbc.properties里的数据读不到。

    咱已经试过了将PropertySourcesPlaceholderConfigurer的bean加载方法改成静态,然而没有用。打过断点,PropertySourcesPlaceholderConfigurer的bean确实先于MapperScannerConfigurer加载,然而还是读不出properties里的数据。

    咱也试过MapperScannerConfigurer里配置SqlSessionFactoryBeanName取代配置SqlSessionFactory(这个已经也被划了,旧了过期了),也没有用。

    就是读不出properties。天知道哪出了问题,只好暂且先弃用了。改用@PropertySource("classpath:jdbc.properties")注解加载jdbc.properties,使用@MapperScan("org.hanzx.dao")扫描dao。

    2、把所有html模板文件迁移进resources/templates里以后,删除掉webapp文件夹以后,还需要在File - project structure - facets - web里面将Web resource directory改为项目的resources下才能正确读取到模板文件。

    然而问题在于,reimport了pom.xml以后此项配置就又恢复原状了,目前尚不知道怎么改pom.xml。

    还望各路高手赐教…

  • 相关阅读:
    java mybatis
    java influx DB工具类
    java redisUtils工具类很全
    java 任务定时调度(定时器)
    java 线程并发(生产者、消费者模式)
    java 线程同步、死锁
    Redis 集群版
    Redis 单机版
    linux下配置zookeeper注册中心及运行dubbo服务
    vue搭建前端相关命令
  • 原文地址:https://www.cnblogs.com/hanzx/p/10309466.html
Copyright © 2011-2022 走看看