JAVA —— SpringMVC③

文章目录

  • 今日菜单
  • 目标
  • 1 校验框架
    • 1.1 入门
      • 1.1.1 表单校验的重要性
      • 1.1.2 表单校验分类
      • 1.1.3 格式校验规则
      • 1.1.4 表单校验框架
    • 1.2 快速使用
    • 小结
    • 1.3 多规则校验
    • 1.4 嵌套校验
    • 1.5 分组校验
  • 2 SSM整合
    • 2.1 整合流程简介
    • 2.2 项目结构搭建
    • 2.3 Spring整合Mybatis(复习)
      • 2.3.1 Spring整合Mybatis
      • 2.3.2 配置分页插件与事务
    • 2.4 整合junit(复习)
    • 小结
    • 2.5 Spring整合SpringMVC
      • 2.5.1 Rest风格开发SpringMVC(复习)
      • 2.5.2 Spring整合SpringMVC
    • 2.6 表现层数据封装
    • 2.7 自定义异常
    • 2.8 返回消息兼容异常信息
  • 3 纯注解开发SSM
    • 3.1 用注解代替UserDao.xml
    • 3.2 用注解替代applicationContext.xml
    • 3.3 用注解替代spring-mvc.xml
    • 3.4 用注解替代web.xml
  • 4 企业开发中新增和修改传参方式
    • 4.1使用Postman模拟ajsx中的json提交
      • 新增和修改
    • 4.2 使用Postman模拟表单提交


今日菜单

  1. 实用技术-校验框架
  2. SSM整合
  3. 纯注解开发SSM

目标

  • 能够阐述表单验证的分类和区别
  • 能够运用表单验证的常用注解
  • 能够编写表单验证的示例
  • 能够编写SSM整合的应用案例
  • 能够总结SSM整合的步骤

1 校验框架

1.1 入门

1.1.1 表单校验的重要性

表单校验保障了数据有效性、安全性

JAVA —— SpringMVC③_第1张图片

数据可以随意输入,导致错误的结果。

1.1.2 表单校验分类

  • 按校验位置分类:
    • 客户端校验:浏览器,手机APP
    • 服务端校验:后端服务器代码校验
  • 按校验内容分类:
    • 格式校验:比如年龄是否为负数,邮箱是否符合规则
      • 客户端:使用Js技术,利用正则表达式校验
      • 服务端:使用校验框架
    • 逻辑校验:比如用户名在当前项目中是否已注册 (需要查询数据库或者业务校验)
      • 客户端:使用ajax发送要校验的数据,在服务端完成逻辑校验,返回校验结果
      • 服务端:接收到完整的请求后,在执行业务操作前完成逻辑校验

1.1.3 格式校验规则

以下几种全部属于格式校验:

  • 长度:例如用户名长度,评论字符数量
  • 非法字符:例如用户名组成
  • 数据格式:例如Email格式、 IP地址格式
  • 边界值:例如转账金额上限,年龄上下限
  • 重复性:例如用户名是否重复

