SSM整合
项目结构配置搭建
pom的依赖:
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.18</version> </dependency> <!-- 添加json数据转换相关坐标--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> <!-- Spring 操作数据库的包--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>6.0.0</version> </dependency> <!--mybatis包--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version> 3.5.11</version> </dependency> <!--mybatis 与 Spring整合的包--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.7</version> </dependency> <!-- mysql包--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency> <!-- spring 测试包 版本需要跟spring-mvc的一样--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.3.18</version> </dependency> <!--德鲁伊依赖--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.14</version> </dependency> </dependencies>
配置文件夹的各个配置文件:
SpringConfig:
@Configuration @ComponentScan({"com.study.service"}) @PropertySource("classpath:jdbc.properties")
//一定要加classpath: 不然读取不到
@Import({JdbcConfig.class, MybatisConfig.class}) public class SpringConfig { }
SpringMvcConfig
@Configuration @ComponentScan("com.study.controller") @EnableWebMvc public class SpringMvcConfig { }
JdbcConfig
public class JdbcConfig { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Bean public DataSource dataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); return dataSource; } }
MybatisConfig
public class MybatisConfig { @Bean public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){ SqlSessionFactoryBean factoryBean =new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); factoryBean.setTypeAliasesPackage("com.study.domain"); return factoryBean; } @Bean public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer msc =new MapperScannerConfigurer(); msc.setBasePackage("com.study.dao"); return msc; } }
ServletConfig
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer { protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringMvcConfig.class}; } protected String[] getServletMappings() { return new String[]{"/"}; } }
dao层:
public interface BrandDao { @Insert("insert into tb_brand1 values (null,#{brandName},#{description},#{status})") public void save(Brand brand); @Update("update tb_brand1 set brand_name=#{brandName}, description=#{description}, status=#{status} where id=#{id}") public void update(Brand brand); @Delete("delete from tb_brand1 where id =#{id}") //用@Results可以嵌套多个@Result @Results({ @Result(property="brandName",column="brand_name") }) public void delete(Integer id); @Select("select * from tb_brand1 where id = #{id}") @Results({ @Result(property="brandName",column="brand_name") }) public Brand getById(Integer id); @Select("select * from tb_brand1") public List<Brand> getAll(); }
service接口:
public interface BrandService { public boolean save(Brand brand); public boolean update(Brand brand); public boolean delete(Integer id); public Brand getById(Integer id); public List<Brand> getAll(); }
seivice实现类:
@Service public class BrandServiceImpl implements BrandService { @Autowired private BrandDao brandDao; //这里自动装配会报错,我们在设置里把检查的报错换成警告就可以了 public boolean save(Brand brand) { brandDao.save(brand); return true; } public boolean update(Brand brand) { brandDao.update(brand); return true; } public boolean delete(Integer id) { brandDao.delete(id); return true; } public Brand getById(Integer id) { return brandDao.getById(id); } public List<Brand> getAll() { return brandDao.getAll(); } }
REST风格的controller类:
@RestController @RequestMapping("/brands") public class BrandController { @Autowired private BrandService brandService; @PostMapping public boolean save(@RequestBody Brand brand) { brandService.save(brand); return true; } @PutMapping public boolean update(@RequestBody Brand brand) { brandService.update(brand); return true; } @DeleteMapping("/{id}") public boolean delete(@PathVariable Integer id) { brandService.delete(id); return true; } @GetMapping("/{id}") public Brand getById(@PathVariable Integer id) { return brandService.getById(id); } @GetMapping public List<Brand> getAll() { return brandService.getAll(); } }
测试
注意:测试的spring-test版本需要跟spring-webmvc版本一致,否则会报错
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SpringConfig.class) public class BrandServiceTest { @Autowired private BrandService brandService; @Test public void testGetById(){ Brand brand = brandService.getById(1); System.out.println(brand); } @Test public void testGetAll(){ List<Brand> all =brandService.getAll(); System.out.println(all); } }
增删改查的内容,我们直接用tomcat运行然后postman进行调试就可以了
事务
1.首先在JdbcConfig里面编写事务管理的bean类
2.在SpringConfig加上 @EnableTransactionManagement //注解开发事务
3.在对应的接口上加上@Transactional
表现层数据封装
我们后台返回的类型有很多,这时候我们封装成一个Result类,这样就统一起来,并且方便跟前端交互,封装的时候要记得设置相应的构造方法 这样会更方便
然后我们再封装一个Code类,使用静态常量定义各个状态,这样我们就能通过类名.常量名调用了
Controller把所有返回值都设置成Result的结果:
@RestController @RequestMapping("/brands") public class BrandController { @Autowired private BrandService brandService; @PostMapping public Result save(@RequestBody Brand brand) { boolean flag = brandService.save(brand); return new Result(flag ? Code.SAVE_OK:Code.SAVE_ERR,flag); } @PutMapping public Result update(@RequestBody Brand brand) { boolean flag = brandService.update(brand); return new Result(flag ? Code.UPDATE_OK:Code.UPDATE_ERR,flag); } @DeleteMapping("/{id}") public Result delete(@PathVariable Integer id) { boolean flag = brandService.delete(id); return new Result(flag ? Code.DELETE_OK:Code.DELETE_ERR,flag); } @GetMapping("/{id}") public Result getById(@PathVariable Integer id) { Brand brand = brandService.getById(id); Integer code =brand!=null?Code.GET_OK:Code.GET_ERR; String msg =brand!=null?"":"数据查询失败,请重试"; return new Result(code,brand,msg); } @GetMapping public Result getAll() { List<Brand> all = brandService.getAll(); Integer code =all!=null?Code.GET_OK:Code.GET_ERR; String msg =all!=null?"":"数据查询失败,请重试"; return new Result(code,all,msg); } }
异常处理器
异常出现的地方会很多,最好就是集中在表现层进行处理
SpringMVC就提供了异常处理器
我们在Controller包里新建一个异常处理器
项目异常处理方案
我们创建一个exception包
然后在里面分别自定义各个种类的异常类BusinessException 跟 SystemException
继承RuntimeException,并加一个code变量,分别写上构造方法。如:
public class SystemException extends RuntimeException{ private Integer code; public SystemException( Integer code,String message) { super(message); this.code = code; } public SystemException(String message,Throwable cause, Integer code) { super(message,cause); this.code = code; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } }
触发后我们修改之前在controller层写的ProjectExceptionAdvice,分别拦截各种异常并作出相应的处理
前端页面放行
为了避免,前端的页面已经js css之类的被SpringMVC拦截,我们新建一个SpringMvcSupport类
然后在SpringMvcConfig中把对应的包位置扫进去,就可以了
@ComponentScan({"com.study.controller","com.study.config"})