project2

项目2要做的事情

给大家提供前端,大家做后端的开发

Vue:后台管理(面向管理员)、前端

微信小程序:前台商城(面向用户)、前端

需要搭建一个SpringBoot的应用,以小组为单位搭建SpringBoot应用

后台管理(后天)

182.92.235.201 抓包

抓包是为了

  1. 请求URL → @RequestMapping
  2. 请求方法 → 请求方法限定、作为Json数据判断的一个条件
  3. 请求参数(是否是JSON) → 判断数据的值
  4. 响应结果 → 封装Handler方法的返回值

当然你也可以看前端

前端应用如果要自己开发,大家可以自己把前端跑起来

前端应用:直接放到tomcat/webapps/ROOT

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用bin/startup.bat(sh)把tomcat跑起来

有的同学的tomcat跑不出,JAVA_HOME要配置;如果JAVA_HOME配置了还跑不起来 → 删掉tomcat,重新下载一个,然后解压

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

前台商城(大后天)

微信开发者工具 → 搜索引擎上下载了一个(稳定版)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有一个配置需要大家来做

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

时间安排

今天到下周四上午(13号) → 项目演示

项目奖励:3(300) 2(400) 1(500)

评分标准:35(完整性) 35(Bug) 15(表达) 15(亮点)

项目进度表

【腾讯文档】36th项目二进度表
https://docs.qq.com/sheet/DSkJCZVVCSlljdFRY

分工、进度

提供SQL脚本

后缀为sql的文件,sql脚本里放的就是sql语句

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用sql脚本

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

开发

Git管理应用

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在工作区的根目录创建SpringBoot

搭建SpringBoot应用

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

IDEA中使用Git

使用鼠标右键 → Git 包含具体的操作

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有一个show history的功能还可以

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可以在IDEA中整合Git的命令行,需要配置一下

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

开发Handler方法

解决跨域问题

SpringBoot应用提供一个CorsFilter → 提供一个组件 → 配置类

@Configuration
public class CorsConfig {
    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
        corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
        corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
        return corsConfiguration;
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig()); // 4 对接口配置跨域设置
        return new CorsFilter(source);
    }
}

也可以在配置类里使用WebMvcConfigurer提供的方法来解决

建议大家在项目中使用配置类这个方式(上面的方式)

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

    //这种方式,引入其他filter时有可能导致跨域失效
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("*")
                .allowedHeaders("*");
    }
}

工具

帮你将Json识别为对应的JavaBean → GsonFormmat (plus)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

识别为对应的JavaBean

分页插件

PageHelper

  1. pagehelper-spring-boot-starter
  2. pagehelper.helper-dialect=mysql
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.1</version>
</dependency>
pagehelper:
  helper-dialect: mysql

使用PageHelper

在执行查询之前开启分页信息,page、limit

PageHelper会在预编译时拼接sql语句,拼接分页相关的sql

<sql id="user_column_list">
    id,username,password,gender,last_login_time as lastLoginTime,nickname,mobile,avatar,status,add_time as addTime,update_time as updateTime,deleted
</sql>
<select id="select" resultType="com.cskaoyan.bean.User">
    select <include refid="user_column_list"/>
    from market_user
    <where>
        <if test="username != null">
            username = #{username}
        </if>
    </where>
    order by ${sort} ${order}
</select>
Integer page = param.getPage();//页码
Integer limit = param.getLimit();//数据量
String sort = param.getSort();//排序列
String order = param.getOrder();//desc\asc
PageHelper.startPage(page, limit);

List<KeyWordListVo.ListDTO> listDTOS = keyWordDao.SelectKeyWordList(param, keyword, url);

PageInfo<KeyWordListVo.ListDTO> listDTOPageInfo = new PageInfo<>(listDTOS);

int pages = listDTOPageInfo.getPages();
long total = listDTOPageInfo.getTotal();

日志

logging.level

    logging:
      level:
    #    key是包名、value是日志级别
        com.cskaoyan.mapper: debug

项目能够进到首页

需要有两个接口 /admin/auth/login 和 /admin/auth/info(里面的数据是构造的)