1.1.4 表单校验框架

  • JSR(Java Specification Requests):Java 规范提案

    303:提供bean属性相关校验规则

  • JCP(Java Community Process):提出JSR规范议案

    • 一个开放性的国际技术标准组织,职责是发展和更新Java技术规范。
    • 成员:甲骨文、ARM、IBM、Intel、SAP、Twitter、阿里巴巴、亚马逊等
  • JSR规范列表

    • 企业应用技术
       Contexts and Dependency Injection for Java (Web Beans 1.0) (JSR 299)
       Dependency Injection for Java 1.0 (JSR 330)@postConstruct, @PreDestroy
       Bean Validation 1.0 (JSR 303)
       Enterprise JavaBeans 3.1 (includes Interceptors 1.1) (JSR 318)
       Java EE Connector Architecture 1.6 (JSR 322)
       Java Persistence 2.0 (JSR 317)
       Common Annotations for the Java Platform 1.1 (JSR 250)
       Java Message Service API 1.1 (JSR 914)
       Java Transaction API (JTA) 1.1 (JSR 907)
       JavaMail 1.4 (JSR 919)
    • Web应用技术
       Java Servlet 3.0 (JSR 315)
       JavaServer Faces 2.0 (JSR 314)
       JavaServer Pages 2.2/Expression Language 2.2 (JSR 245)
       Standard Tag Library for JavaServer Pages (JSTL) 1.2 (JSR 52)
       Debugging Support for Other Languages 1.0 (JSR 45)
       模块化 (JSR 294)
       Swing应用框架 (JSR 296)
       JavaBeans Activation Framework (JAF) 1.1 (JSR 925)
       Streaming API for XML (StAX) 1.0 (JSR 173)
    • 管理与安全技术
       Java Authentication Service Provider Interface for Containers (JSR 196)
       Java Authorization Contract for Containers 1.3 (JSR 115)
       Java EE Application Deployment 1.2 (JSR 88)
       J2EE Management 1.1 (JSR 77)
       Java SE中与Java EE有关的规范
       JCache API (JSR 107)
       Java Memory Model (JSR 133)
       Concurrency Utilitie (JSR 166)
       Java API for XML Processing (JAXP) 1.3 (JSR 206)
       Java Database Connectivity 4.0 (JSR 221)
       Java Management Extensions (JMX) 2.0 (JSR 255)
       Java Portlet API (JSR 286)
  • Web Service技术
     Java Date与Time API (JSR 310)
     Java API for RESTful Web Services (JAX-RS) 1.1 (JSR 311)
     Implementing Enterprise Web Services 1.3 (JSR 109)
     Java API for XML-Based Web Services (JAX-WS) 2.2 (JSR 224)
     Java Architecture for XML Binding (JAXB) 2.2 (JSR 222)
     Web Services Metadata for the Java Platform (JSR 181)
     Java API for XML-Based RPC (JAX-RPC) 1.1 (JSR 101)
     Java APIs for XML Messaging 1.3 (JSR 67)
     Java API for XML Registries (JAXR) 1.0 (JSR 93)

  • JSR303实现:校验框架hibernate-validator

    导入坐标

    
    <dependency>
        <groupId>javax.validationgroupId>
        <artifactId>validation-apiartifactId>
        <version>2.0.1.Finalversion>
    dependency>
    
    <dependency>
        <groupId>org.hibernategroupId>
        <artifactId>hibernate-validatorartifactId>
        <version>6.1.0.Finalversion>
    dependency>
    

    注意:
    tomcat7 :搭配hibernate-validator版本5...Final
    tomcat8.5↑ :搭配hibernate-validator版本6...Final

1.2 快速使用

1. 开启校验

 名称:@Valid 、 @Validated
 类型:形参注解
 位置:处理器类中的实体类类型的方法形参前方
 作用:设定对当前实体类类型参数进行校验
 范例:

@RequestMapping(value = "/addemployee")
public String addEmployee(@Valid Employee employee) {
    System.out.println(employee);
    return "success";
}

2.设置校验规则

 名称:@NotNull, @NotBlank, @NotEmpty
 类型:属性注解 等
 位置:属性上方
 作用:设定当前属性校验规则
 范例:
每个校验规则所携带的参数不同,根据校验规则进行相应的调整
具体的校验规则查看对应的校验框架进行获取

public class Employee{
    @NotBlank(message = "姓名不能为空")
    private String name;//员工姓名
}  

3.获取错误信息

通过形参Errors获取校验结果数据,通过Model接口将数据封装后传递到页面显示

@RequestMapping(value = "/addemployee")
public String addEmployee(@Valid Employee employee, Errors errors, Model model){
    System.out.println(employee);
    if(errors.hasErrors()){
        for(FieldError error : errors.getFieldErrors()){
            model.addAttribute(error.getField(),error.getDefaultMessage());
        }
        return "addemployee.jsp";
    }
    return "success.jsp";
}

