SSM项目实战

项目实战一

这里实战的是我Javaweb项目实战(后端篇)的改写

Javaweb项目实战用到的技术是servlet+vue3

这里用到的是spring+springmvc+mybatis+vue3

项目结构

步骤一:导入需要依赖

XML 复制代码
   <!--mybatis核心-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.16</version>
        </dependency>
<!--德鲁伊连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.32</version>
        </dependency>
       <!--简化实体类的getset-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.32</version>
        </dependency>
      <!-- 方便使用JdbcTemplate事务也需要它-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>6.0.6</version>
        </dependency>

        <!--spring context依赖-->
        <!--当你引入Spring Context依赖之后,表示将Spring的基础依赖引入了-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.6</version>
        </dependency>
        <!--junit5测试-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.10.2</version>
        </dependency>

    <!--spring test依赖快速使用ioc容器-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>6.0.6</version>
            <scope>test</scope>
        </dependency>

        <!--spring aop依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>6.0.6</version>
        </dependency>

        <!-- 声明式事务依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>6.0.6</version>
        </dependency>

     <!--springmvc依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>6.0.6</version>
        </dependency>
        <!--web项目需要servlet-->
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-web-api</artifactId>
            <version>9.1.0</version>
            <scope>provided</scope>
        </dependency>

        <!--json-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.17.1</version>
        </dependency>

        <!-- jsp需要依赖! jstl-->
        <dependency>
            <groupId>jakarta.servlet.jsp.jstl</groupId>
            <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
            <version>3.0.0</version>
        </dependency>

        <!--整和需要  加载ioc容器-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>6.0.6</version>
        </dependency>

        <!--整合需要  spring整合mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>3.0.3</version>
        </dependency>

        <!--日志-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.5.6</version>
        </dependency>

步骤二:配置类

2.1 SpringConfig类

java 复制代码
package org.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

@Configuration
@ComponentScan({"org.example.service"})
@EnableAspectJAutoProxy
@EnableTransactionManagement
public class SpringConfig {

    //开始事务注解
    @Bean
    public TransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}

2.2 JdbcConfig类

java 复制代码
package org.example.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import javax.sql.DataSource;

@Configuration
@PropertySource({"classpath:jdbc.properties"})
public class JdbcConfig {
    @Value("${jdbc.driverClassName}")
    private String driverClassName;
    @Value("${jdbc.url}")
    private  String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")

    private String password;

    @Bean
    public DataSource getDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}

2.3 MybatisConfig类

java 复制代码
package org.example.config;

import com.github.pagehelper.PageInterceptor;
import jakarta.servlet.jsp.jstl.core.Config;
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.apache.ibatis.session.AutoMappingBehavior;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.util.Properties;

@Configuration
public class MybatisConfig {
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
        SqlSessionFactoryBean sqlSession= new SqlSessionFactoryBean();
        sqlSession.setDataSource(dataSource);
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setLogImpl(Slf4jImpl.class);  //日志
        configuration.setMapUnderscoreToCamelCase(true); //驼峰映射
        configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL);//自动映射 数据库表和java对象
        sqlSession.setConfiguration(configuration);
        sqlSession.setTypeAliasesPackage("org.example.pojo");  //别名

        //分页插件
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("helperDialect","mysql");
        pageInterceptor.setProperties(properties);
        sqlSession.addPlugins(pageInterceptor);

        return sqlSession;
    }


    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setBasePackage("org.example.mapper");
        return mapperScannerConfigurer;
    }
}

2.4 SpringMvcConfig类

java 复制代码
package org.example.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
@ComponentScan({"org.example.controller"})
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {

    //全局异常处理


    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {


    }

    //静态资源
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {

        configurer.enable();
    }
}

2.5 JavaConfig类

