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

相关推荐
顽疲几秒前
springboot vue 会员收银系统 含源码 开发流程
vue.js·spring boot·后端
cmdch20176 分钟前
Mybatis加密解密查询操作(sql前),where要传入加密后的字段时遇到的问题
数据库·sql·mybatis
王ASC29 分钟前
SpringMVC的URL组成,以及URI中对/斜杠的处理,解决IllegalStateException: Ambiguous mapping
java·mvc·springboot·web
撒呼呼30 分钟前
# 起步专用 - 哔哩哔哩全模块超还原设计!(内含接口文档、数据库设计)
数据库·spring boot·spring·mvc·springboot
是小崔啊31 分钟前
开源轮子 - Apache Common
java·开源·apache
因我你好久不见35 分钟前
springboot java ffmpeg 视频压缩、提取视频帧图片、获取视频分辨率
java·spring boot·ffmpeg
程序员shen16161137 分钟前
抖音短视频saas矩阵源码系统开发所需掌握的技术
java·前端·数据库·python·算法
Ling_suu1 小时前
SpringBoot3——Web开发
java·服务器·前端
hanglove_lucky1 小时前
本地摄像头视频流在html中打开
前端·后端·html
天使day1 小时前
SpringMVC
java·spring·java-ee