页面获取后台封装的校验结果信息

<form action="/addemployee" method="post">
    员工姓名:<input type="text" name="name"><span style="color:red">${name}span><br/>
    员工年龄:<input type="text" name="age"><span style="color:red">${age}span><br/>
    <input type="submit" value="提交">
form>

小结

  1. 方法参数上开启校验:@Valid 、 @Validated
  2. Bean的属性上设置校验规则:@NotBlank
  3. 通过参数Errors获取错误信息

1.3 多规则校验

同一个字段有多个约束条件

  • 同一个属性可以添加多个校验器

    @NotNull(message = "请输入您的年龄")
    @Max(value = 60,message = "年龄最大值不允许超过60岁")
    @Min(value = 18,message = "年龄最小值不允许低于18岁")
    private Integer age;//员工年龄
    
  • 3种判定空校验器的区别

JAVA —— SpringMVC③_第2张图片

1.4 嵌套校验

引用类型字段如何校验

 名称:@Valid
 类型:属性注解
 位置:实体类中的引用类型属性上方
 作用:设定当前应用类型属性中的属性开启校验
 范例:

public class Employee {
    //实体类中的引用类型通过标注@Valid注解,设定开启当前引用类型字段中的属性参与校验
    @Valid
    private Address address;
    
    //添加address属性的get,set方法
}

注意:开启嵌套校验后,被校验对象内部需要添加对应的校验规则,并添加嵌套属性的get,set方法

//嵌套校验的实体中,对每个属性正常添加校验规则即可
public class Address {
    @NotBlank(message = "请输入省份名称")
    private String provinceName;//省份名称

    @NotBlank(message = "请输入城市名称")
    private String cityName;//城市名称

    @NotBlank(message = "请输入详细地址")
    private String detail;//详细住址

    @NotBlank(message = "请输入邮政编码")
    @Size(max = 6, min = 6, message = "邮政编码由6位组成")
    private String zipCode;//邮政编码
    
    //添加get,set方法
    
}

jsp页面中获取嵌套属性中的错误信息

${requestScope['address.cityName']}

<%--注意,引用类型的校验未通过信息不是通过对象进行封装的,直接使用对象名.属性名的格式作为整体属性字符串进行保存的,和使用者的属性传递方式有关,不具有通用性,仅适用于本案例--%>
省:<input type="text" name="address.provinceName"><span style="color:red">${requestScope['address.provinceName']}span><br/>
市:<input type="text" name="address.cityName"><span
         style="color:red">${requestScope['address.cityName']}span><br/>

1.5 分组校验

根据业务不同需要调整是否参与校验,比如同一个模块,新增和修改时校验规则是不一致的

  • 新增用户:新增时用户名不能为空
  • 修改用户:修改时不能修改用户名,所以不用强制用户名不能为空

解决方案:对不同种类的属性进行分组,在校验时可以指定参与校验的字段所属的组类别

  • 定义组(通用)
  • 为属性设置所属组,可以设置多个
  • 开启组校验
public interface GroupOne {
}

public String addEmployee(@Validated({GroupOne.class}) Employee employee){
}  

@NotEmpty(message = "姓名不能为空",groups = {GroupOne.class})
private String name;//员工姓名

2 SSM整合

2.1 整合流程简介

整合步骤分析:SSM(Spring+SpringMVC+MyBatis)

JAVA —— SpringMVC③_第3张图片

表结构

JAVA —— SpringMVC③_第4张图片

2.2 项目结构搭建

Part0: 项目基础结构搭建

  • 创建项目,组织项目结构,创建包
  • 创建表与实体类
  • 创建三层架构对应的模块、接口与实体类,建立关联关系
    • 数据层接口(代理自动创建实现类)
    • 业务层接口+业务层实现类
    • 表现层类
public interface UserDao {
    /**
     * 添加用户
     * @param user
     * @return
     */
    public boolean save(User user);