先给大家提供这两个接口,shiro框架 → 视频课程

逆向工程

开发繁琐的地方

数据库给到大家了,表 → 与之对应的JavaBean、Mapper接口、映射文件 → 能够带来可以直接使用的方法

→ 基本上单表能用到的SQL都可以帮你执行

引入依赖

mybatis-generator-core、mysql-connnector-java

<dependency>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-core</artifactId>
    <version>1.4.0</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>
<!--如果要使用mybatis的话就引入mybatis-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.7</version>
</dependency>

配置文件

连接:datasource的配置

javabean目录的配置

mapper接口目录的配置

mapper映射文件目录的配置

<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
                connectionURL="jdbc:mysql://localhost:3306/mall36"
                userId="root"
                password="123456">
    <!--是否去除同名表-->
    <property name="nullCatalogMeansCurrent" value="true"/>
</jdbcConnection>
<!-- javaModelGenerator javaBean生成的配置信息
     targetProject:生成PO类的位置
     targetPackage:生成PO类的类名-->
<javaModelGenerator targetPackage="com.cskaoyan.bean"
                    targetProject=".\src\main\java">
    <!-- enableSubPackages:是否允许子包,是否让schema作为包的后缀
         即targetPackage.schemaName.tableName -->
    <property name="enableSubPackages" value="true" />
    <!-- 从数据库返回的值是否清理前后的空格 -->
    <property name="trimStrings" value="true" />
</javaModelGenerator>


<!-- sqlMapGenerator Mapper映射文件的配置信息
    targetProject:mapper映射文件生成的位置
    targetPackage:生成mapper映射文件放在哪个包下-->
<sqlMapGenerator targetPackage="com.cskaoyan.mapper"
                 targetProject=".\src\main\resources">
    <!-- enableSubPackages:是否让schema作为包的后缀 -->
    <property name="enableSubPackages" value="true" />
</sqlMapGenerator>

<!--
   javaClientGenerator 生成 Model对象(JavaBean)和 mapper XML配置文件 对应的Dao代码
   targetProject:mapper接口生成的位置
   targetPackage:生成mapper接口放在哪个包下

   ANNOTATEDMAPPER
   XMLMAPPER
   MIXEDMAPPER
-->

<javaClientGenerator type="XMLMAPPER"
                     targetPackage="com.cskaoyan.mapper"
                     targetProject=".\src\main\java">
    <!-- enableSubPackages:是否让schema作为包的后缀 -->
    <property name="enableSubPackages" value="true" />
</javaClientGenerator>

使用mac的同学targetProject里面使用 /

<!--生成的JavaBean、接口和映射文件的名称-->
<table tableName="market_admin" domainObjectName="Admin"/>

如果要重新生成,建议先把已有的文件删除掉在重新生成 → 因为映射文件做的是增量更新 → 会导致映射文件中出现相同的id

生成类

配置 能够加载到配置文件的地址

//new File的时候 👉 加载的是working directory的相对目录
File configFile = new File("src/main/resources/generatorConfig.xml");

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用Mapper接口生成的方法

ByPrimaryKey

主要做的事情是生成条件:主键等于一个值的条件

比如

where id = #{id,jdbcType=INTEGER}

Selective

选择性的 → 传入的值不为null → if标签

