ssm整合

SSM (spring springmvc mybatis)

数据层 - mybatis
表现层 - springmvc
业务层 - 由需求决定

spring 是在三层之间进行整合的基础架构
spring做底,其他东西都在spring上运行

spring -- 搭框架基础
MyBatis -- mysql + druid + pagehelper

Spring 整合 MyBatis --加上 Junit 测试业务层接口
SpringMVC --rest风格(postman测试请求结果)、数据封装json
Spring 整合 SpringMVC -- Controller 能调用Service
基于springmvc的表现层技术、调用业务层、再调数据层
整个由spring做整体的项目总控

1、项目结构搭建

Java三层架构

注意:
1.1 实体类实现 Serializable 接口
1.2 数据层操作不要和业务层操作的名称混淆,通常数据层仅反映与数据库间的信息交换,不体现业务逻辑
1.3 列如 :数据层 getByUserNameAndPassword 业务层 login

2、spring整合mybatis
2.1 创建MyBatis映射文件

相关注意:dao层类中方法传参问题 两个参数以上加@Param

public User getByUserNameAndPassword(@Param("userName") String userName,@Param("password")String password);
2.2 创建Spring配置文件 - 组件扫描

相关注意:service层类中方法:分页查询
@Service中 @Autowired (注入dao)
查询使用分页查询

    @Override
    public PageInfo<User> getAll(int page, int size) {
        PageHelper.startPage(page,size);
        List<User> all = userDao.getAll();
        return new PageInfo<User>(all);
    }
2.3 整合mybatis到spring环境中

​ 2.3.1 SqlSessionFactoryBean
​ 2.3.1.1 数据源(druid + jbdc.properties)
​ 2.3.2 映射扫描

​ !+++++++++!

​ 2.3.3 注解事务
​ 2.3.4 分页插件

    <context:component-scan base-package="com.itheima">
        <!--排除controller包下的bean-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!--加载properties文件-->
    <context:property-placeholder location="classpath*:jdbc.properties"/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--整合mybatis到spring中-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="typeAliasesPackage" value="com.itheima.domain"/>
        <!--分页插件   - 原理 : 在查询的内容的基础上进行了一些功能的增强-->
        <!--private Interceptor[] plugins;-->
        <property name="plugins">
            <!--public void setPlugins(Interceptor... plugins) {
                                        要参数拦截器  ...多个参数
                    this.plugins = plugins;
                }-->
            <array>
                <!--拦截器-->
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <!--要Properties类型的,怎么注入?     -->
                        <!--使用 spring 提供的<prop>为Java持久属性集注入值,也就是向 java.util.Properties 对象中注入值。-->
                        <props>
                            <prop key="helperDialect">mysql</prop>
                            <prop key="reasonable">true</prop>
                        </props>
                    </property>
                </bean>
            </array>
        </property>
    </bean>

    <!--映射扫描-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.itheima.dao"/>
    </bean>

    <!--在业务层接口上开事务管理器-->
    <!--开启注解驱动-->
    <tx:annotation-driven transaction-manager="txManager"/>

    <!--创建事务管理器 - 使用jdbc的事务管理器-->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

开启事务

@Transactional(readOnly = true)//只读事务
public interface UserService {
      @Transactional(readOnly = false) //读写事务
      public boolean save(User user);
}
2.4 创建单元测试

Junit测试业务层接口

package com.itheima.service;  //对service包下的类进行测试


//1、Junit专用的类加载器
@RunWith(SpringJUnit4ClassRunner.class)
//2、指定配置文件
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class UserServiceTest {

    //注入要测试的接口
    @Autowired
    private UserService userService;

    //测试方法
    @Test
    public void testSave(){
        User user = new User();
        user.setUserName("Nami");
        user.setPassword("root");
        user.setRealName("娜美");
        user.setGender(0);
        user.setBirthday(new Date(123456789L));

        userService.save(user);
    }
}
3、SpringMVC
3.1 web.xml 加载SpringMVC

​ 3.1.1 创建spring-mvc.xml

    <!--开启注解扫描-->
    <mvc:annotation-driven/>
    <!--加载controller包下的所有东西-->
    <!--默认情况下,<context:component-scan>查找使用构造型(stereotype)注解所标注的类,
    如@Component(组件),@Service(服务),@Controller(控制器),@Repository(数据仓库)。-->
    <context:component-scan base-package="com.itheima.controller"/>

​ 3.1.2 加载

  <!--  中文过滤-->
  <filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!--  加载文件-->
  <servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath*:spring-mvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
3.2 rest风格
@RestController
@RequestMapping("/user")
public class UserController {


    @GetMapping("/{uuid}")
    public User get(@PathVariable Integer uuid){
        System.out.println("get ..." + uuid);
        return null;
    }

    @PostMapping
    public boolean save(User user){
        System.out.println("save ..." + user);
        return true;
    }

    @PutMapping
    public boolean update(User user){
        System.out.println("update ..." + user);
        return true;
    }