    /**
     * 修改用户
     * @param user
     * @return
     */
    public boolean update(User user);

    /**
     * 删除用户
     * @param uuid
     * @return
     */
    public boolean delete(Integer uuid);

    /**
     * 查询单个用户信息
     * @param uuid
     * @return
     */
    public User get(Integer uuid);

    /**
     * 查询全部用户信息
     * @return
     */
    public List<User> getAll();


    /**
     * 根据用户名密码查询个人信息
     * @param userName 用户名
     * @param password 密码信息
     * @return
     */
    //注意:数据层操作不要和业务层操作的名称混淆,通常数据层仅反映与数据库间的信息交换,不体现业务逻辑
    public User getByUserNameAndPassword(String userName,String password);
}

public interface UserService {
    /**
     * 添加用户
     * @param user
     * @return
     */
    public boolean save(User user);

    /**
     * 修改用户
     * @param user
     * @return
     */
    public boolean update(User user);

    /**
     * 删除用户
     * @param uuid
     * @return
     */
    public boolean delete(Integer uuid);

    /**
     * 查询单个用户信息
     * @param uuid
     * @return
     */
    public User get(Integer uuid);

    /**
     * 查询全部用户信息
     * @return
     */
    public List<User> getAll();

    /**
     * 根据用户名密码进行登录
     * @param userName
     * @param password
     * @return
     */
    public User login(String userName,String password);
}

2.3 Spring整合Mybatis(复习)

JAVA —— SpringMVC③_第5张图片

在pom.xml引入坐标:

<dependencies>
    
    
    
    


    
    
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-webmvcartifactId>
      <version>5.1.9.RELEASEversion>
    dependency>


    
    
    
    <dependency>
      <groupId>org.mybatisgroupId>
      <artifactId>mybatisartifactId>
      <version>3.5.3version>
    dependency>

    
    <dependency>
      <groupId>mysqlgroupId>
      <artifactId>mysql-connector-javaartifactId>
      <version>5.1.47version>
    dependency>

    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-jdbcartifactId>
      <version>5.1.9.RELEASEversion>
    dependency>

    
    <dependency>
      <groupId>org.mybatisgroupId>
      <artifactId>mybatis-springartifactId>
      <version>2.0.3version>
    dependency>

    
    <dependency>
      <groupId>com.alibabagroupId>
      <artifactId>druidartifactId>
      <version>1.1.16version>
    dependency>

    
    <dependency>
      <groupId>com.github.pagehelpergroupId>
      <artifactId>pagehelperartifactId>
      <version>5.1.2version>
    dependency>

    
    <dependency>
      <groupId>com.fasterxml.jackson.coregroupId>
      <artifactId>jackson-databindartifactId>
      <version>2.9.0version>
    dependency>
    
    
    <dependency>
      <groupId>javax.servletgroupId>
      <artifactId>javax.servlet-apiartifactId>
      <version>3.1.0version>
      <scope>providedscope>
    dependency>


    
    
    
    
    <dependency>
      <groupId>junitgroupId>
      <artifactId>junitartifactId>
      <version>4.12version>
    dependency>
    
    <dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-testartifactId>
      <version>5.1.9.RELEASEversion>
    dependency>
  dependencies>

