这里实战的是我Javaweb项目实战(后端篇)的改写
Javaweb项目实战用到的技术是servlet+vue3
这里用到的是spring+springmvc+mybatis+vue3

org.mybatis mybatis 3.5.16 com.alibaba druid 1.2.8 mysql mysql-connector-java 8.0.32 org.projectlombok lombok 1.18.32 org.springframework spring-jdbc 6.0.6 org.springframework spring-context 6.0.6 org.junit.jupiter junit-jupiter-api 5.10.2 org.springframework spring-test 6.0.6 test org.springframework spring-aspects 6.0.6 org.springframework spring-tx 6.0.6 org.springframework spring-webmvc 6.0.6 jakarta.platform jakarta.jakartaee-web-api 9.1.0 provided com.fasterxml.jackson.core jackson-databind 2.17.1 jakarta.servlet.jsp.jstl jakarta.servlet.jsp.jstl-api 3.0.0 org.springframework spring-web 6.0.6 org.mybatis mybatis-spring 3.0.3 ch.qos.logback logback-classic 1.5.6 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; } } 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; } } 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; } } 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 resolvers) { } //静态资源 @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } } 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[]{"/"}; } } [%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n UTF-8 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加密出错"); } } } package org.example.json; //全局统一响应的JSON格式处理类 public class Result { //因为不确定返回消息是什么类型 ,所以这里声明了 // 返回码 private Integer code; // 返回消息 private String message; // 返回数据 private T data; public Result(){} // 返回数据 protected static Result build(T data) { //将data添加进去 Result result = new Result(); if (data != null) result.setData(data); return result; //返回一个result对象 } public static Result build(T body, Integer code, String message) { // Result result = build(body); // 创建一个result对象,并添加data对象 result.setCode(code); result.setMessage(message); return result; } public static Result build(T body, ResultCodeEnum resultCodeEnum) { Result result = build(body); //创建result对象并添加data数据 result.setCode(resultCodeEnum.getCode()); //给响应码添加枚举类中的数据 result.setMessage(resultCodeEnum.getMessage()); //给响应消息添加枚举类中的数据 return result; } /** * 操作成功 * @param data baseCategory1List * @param * @return */ public static Result ok(T data){ //返回一个result对象,这是一个操作成功的数据,如果操作成功就执行它 Result result = build(data); //创建result对象并添加data数据 return build(data, ResultCodeEnum.SUCCESS); //调用上面的方法,将枚举类中的ResultCodeEnum.SUCCESS赋值给响应码和响应消息并返回result } public Result message(String msg){ this.setMessage(msg); return this; } public Result 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; } } 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; } } public interface SysUserMapper { int add(SysUser sysUser); SysUser findByUsername(String username); } 对应的xml文件
insert into sys_user values(default,#{username},#{userPwd}) 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集合中返回 */ List findAll(); List findItemListByUid(int uid); Integer addDefault(int uid); Integer updateSchedule(SysSchedule schedule); Integer removeSchedule(int sid); } 对应的xml文件
insert into sys_schedule values (DEFAULT,#{uid},'请输入日程',0) insert into sys_schedule values(DEFAULT,#{uid},#{title},#{completed}) update sys_schedule set title = #{title} ,completed = #{completed} where sid = #{sid} delete from sys_schedule where sid = #{sid} public interface SysUserService { int regist(SysUser sysUser); /** * 根据用户名获得完整用户信息的方法 * @param username 要查询的用户名 * @return 如果找到了返回SysUser对象,找不到返回null */ SysUser findByUsername(String username); } 实现类
@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); } } public interface SysScheduleService { List findItemListByUid(int uid); Integer addDefault(int uid); Integer updateSchedule(SysSchedule schedule); Integer removeSchedul(int sid); } 实现类
@Service public class SysScheduleServiceImpl implements SysScheduleService { @Autowired private SysScheduleMapper sysScheduleMapper; @Override public List 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 @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; } } @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 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