-- 假设只有id、username、password不为null
-- 哪一列传入了值,则给它插入对应的值;如果没有传入值,相当于该列对应的值为null,则不插入对应的值
-- 数据库表的列可以设置默认值,如果你插入记录的时候,没有给这一列插入对应的值,会采用默认值
-- 如果你要给数据中的某一列插入默认值,你让其传入的这一列对应的参数为null
insert into market_admin (id,username,password) values (#{id,jdbcType=INTEGER},#{username,jdbcType=VARCHAR},#{password,jdbcType=VARCHAR})
<insert id="insertSelective" parameterType="com.cskaoyan.bean.Admin">
  insert into market_admin
  <trim prefix="(" suffix=")" suffixOverrides=",">
    <if test="id != null">
      id,
    </if>
    <if test="username != null">
      username,
    </if>
    <if test="password != null">
      password,
    </if>
    <if test="lastLoginIp != null">
      last_login_ip,
    </if>
    <if test="lastLoginTime != null">
      last_login_time,
    </if>
    <if test="avatar != null">
      avatar,
    </if>
    <if test="addTime != null">
      add_time,
    </if>
    <if test="updateTime != null">
      update_time,
    </if>
    <if test="deleted != null">
      deleted,
    </if>
    <if test="roleIds != null">
      role_ids,
    </if>
  </trim>
  <trim prefix="values (" suffix=")" suffixOverrides=",">
    <if test="id != null">
      #{id,jdbcType=INTEGER},
    </if>
    <if test="username != null">
      #{username,jdbcType=VARCHAR},
    </if>
    <if test="password != null">
      #{password,jdbcType=VARCHAR},
    </if>
    <if test="lastLoginIp != null">
      #{lastLoginIp,jdbcType=VARCHAR},
    </if>
    <if test="lastLoginTime != null">
      #{lastLoginTime,jdbcType=TIMESTAMP},
    </if>
    <if test="avatar != null">
      #{avatar,jdbcType=VARCHAR},
    </if>
    <if test="addTime != null">
      #{addTime,jdbcType=TIMESTAMP},
    </if>
    <if test="updateTime != null">
      #{updateTime,jdbcType=TIMESTAMP},
    </if>
    <if test="deleted != null">
      #{deleted,jdbcType=BIT},
    </if>
    <if test="roleIds != null">
      #{roleIds,jdbcType=VARCHAR},
    </if>
  </trim>
</insert>

update使用selective可以避免其他不需要更新的列 被更新

ByExample

传入了一个参数Example,Example是通过逆向工程生成的。

构造单表的条件

设定排序

去重 distinct

<select id="selectByExample" parameterType="com.cskaoyan.bean.AdminExample" resultMap="BaseResultMap">
  select
  <!--判断Example中的boolean类型的distinct是否为true-->
  <if test="distinct">
    distinct
  </if>
  <include refid="Base_Column_List" />
  from market_admin
    <!--_parameter指的是当前的参数 → example对象本身-->
  <if test="_parameter != null">
    <!--引入sql片段*** 构造的是条件-->
    <include refid="Example_Where_Clause" />
  </if>
    <!--判断example中的orderByClause是否为null-->
  <if test="orderByClause != null">
    order by ${orderByClause}
  </if>
</select>
public Criteria andUsernameLike(String value) {
    addCriterion("username like", value, "username");
    return (Criteria) this;
}
public Criteria andUsernameBetween(String value1, String value2) {
    addCriterion("username between", value1, value2, "username");
    return (Criteria) this;
}
protected abstract static class GeneratedCriteria {
    protected List<Criterion> criteria;
    protected void addCriterion(String condition, Object value, String property) {
        if (value == null) {
            throw new RuntimeException("Value for " + property + " cannot be null");
        }
        criteria.add(new Criterion(condition, value));
    }
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

<!--collection List<Criterion> -->
<foreach collection="criteria.criteria" item="criterion">
  <choose>
    <when test="criterion.noValue">
      and ${criterion.condition}
    </when>
    <when test="criterion.singleValue">
      and ${criterion.condition} #{criterion.value}
    </when>
    <when test="criterion.betweenValue">
      and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
    </when>
    <when test="criterion.listValue">
      and ${criterion.condition}
      <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
        #{listItem}
      </foreach>
    </when>
  </choose>
</foreach>

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意事项

  • 逆向工程生成的是文件 👉 文件可以自己修改

  • 生成的内容不保证没有错误

    • 列名出现sql的关键词,比如from、desc、order 👉 `from`,`desc`,`order`,注意是飘号(esc下面,1左边)不是单引号
    • 会出现在逆向工程的Base_Column_List、update、insert语句、Example中的and方法
    • SyntaxException 语法错误 👉 看控制台 👉 检查控制台中的sql语句
  • 如果要重新生成,先把之前的内容删除掉(至少删除映射文件),增量更新导致出现重复id

  • 不建议在已有的项目中使用逆向工程 👉 有可能导致已有的代码丢失

TypeHandler

类型处理器

前端响应的结果类型 → 和数据库里查询结果封装的类型不一致

mall_admin中的role_ids数据库中的类型varchar

而varchar类型的值 → String → Integer[]

输出映射:varchar → String → Integer[]

输入映射:Integer[] → String → varchar

TypeHandler中完成类型转换:String ↔ Integer[] 可以通过Json的工具类jackson

public interface TypeHandler<T> {
    //输入映射过程 Integer[]   → String
    void setParameter(PreparedStatement var1, int var2, T var3, JdbcType var4) throws SQLException;

    //输出映射过程 String → Integer[]
    T getResult(ResultSet var1, String var2) throws SQLException;

    T getResult(ResultSet var1, int var2) throws SQLException;

    T getResult(CallableStatement var1, int var2) throws SQLException;
}
public class IntegerArrayTypeHandler implements TypeHandler<Integer[]> {
    //jackson
    ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void setParameter(PreparedStatement preparedStatement, int i, Integer[] integers, JdbcType jdbcType) throws SQLException {
        //Integer[] → String
        try {
            String value = objectMapper.writeValueAsString(integers);
            //给对应序号的占位符提供值
            preparedStatement.setString(i, value);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    //String → Integer[]
    @Override
    public Integer[] getResult(ResultSet resultSet, String columnName) throws SQLException {
        try {
            //从结果集中根据列名获得对应类的查询结果
            String result = resultSet.getString(columnName);
            //把String类型的结果封装为参数(resultMap中的property属性对应的参数)需要的类型
            Integer[] integers = objectMapper.readValue(result, Integer[].class);
            return integers;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return new Integer[0];
    }
}

配置typeHandler

如果没有配置的话,需要输入映射和输出映射过程单独来指定

配置的是可用的typeHandler都有谁,并且映射的类型是什么

  • typeHandler的包目录的配置

    • <typeHandlers>
          <package name="com.cskaoyan.typehandler"/>
      </typeHandlers>
      
    • springboot可以直接在配置文件中指定

    • mybatis:
        type-handlers-package: com.cskaoyan.typehandler
      
  • TypeHandler类上指明映射的类型

    • @MappedTypes(Integer[].class)
      @MappedJdbcTypes(JdbcType.VARCHAR)
      public class IntegerArrayTypeHandler implements TypeHandler<Integer[]>{}
      

@MappedTypes这里能写数组的情况不要写List,如果用List类型的识别会有问题

Invalid Binding Exception

Mapper接口和映射文件是对应起来

接口中的方法和标签中的id是对应起来

出现这个异常的场景:

  • 映射文件没有编译进去
  • 映射文件和接口不在同一级目录
  • 名字没有对应起来

SyntaxException → 语法错误

前端也可以看控制台

视图页面没有解析,可以查看console

也可以看前端代码如何解析数据的 → vue、js

jackson

Date ↔ String

直接接收请求参数:@DateTimeFormat

Json日期:@JsonFormat(接收json日期,响应json日期)

日期的格式

jackson可以在配置文件中以jackson作为前缀去做相关配置

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • TypeHandler类上指明映射的类型

    • @MappedTypes(Integer[].class)
      @MappedJdbcTypes(JdbcType.VARCHAR)
      public class IntegerArrayTypeHandler implements TypeHandler<Integer[]>{}
      

@MappedTypes这里能写数组的情况不要写List,如果用List类型的识别会有问题

Invalid Binding Exception

Mapper接口和映射文件是对应起来

接口中的方法和标签中的id是对应起来

出现这个异常的场景:

  • 映射文件没有编译进去
  • 映射文件和接口不在同一级目录
  • 名字没有对应起来

SyntaxException → 语法错误

前端也可以看控制台

视图页面没有解析,可以查看console

也可以看前端代码如何解析数据的 → vue、js

jackson

Date ↔ String

直接接收请求参数:@DateTimeFormat

Json日期:@JsonFormat(接收json日期,响应json日期)

日期的格式

jackson可以在配置文件中以jackson作为前缀去做相关配置

[外链图片转存中…(img-ifJJoOY3-1707112586992)]

  • 26
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值