2.3.1 Spring整合Mybatis

  • 创建Spring配置文件:组件扫描
  • 创建MyBatis映射文件
  • 整合MyBatis到Spring环境中
    • SqlSesionFactoryBean
    • 数据源(druid+jdbc.properties)
    • 映射扫描
  1. Spring环境配置:applicationContext.xml

    
    <beans xmlns="http://www.springframework.org/schema/beans"  xmlns:context="http://www.springframework.org/schema/context"  xmlns:tx="http://www.springframework.org/schema/tx"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd  http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd  http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx.xsd">
    
        
        <context:component-scan base-package="com.xxx"/>
    
    beans>
    
    
  2. MyBatis映射文件:UserDao.xml
    注意目录:resources\com\xxx\dao\UserDao.xml

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.xxx.dao.UserDao">
    
        
        <insert id="save" parameterType="user">
            insert into user(userName,password,realName,gender,birthday)values(#{userName},#{password},#{realName},#{gender},#{birthday})
        insert>
    
        
        <delete id="delete" parameterType="int">
            delete from user where uuid = #{uuid}
        delete>
    
        
        <update id="update" parameterType="user">
            update user set userName=#{userName},password=#{password},realName=#{realName},gender=#{gender},birthday=#{birthday} where uuid=#{uuid}
        update>
    
        
        <select id="get" resultType="user" parameterType="int">
            select * from user where uuid = #{uuid}
        select>
    
        
        <select id="getAll" resultType="user">
            select * from user
        select>
    
        
        <select id="getByUserNameAndPassword" resultType="user" >
            select * from user where userName=#{userName} and password=#{password}
        select>
    
    mapper>
    
    
  3. 整合MyBatis到Spring环境中:数据源(druid+jdbc.properties)、SqlSesionFactoryBean、映射扫描
    applicationContext.xml

    
    <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>
    
    
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="typeAliasesPackage" value="com.xxx.domain"/>
    bean>
    
    
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.xxx.dao"/>
    bean>
    
    

2.3.2 配置分页插件与事务

  1. 添加分页插件坐标

    
    <dependency>
      <groupId>com.github.pagehelpergroupId>
      <artifactId>pagehelperartifactId>
      <version>5.1.2version>
    dependency>
    
    
  2. 配置分页插件pagehelper:applicationContext.xml

    
        <bean class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="typeAliasesPackage" value="com.xxx.domain"/>
            
            <property name="plugins">
                <array>
                    <bean class="com.github.pagehelper.PageInterceptor">
                        <property name="properties">
                            <props>
                                <prop key="helperDialect">mysqlprop>
                                
                                <prop key="reasonable">trueprop>
                            props>
                        property>
                    bean>
                array>
            property>
        bean>
    
    
  3. 添加事务管理:applicationContext.xml

    • 确认已添加tx命名空间

      
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:context="http://www.springframework.org/schema/context"
             xmlns:tx="http://www.springframework.org/schema/tx"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
              http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
      
      
    • 配置事务管理器

      
      <tx:annotation-driven transaction-manager="txManager"/>
      
      
      <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          <property name="dataSource" ref="dataSource"/>
      bean>
      
      
    • 在类上或方法上添加@Transactional注解

      //类上
      @Transactional(readOnly = true)
      
      
      //方法上
      @Transactional(readOnly = false)
      
      

2.4 整合junit(复习)

测试环境使用单独的数据库配置:在test\resources放置一套applicationContext.xml和jdbc.properties

JAVA —— SpringMVC③_第6张图片

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class UserServiceTest {

@Autowired
    private UserService userService;

    @Test
    public void testSave(){
        User user = new User();
        user.setUserName("Jock");
        user.setPassword("root");
        user.setRealName("Jockme");
        user.setGender(1);
        user.setBirthday(new Date(333333000000L));

        userService.save(user);
    }

    @Test
    public void testDelete(){
        User user = new User();
        userService.delete(3);
    }

    @Test
    public void testUpdate(){
        User user = new User();
        user.setUuid(1);
        user.setUserName("Jockme");
        user.setPassword("root");
        user.setRealName("JockIsMe");
        user.setGender(1);
        user.setBirthday(new Date(333333000000L));

        userService.update(user);
    }

    @Test
    public void testGet(){
        User user = userService.get(1);
        System.out.println(user);
    }

    @Test
    public void testGetAll(){
        PageInfo<User> all = userService.getAll(2, 2);
        System.out.println(all);
        System.out.println(all.getList().get(0));
        System.out.println(all.getList().get(1));
    }

    @Test
    public void testLogin(){
        User user = userService.login("Jockme", "root");
        System.out.println(user);
    }
}

小结

JAVA —— SpringMVC③_第7张图片

2.5 Spring整合SpringMVC

JAVA —— SpringMVC③_第8张图片

2.5.1 Rest风格开发SpringMVC(复习)

Part3: 配置SpringMVC,完成如下4个步骤:

  1. 在web.xml中配置DispatcherServlet,并加载spring-mvc.xml

    
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
             version="3.1">
    <servlet>
        <servlet-name>DispatcherServletservlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <init-param>
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath*:spring-mvc.xmlparam-value>
        init-param>
    servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServletservlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>
        
    web-app>
    
    
  2. 配置spring-mvc.xml只加载Controller

    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <mvc:annotation-driven/>
    
        <context:component-scan base-package="com.xxx.controller"/>
    
    beans>
    
    
  3. 修改applicationContext.xml的包扫描,排除@Controller标记的类

    
    <context:component-scan base-package="com.xxx">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    context:component-scan>
    
    
  4. 编写UserController

    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @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("/{uuid}")
        public User get(@PathVariable Integer uuid){
            System.out.println("get ..." + uuid);
            return null;
        }
    
        @GetMapping("/{page}/{size}")
        public List getAll(@PathVariable Integer page,@PathVariable Integer size){
            System.out.println("getAll ..." + page+","+size);
            return null;
        }
    
        @PostMapping("/login")
        public User login(String userName,String password){
            System.out.println("login ..." + userName + " ," +password);
            return null;
        }
    
    }
    
    