java 复制代码
package org.example.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class JavaConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{JdbcConfig.class, SpringConfig.class, MybatisConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

步骤三:创建日志文件 logback.xml

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
    <!-- 指定日志输出的位置,ConsoleAppender表示输出到控制台 -->
    <appender name="STDOUT"
              class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 日志输出的格式 -->
            <!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -->
            <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 设置全局日志级别。日志级别按顺序分别是:TRACE、DEBUG、INFO、WARN、ERROR -->
    <!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
    <root level="DEBUG">
        <!-- 指定打印日志的appender,这里通过"STDOUT"引用了前面配置的appender -->
        <appender-ref ref="STDOUT"/>
    </root>

    <!-- 根据特殊需求指定局部日志级别,可也是包名或全类名。 -->
    <logger name="org.example.mapper" level="DEBUG"/>

</configuration>

步骤四 创建MD5类,全局统一json类

4.1MD5

java 复制代码
package org.example.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Util {
    public static String encrypt(String strSrc) {
        try {
            char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
                    '9', 'a', 'b', 'c', 'd', 'e', 'f' };
            byte[] bytes = strSrc.getBytes();  //使用平台的默认字符集将此 String 编码为 byte 序列,并 将结果存储到一个新的 byte 数组中。
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(bytes);
            bytes = md.digest();
            int j = bytes.length;
            char[] chars = new char[j * 2];
            int k = 0;
            for (int i = 0; i < bytes.length; i++) {
                byte b = bytes[i];
                chars[k++] = hexChars[b >>> 4 & 0xf];
                chars[k++] = hexChars[b & 0xf];
            }
            return new String(chars);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException("MD5加密出错");
        }

    }

}

4.2json

java 复制代码
package org.example.json;

//全局统一响应的JSON格式处理类
public class Result <T>{   //因为不确定返回消息是什么类型 ,所以这里声明了<T>
    // 返回码
    private Integer code;
    // 返回消息
    private String message;
    // 返回数据
    private T data;
    public Result(){}
    // 返回数据
    protected static <T> Result<T> build(T data) {   //将data添加进去
        Result<T> result = new Result<T>();
        if (data != null)
            result.setData(data);
        return result;            //返回一个result对象
    }
    public static <T> Result<T> build(T body, Integer code, String message) { //
        Result<T> result = build(body);  // 创建一个result对象,并添加data对象
        result.setCode(code);
        result.setMessage(message);
        return result;
    }
    public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
        Result<T> result = build(body);       //创建result对象并添加data数据
        result.setCode(resultCodeEnum.getCode());  //给响应码添加枚举类中的数据
        result.setMessage(resultCodeEnum.getMessage()); //给响应消息添加枚举类中的数据
        return result;
    }
    /**
     * 操作成功
     * @param data  baseCategory1List
     * @param <T>
     * @return
     */
    public static<T> Result<T> ok(T data){          //返回一个result对象,这是一个操作成功的数据,如果操作成功就执行它
        Result<T> result = build(data);    //创建result对象并添加data数据
        return build(data, ResultCodeEnum.SUCCESS); //调用上面的方法,将枚举类中的ResultCodeEnum.SUCCESS赋值给响应码和响应消息并返回result
    }
    public Result<T> message(String msg){
        this.setMessage(msg);
        return this;
    }
    public Result<T> code(Integer code){
        this.setCode(code);
        return this;
    }
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
}
java 复制代码
package org.example.json;

public enum ResultCodeEnum {
    SUCCESS(200,"success"),
    USERNAEM_ERROR(501,"usernameError"),
    PASSWORD_ERROR(503,"passwordError"),
    NOTLOGIN(504,"notlogin"),
    USERNAME_USED(505,"usernameUsed");



    private Integer code;
    private String message;
    private ResultCodeEnum(Integer code ,String message){
        this.code= code;
        this.message = message;

    }

    public Integer getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }
}

步骤五:三层架构

mapper层

1.账户表SysUserMapper

java 复制代码
public interface SysUserMapper {
  int  add(SysUser sysUser);
SysUser findByUsername(String username);
}

对应的xml文件