    @DeleteMapping("/{uuid}")
    public boolean delete(@PathVariable Integer uuid){
        System.out.println("delete ..." + uuid);
        return true;
    }
	//注意 : 传两个
    @GetMapping("/{page}/{size}")
    public List getAll(@PathVariable Integer page, @PathVariable Integer size){
        System.out.println("getAll ..." + page+","+size);
        return null;
    }
	//注意 :登录 发post请求
    @PostMapping("/login")
    public User login(String userName,String password){
        System.out.println("login ..." + userName + " ," +password);
        return null;
    }
}
3.3 数据封装为json数据
4、Spring整合SpringMVC
4.1 web.xml 加载Spring环境
    <!--加载哪一个配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:applicationContext.xml</param-value>
    </context-param>
    <!--  启动服务器时,通过监听器加载spring运行环境-->
    <!--加载到ServletContext的上下文中-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
4.2 Controller调用Service
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping
    public boolean save(User user){
        return userService.save(user);
    }

    @PutMapping
    public boolean update(User user){
        return userService.update(user);
    }

    @DeleteMapping("/{uuid}")
    public boolean delete(@PathVariable Integer uuid){
        return userService.delete(uuid);
    }

    @GetMapping("/{uuid}")
    public User get(@PathVariable Integer uuid){
        return userService.get(uuid);
    }

    @GetMapping("/{page}/{size}")
    public PageInfo<User> getAll(@PathVariable Integer page, @PathVariable Integer size){
        return userService.getAll(page,size);
    }

    @PostMapping("/login")
    public User login(String userName,String password){
        return userService.login(userName,password);
    }
}
5、表现层数据封装

返回数据格式 状态 、 数据 、消息

package com.itheima.controller.results;

public class Result {
    //    操作结果编码
    private Integer code;
    //    操作数据结果
    private Object data;
    //    消息
    private String message;

    public Result(Integer code) {
        this.code = code;
    }

    public Result(Integer code, Object data) {
        this.code = code;
        this.data = data;
    }
   // get/set
}
package com.itheima.controller.results;

public class Code {
//    操作结果编码
    public static final Integer SAVE_OK = 20011;
    public static final Integer UPDATE_OK = 20021;
    public static final Integer DELETE_OK = 20031;
    public static final Integer GET_OK = 20041;

    public static final Integer SAVE_ERROR = 20010;
    public static final Integer UPDATE_ERROR = 20020;
    public static final Integer DELETE_ERROR = 20030;
    public static final Integer GET_ERROR = 20040;

//    系统错误编码
//    操作权限编码
//    校验结果编码
}

使用

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping
    public Result save(User user) {
        boolean flag = userService.save(user);
        return new Result(flag ? Code.SAVE_OK : Code.SAVE_ERROR);
    }

    @PutMapping
    public Result update(User user) {
        boolean flag = userService.update(user);
        return new Result(flag ? Code.UPDATE_OK : Code.UPDATE_ERROR);
    }

    @DeleteMapping("/{uuid}")
    public Result delete(@PathVariable Integer uuid) {
        boolean flag = userService.delete(uuid);
        return new Result(flag ? Code.DELETE_OK : Code.DELETE_ERROR);
    }

    @GetMapping("/{uuid}")
    public Result get(@PathVariable Integer uuid) {
        User user = userService.get(uuid);
        return new Result(null != user ? Code.GET_OK : Code.GET_ERROR, user);
    }

    @GetMapping("/{page}/{size}")
    public Result getAll(@PathVariable Integer page, @PathVariable Integer size) {
        PageInfo<User> all = userService.getAll(page, size);
        return new Result(null != all ? Code.GET_OK : Code.GET_ERROR, all);
    }


    @PostMapping("/login")
    public Result login(String userName, String password) {
        User user = userService.login(userName, password);
        return new Result(null != user ? Code.GET_OK : Code.GET_ERROR, user);
    }
}
6、问题消息处理

异常信息要和正常的返回信息统一格式

package com.itheima.system.exception;

public class BusinessException extends RuntimeException {
    
    //自定义异常中封装对应的错误编码,用于异常处理时获取对应的操作编码
    private Integer code;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public BusinessException(Integer code) {
        this.code = code;
    }

    public BusinessException(String message, Integer code) {
        super(message);
        this.code = code;
    }

    public BusinessException(String message, Throwable cause,Integer code) {
        super(message, cause);
        this.code = code;
    }

    public BusinessException(Throwable cause,Integer code) {
        super(cause);
        this.code = code;
    }

    public BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace,Integer code) {
        super(message, cause, enableSuppression, writableStackTrace);
        this.code = code;
    }
}

package com.itheima.controller.interceptor;


@Component
@ControllerAdvice   //设置当前类为异常处理器类
public class ProjectExceptionAdivce {

    @ExceptionHandler(BusinessException.class) //设置指定异常的处理方式
    @ResponseBody   //为了统一格式
    //对出现异常的情况进行拦截,并将其处理成统一的页面数据结果格式
    public Result doBusinessException(BusinessException e){
        return new Result(e.getCode(),e.getMessage()); //e.getCode()  - 上面定义的
    }
}

使用

    @GetMapping("/{uuid}")
    public Result get(@PathVariable Integer uuid){
        User user = userService.get(uuid);
        //模拟出现异常,使用条件控制,便于测试结果
        if (uuid == 10 ) throw new BusinessException("查询出错啦,请重试!",Code.GET_ERROR);
        return new Result(null != user ?Code.GET_OK: Code.GET_ERROR,user);
    }

结果

{
    "code": 20040,
    "data": "查询出错啦,请重试!",
    "message": null
}
镜花水月
原文地址:https://www.cnblogs.com/fengbingshui/p/13620512.html