2.5.2 Spring整合SpringMVC

Part4:完成如下2个步骤:

  1. web.xml加载Spring环境

    <context-param>
        <param-name>contextConfigLocationparam-name>
        <param-value>classpath*:applicationContext.xmlparam-value>
    context-param>
    
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
    listener>
    
    
  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);
        }
    
    }
    
    

2.6 表现层数据封装

Part5-1: 表现层数据封装

操作类型 返回数据 格式
操作是否成功 true/false 格式A
单个数据 1, “zhangshan” 格式B
对象数据 json对象:{“name”:“Jock”,“age”:39} 格式C
集合数据 json数组:[{“name”:“Jock”,“age”:39},{“name”:“Jockme”,“age”:40}] 格式D

JAVA —— SpringMVC③_第9张图片

下面进行表现层数据封装,分为如下4个步骤:

  1. 返回数据格式设计

JAVA —— SpringMVC③_第10张图片

  1. 编写返回数据封装类:Result

    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;
        }
    
        public Result(Integer code, String message) {
            this.code = code;
            this.message = message;
        }
    }
    
    
  2. 状态码常量可以根据自己的业务需求设定

    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;
    
    //    系统错误编码
    
    //    操作权限编码
    
    //    校验结果编码
    
    }
    
    
  3. Controller 调用

    @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);
        }
    
    }
    
    

2.7 自定义异常

Part5-2: 自定义异常处理

  1. 设定自定义业务异常,封装程序执行过程中出现的问题,便于表现层进行统一的异常拦截并进行处理

    BusinessException

    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;
        }
    }
    
    
  2. 自定义异常消息返回时需要与业务正常执行的消息按照统一的格式进行处理

    @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);
    }
    
    

2.8 返回消息兼容异常信息

在异常处理类中,将异常信息封装成Result对象:

@RestControllerAdvice
public class ProjectExceptionAdvice {

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

    @ExceptionHandler(Exception.class)
    public Result doOtherException(Exception e) {
        return new Result(500, "请稍候重试");
    }

}

3 纯注解开发SSM

需要使用注解改造的配置文件如下所示:

  • UserDao.xml
  • applicationContext.xml
  • web.xml
  • spring-mvc.xml

3.1 用注解代替UserDao.xml

使用MyBatis提供的注解在UserDao接口中改造

public interface UserDao {
    /**
     * 添加用户
     * @param user
     * @return
     */
    @Insert("insert into user(userName,password,realName,gender,birthday)values(#{userName},#{password},#{realName},#{gender},#{birthday})")
    public boolean save(User user);