java 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace等于mapper接口类的全限定名,这样实现对应 -->
<mapper namespace="org.example.mapper.SysUserMapper">


    <insert id="add">
        insert into sys_user values(default,#{username},#{userPwd})
    </insert>
    <select id="findByUsername" resultType="sysUser">

        select * from sys_user where username =#{username}
    </select>
</mapper>

2.数据表SysSchedule

java 复制代码
package org.example.mapper;

import org.example.pojo.SysSchedule;

import java.util.List;

public interface SysScheduleMapper {
    /**
     * 用于向数据中增加一条日程记录
     * @param schedule 日程数据以SysSchedule实体类对象形式入参
     * @return 返回影响数据库记录的行数, 行数为0说明增加失败,行数大于0说明增加成功
     */
    int addSchedule(int  uid);


    /**
     * 查询所有用户的所有日程
     * @return 将所有日程放入一个:List<SysSchedule>集合中返回
     */
    List<SysSchedule> findAll();

    List<SysSchedule> findItemListByUid(int uid);

    Integer addDefault(int uid);

    Integer updateSchedule(SysSchedule schedule);

    Integer removeSchedule(int sid);
}

对应的xml文件

java 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace等于mapper接口类的全限定名,这样实现对应 -->
<mapper namespace="org.example.mapper.SysScheduleMapper">

    <insert id="addDefault">
        insert into sys_schedule values (DEFAULT,#{uid},'请输入日程',0)
    </insert>
    <insert id="addSchedule">
        insert into sys_schedule values(DEFAULT,#{uid},#{title},#{completed})
    </insert>
    <update id="updateSchedule">
        update sys_schedule set title = #{title} ,completed = #{completed} where  sid = #{sid}
    </update>


    <delete id="removeSchedule">

        delete from sys_schedule where sid = #{sid}
    </delete>


    <select id="findItemListByUid" resultType="org.example.pojo.SysSchedule">
        select sid ,uid,title,completed from sys_schedule where uid = #{uid}
    </select>

    <select id="findAll" resultType="org.example.pojo.SysSchedule">
        select * from sys_schedule
    </select>
</mapper>

Service层

1.账户表SysUserMapper

java 复制代码
public interface SysUserService {
         int regist(SysUser sysUser);

    /**
     * 根据用户名获得完整用户信息的方法
     * @param username 要查询的用户名
     * @return 如果找到了返回SysUser对象,找不到返回null
     */
    SysUser findByUsername(String username);
}

实现类

java 复制代码
    @Service
public class SysUserServiceImpl implements SysUserService {
    @Autowired
    private SysUserMapper sysUserMapper;


    @Override
    public int regist(SysUser sysUser) {
        sysUser.setUserPwd(MD5Util.encrypt(sysUser.getUserPwd()));

      return   sysUserMapper.add(sysUser);
    }

    @Override
    public SysUser findByUsername(String username) {
     return   sysUserMapper.findByUsername(username);
    }
}

2.数据表SysSchedule

java 复制代码
public interface SysScheduleService {
    List<SysSchedule> findItemListByUid(int uid);

    Integer addDefault(int uid);

    Integer updateSchedule(SysSchedule schedule);

    Integer removeSchedul(int sid);
}

实现类

java 复制代码
@Service

public class SysScheduleServiceImpl implements SysScheduleService {
    @Autowired
    private SysScheduleMapper sysScheduleMapper;


    @Override
    public List<SysSchedule> findItemListByUid(int uid) {
        return sysScheduleMapper.findItemListByUid(uid);
    }

    @Override
    public Integer addDefault(int uid) {
        return sysScheduleMapper.addDefault(uid);
    }

    @Override
    public Integer updateSchedule(SysSchedule schedule) {
        return sysScheduleMapper.updateSchedule(schedule);
    }

    @Override
    public Integer removeSchedul(int sid) {
        return sysScheduleMapper.removeSchedule(sid);
    }
}

controller层

1.账户表SysUserMapper

java 复制代码
@Controller
@CrossOrigin
@ResponseBody
@RequestMapping("user")
@Slf4j
public class SysUserController {

    @Autowired
    private SysUserService service;

    @RequestMapping("checkUsernameUsed")
    public Result checkUsernameUsed(String username) {
        SysUser sysUser = service.findByUsername(username);
        Result result = Result.ok(null);
        if (sysUser != null) {
            result = Result.build(null, ResultCodeEnum.USERNAME_USED);
        }
        log.info("用户名是否被占用:{}", result);
        return result;

    }

    @RequestMapping(value = "login",method = RequestMethod.POST)
    public Result login(@RequestBody SysUser sysUser) {
        //2 调用服务层方法,根据用户名查询用户信息
        SysUser loginUser = service.findByUsername(sysUser.getUsername());

        Result result = null;

        if (null == loginUser) {
            result = Result.build(null, ResultCodeEnum.USERNAEM_ERROR);

        } else if (!MD5Util.encrypt(sysUser.getUserPwd()).equals(loginUser.getUserPwd())) {
            result = Result.build(null, ResultCodeEnum.PASSWORD_ERROR);
        } else {
            // 登录程序,将用户uid和username响应给客户端
            Map data = new HashMap();
            loginUser.setUserPwd("");
            data.put("loginUser", loginUser);
            result = Result.ok(data);
        }
        log.info("用户名是否被占用:{}", result);
        // 3将登录结果响应给客户端
       return result;
    }

    @RequestMapping("regist")
    public Result regist(@RequestBody SysUser sysUser){
        int regist = service.regist(sysUser);
        Result result = Result.ok(null);
        if (regist < 1) {
            result = Result.build(null, ResultCodeEnum.USERNAME_USED);
        }
log.info("用户注册:{}", result);
return result;
    }

    @RequestMapping("select")
    public Result select(String username) {
        SysUser sysUser = service.findByUsername(username);
        Result result = Result.ok(null);
        if (sysUser != null) {
            result = Result.build(null, ResultCodeEnum.USERNAME_USED);
        }
        log.info("用户名是否被占用:{}", result);
        return result;

    }
}

2.数据表SysSchedule

java 复制代码
@Slf4j
@CrossOrigin
@ResponseBody
@Controller
@RequestMapping("schedule")
public class SysScheduleController {
    @Autowired
    private SysScheduleService service;


    @RequestMapping("removeSchedule")
    public Result removeSchedule(int sid){
        Integer i = service.removeSchedul(sid);
      if(i<0){
      return     Result.build(null, ResultCodeEnum.NOTLOGIN);
      }else {
        return   Result.ok(null);
      }
    }

 @RequestMapping(value = "updateSchedule",method = RequestMethod.POST)
public Result updateSchedule(@RequestBody SysSchedule schedule){
     Integer i = service.updateSchedule(schedule);
     if(i<0){
         return     Result.build(null, ResultCodeEnum.NOTLOGIN);
     }else {
         return   Result.ok(null);
     }
 }
 @RequestMapping("addDefaultSchedule")
    public Result addDefaultSchedule(int uid){
        Integer i = service.addDefault(uid);
        if(i<0){
            return     Result.build(null, ResultCodeEnum.NOTLOGIN);
        }else {
            return   Result.ok(null);
        }
 }
@RequestMapping("findAllSchedule")
    public Result findAllSchedule(int uid){
    List<SysSchedule> itemList = service.findItemListByUid(uid);

    // 将用户的所有日程放入一个Result对象
    Map data =new HashMap();
    data.put("itemList",itemList);

    Result result = Result.ok(data);
    // 将Result对象转换为json响应给客户端
    return result;
}
}

总结

与servlet相比

ssm

简化了响应json的WebUtil

简化了JDBCUtil

简化了全局统一 处理servlet的BaseContoller

简化了跨域CrosFilter的java文件

ssm 使用@CrossOrigin注解就使当前文件可以跨域大大减少了代码量

ssm使用@ResponseBody注解就使响应数据变为json形式

ssm使用@RequestMapping就相当于一个servlet所以无需统一处理servlet

相关推荐
儿时可乖了3 分钟前
使用 Java 操作 SQLite 数据库
java·数据库·sqlite
ruleslol5 分钟前
java基础概念37:正则表达式2-爬虫
java
xmh-sxh-131421 分钟前
jdk各个版本介绍
java
XINGTECODE35 分钟前
海盗王集成网关和商城服务端功能golang版
开发语言·后端·golang
天天扭码40 分钟前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
程序猿进阶41 分钟前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
FIN技术铺1 小时前
Spring Boot框架Starter组件整理
java·spring boot·后端
小曲程序1 小时前
vue3 封装request请求
java·前端·typescript·vue
凡人的AI工具箱1 小时前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
陈王卜1 小时前
django+boostrap实现发布博客权限控制
java·前端·django