    /**
     * 修改用户
     * @param user
     * @return
     */
    @Update("update user set userName=#{userName},password=#{password},realName=#{realName},gender=#{gender},birthday=#{birthday} where uuid=#{uuid}")
    public boolean update(User user);

    /**
     * 删除用户
     * @param uuid
     * @return
     */
    @Delete("delete from user where uuid = #{uuid}")
    public boolean delete(Integer uuid);

    /**
     * 查询单个用户信息
     * @param uuid
     * @return
     */
    @Select("select * from user where uuid = #{uuid}")
    public User get(Integer uuid);

    /**
     * 查询全部用户信息
     * @return
     */
    @Select("select * from user")
    public List<User> getAll();


    /**
     * 根据用户名密码查询个人信息
     * @param userName 用户名
     * @param password 密码信息
     * @return
     */
    @Select("select * from user where userName=#{userName} and password=#{password}")
    //注意:数据层操作不要和业务层操作的名称混淆,通常数据层仅反映与数据库间的信息交换,不体现业务逻辑
    public User getByUserNameAndPassword(@Param("userName") String userName,@Param("password") String password);
}

易错点:删除UserDao.xml

3.2 用注解替代applicationContext.xml

共分为如下3个步骤:

  1. 新建Druid数据源配置类:JdbcConfig

    public class JdbcConfig {
        //使用注入的形式,读取properties文件中的属性值,等同于
        @Value("${jdbc.driver}")
        private String driver;
        @Value("${jdbc.url}")
        private String url;
        @Value("${jdbc.username}")
        private String userName;
        @Value("${jdbc.password}")
        private String password;
    
        //定义dataSource的bean,等同于
        @Bean("dataSource")
        public DataSource getDataSource(){
            //创建对象
            DruidDataSource ds = new DruidDataSource();
            //手工调用set方法,等同于set属性注入
            ds.setDriverClassName(driver);
            ds.setUrl(url);
            ds.setUsername(userName);
            ds.setPassword(password);
            return ds;
        }
    }
    
    
  2. 新建MyBatis配置类:MyBatisConfig,添加分页插件pageHelper配置

    public class MyBatisConfig {
        //定义MyBatis的核心连接工厂bean,等同于
        @Bean
        //参数使用自动装配的形式加载dataSource,为set注入提供数据,dataSource来源于JdbcConfig中的配置
        public SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource dataSource,@Autowired Interceptor interceptor){
            SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
            //等同于
            ssfb.setTypeAliasesPackage("com.xxx.domain");
            //等同于
            ssfb.setDataSource(dataSource);
            ssfb.setPlugins(interceptor);
            return ssfb;
        }
    
        //定义MyBatis的映射扫描,等同于
        @Bean
        public MapperScannerConfigurer getMapperScannerConfigurer(){
            MapperScannerConfigurer msc = new MapperScannerConfigurer();
            //等同于
            msc.setBasePackage("com.xxx.dao");
            return msc;
        }
    
        //分页插件pageHelper配置
        @Bean("pageInterceptor")
        public Interceptor getPageInterceptor(){
            Interceptor interceptor = new PageInterceptor();
            Properties properties = new Properties();
            properties.setProperty("helperDialect","mysql");
            properties.setProperty("reasonable","true");
            //等同于
            interceptor.setProperties(properties);
            return interceptor;
        }
    
    }
    
    
  3. 新建Spring配置类:SpringConfig,完成事务管理配置

    @Configuration
    //等同于
    @ComponentScan(value = "com.xxx",excludeFilters =
        //等同于
        @ComponentScan.Filter(type= FilterType.ANNOTATION,classes = {Controller.class}))
    //等同于
    @PropertySource("classpath:jdbc.properties")
    //等同于,bean的名称默认取transactionManager
    @EnableTransactionManagement
    @Import({MyBatisConfig.class,JdbcConfig.class})
    public class SpringConfig {
        //等同于
        @Bean("transactionManager")
        //等同于
        public DataSourceTransactionManager getTxManager(@Autowired DataSource dataSource){
            DataSourceTransactionManager tm = new DataSourceTransactionManager();
            //等同于
            tm.setDataSource(dataSource);
            return tm;
        }
    }
    
    

3.3 用注解替代spring-mvc.xml

  • 添加@EnableWebMvc注解

    @Configuration
    @ComponentScan("com.xxx.controller")
    @EnableWebMvc
    public class SpringMvcConfig implements WebMvcConfigurer {
    }
    
    
  • EnableWebMvc (了解)

  1. 支持ConversionService的配置,可以方便配置自定义类型转换器
  2. 支持@NumberFormat注解格式化数字类型
  3. 支持@DateTimeFormat注解格式化日期数据,日期包括Date,Calendar,JodaTime(JodaTime要导包)
  4. 支持@Valid的参数校验(需要导入JSR-303规范)
  5. 配合第三方jar包和SpringMVC提供的注解读写XML和JSON格式数据

3.4 用注解替代web.xml

  1. 新建Servlet容器初始化配置类:ServletContainersInitConfig

    public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    
        //创建Servlet容器时,使用注解的方式加载SPRINGMVC配置类中的信息,并加载成WEB专用的ApplicationContext对象
        //该对象放入了ServletContext范围,后期在整个WEB容器中可以随时获取调用
        @Override
        protected WebApplicationContext createServletApplicationContext() {
            AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
            ctx.register(SpringMvcConfig.class);
            return ctx;
        }
    
        //注解配置映射地址方式,服务于SpringMVC的核心控制器DispatcherServlet
        @Override
        protected String[] getServletMappings() {
            return new String[]{"/"};
        }
    
        //乱码处理作为过滤器,在servlet容器启动时进行配置,相关内容参看Servlet零配置相关
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
            //触发父类的onStartup
            super.onStartup(servletContext);
            //1.创建字符集过滤器对象
            CharacterEncodingFilter cef = new CharacterEncodingFilter();
            //2.设置使用的字符集
            cef.setEncoding("UTF-8");
            //3.添加到容器(它不是ioc容器,而是ServletContainer)
            FilterRegistration.Dynamic registration = servletContext.addFilter("characterEncodingFilter", cef);
            //4.添加映射
            registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE), false, "/*");
        }
    }
    
    
  2. 添加加载spring核心配置文件,生成Spring核心容器(主容器/父容器/根容器)

    @Override
    //基本等同于org.springframework.web.context.ContextLoaderListener
    protected WebApplicationContext createRootApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringConfig.class);
        return ctx;
    }
    
    
  • 父容器:Spring环境加载后形成的容器,包含spring环境下所有的bean,配置文件和Service层的bean
  • 子容器:当前springmvc环境加载后形成的容器,不包含spring环境下的bean,只包含Controller层的bean
  • 子容器可以访问父容器中的资源,父容器不可以访问子容器中的资源

易错点:删除web.xml

4 企业开发中新增和修改传参方式

4.1使用Postman模拟ajsx中的json提交

新增和修改

全部使用JSON格式传参

  1. Controller中使用@RestController,在方法参数前添加@RequestBody

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

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

2.使用Postman构建新增数据(JSON格式)

​ 新增JSON

{
    "userName": "zhangsan",
    "password": "root",
    "realName": "zs",
    "gender": 1
}

修改JSON:根据uuid进行修改

{
    "userName": "zhangsan",
    "password": "root",
    "realName": "zs",
    "gender": 1,
    "uuid" : 1
}

Postman中的操作

JAVA —— SpringMVC③_第11张图片

4.2 使用Postman模拟表单提交

  1. Controller中编写登录方法

    @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);
    }
    
    
  2. 使用Postman构建表单数据

JAVA —— SpringMVC③_第12张图片

你可能感兴趣的:(java基础,java,开发语言,后端,spring,mvc)