开始时间:2022-03-02
课程链接:米米商城
mybatis逆向工程
mybatis需要程序员自己编写sql语句,mybatis官方提供逆向工程,可以针对单表自动生成mybatis执行所需要的代码(mapper.java、mapper.xml、pojo…)
逆向工程代码源
网盘链接:https://pan.baidu.com/s/1ssifbwCDGgNbNCxFJhjuDg 提取码:ozwv
要将其放在纯英文路径下才行
然后导入到idea里面
配置generatorConfig
主体不要动,只把相应路径和数据库密码修改一下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="testTables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mimissm?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true" userId="root"
password="333">
</jdbcConnection>
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和
NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- targetProject:生成PO类的位置 -->
<javaModelGenerator targetPackage="BUPT.pojo"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="BUPT.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="BUPT.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 指定数据库表 -->
<table schema="" tableName="admin"></table>
<table schema="" tableName="product_info"></table>
<table schema="" tableName="product_type"></table>
</context>
</generatorConfiguration>
然后打开GeneratorSqlmap
package com.oracle.mybatis.tools;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.DefaultShellCallback;
public class GeneratorSqlmap {
public void generator() throws Exception{
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
//指定 逆向工程配置文件
File configFile = new File("generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
callback, warnings);
myBatisGenerator.generate(null);
}
public static void main(String[] args) throws Exception {
try {
GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
generatorSqlmap.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
执行主方法
这里有几个注意点
一个是要在数据库中有对应的表,一个是数据库要处于链接状态
还需要注意,新导入的这个逆向工程,记得选中jdk,我因为没选jdk导致通篇爆红
执行完后得到以下代码
MD5加密算法的演示
我们为了安全,是不会将密码以明文形式显示的
注册时,将密码进行md5加密,存到数据库中,防止可以看到数据库数据的人恶意篡改。
登录时,将密码进行md5加密,与存储在数据库中加密过的密码进行比对
先在我们的utils包里面添加MD5的执行类
/**
* 1.MD5(message-digest algorithm 5)信息摘要算法,
* 它的长度一般是32位的16进制数字符串(如81dc9bdb52d04dc20036dbd8313ed055)
* 2.由于系统密码明文存储容易被黑客盗取
* 3.应用:注册时,将密码进行md5加密,存到数据库中,防止可以看到数据库数据的人恶意篡改。
* 登录时,将密码进行md5加密,与存储在数据库中加密过的密码进行比对
* 4.md5不可逆,即没有对应的算法,从产生的md5值逆向得到原始数据。
* 但是可以使用暴力破解,这里的破解并非把摘要还原成原始数据,如暴力枚举法。
*
*/
package BUPT.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Util {
public final static String getMD5(String str){
try {
MessageDigest md = MessageDigest.getInstance("SHA");//创建具有指定算法名称的摘要
md.update(str.getBytes()); //使用指定的字节数组更新摘要
byte mdBytes[] = md.digest(); //进行哈希计算并返回一个字节数组
String hash = "";
for(int i= 0;i<mdBytes.length;i++){ //循环字节数组
int temp;
if(mdBytes[i]<0) //如果有小于0的字节,则转换为正数
temp =256+mdBytes[i];
else
temp=mdBytes[i];
if(temp<16)
hash+= "0";
hash+=Integer.toString(temp,16); //将字节转换为16进制后,转换为字符串
}
return hash;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
}
然后在test下进行一个小测试
package BUPT.Test;
import BUPT.utils.MD5Util;
import org.junit.Test;
public class MyTest {
@Test
public void testMD5() {
String mi = MD5Util.getMD5("000000");
System.out.println("加密后的密码为:" + mi);
}
}
6个0的执行结果为
加密后的密码为:c984aed014aec7623a54f0591da07a85fd4b762d
这正好就是我们数据库开始存入的数据
登录的业务逻辑层实现
在service包下进行代码编写
接口类
直接返回一个对象,方便后续灵活调用
package BUPT.service;
import BUPT.pojo.Admin;
public interface AdminService {
Admin login(String name, String pwd);
}
接口类的实现类
package BUPT.service;
import BUPT.mapper.AdminMapper;
import BUPT.pojo.Admin;
import BUPT.pojo.AdminExample;
import BUPT.utils.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
//业务逻辑层的对象创建交给Spring
@Service
public class AdminServiceImpl implements AdminService {
//在业务逻辑层中,一定会有数据访问层的对象,Spring来new出来
@Autowired
AdminMapper adminMapper;
@Override
public Admin login(String name, String pwd) {
//判断登录就得拿传入的对象和数据库中相应对象进行对比
//如果有条件需要SQL语句,则一定要创建AdminExample对象来封装条件
//也就是说SQL语句我们也不会完整的写下来而是拼接条件生成语句
//创建存放 封装条件的对象
AdminExample example = new AdminExample();
//例如这里我们需要的是 select * from admin where a_name='admin'
//传进去就是我们要比对的条件 name
//创造条件,添加条件
example.createCriteria().andANameEqualTo(name);
// 查询返回结果是一个list
List<Admin> list = adminMapper.selectByExample(example);
if (list.size() > 0) {
Admin admin = list.get(0);
//能进入到这里面,就可以进行密码比对
String miPwd = MD5Util.getMD5(pwd);
if (miPwd.equals(admin.getaPass())) {
return admin;
}
}
return null;
}
}
补充controller的AdminAction方法
package BUPT.controller;
import BUPT.pojo.Admin;
import BUPT.service.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
@Controller
@RequestMapping("/admin")
public class AdminAction {
//切记:在所有的界面层,一定会有业务逻辑层的对象
@Autowired
AdminService adminService;
//实现登录判断,并进行相应的跳转
@RequestMapping("/login")
//这里的login参数名称,是从前端 login.jsp页面中找到对应位置的参数名来写的
public String login(String name, String pwd, HttpServletRequest request) {
Admin admin = adminService.login(name, pwd);
System.out.println("AdminAction中输出的admin是" + admin);
if (admin != null) {
//登录成功
request.setAttribute("admin", admin);
return "main";
}
//返回主界面
else {
request.setAttribute("errmsg", "用户名或密码不正确!");
return "login";
}
}
}
这里的request也可以考虑改为视图来做
报错
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘adminAction’: Unsatisfied dependency expressed through field ‘adminService’; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ‘BUPT.service.AdminService’ available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
解读一下就是adminService和adminAction没配好
找到问题是
web.xml中监听器的配置,我 图快直接 alt+enter
导致导包出错
错误
<listener-class>org.springframework.web.context.ContextLoader</listener-class>
</listener>
正确
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
然而我又进行了测试
登录发现报错,进不去
查看输出日志
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@4c662a59] will be managed by Spring
==> Preparing: select a_id, a_name, a_pass from admin WHERE ( a_name = ? )
==> Parameters: admin(String)
<== Total: 0
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7328a4ea]
pwd输出为000000
[]
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7328a4ea]
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7328a4ea]
AdminAction中输出的admin是null
发现数据库是连接上的
也能拿到从登录界面上的账号
也能拿到登录界面上的密码
但是查询返回结果却是一个null,也就没办法正常登录到main里面了
暂时搁置一下
直接进入main里面学后面的
问题已解决
解决思路
我首先对比了我写的代码和教程里提供的代码,发现并没有什么区别
然后测试了
example.createCriteria().andANameEqualTo(name);
example.createCriteria().andAIdEqualTo(1);
example.createCriteria().andAPassEqualTo(MD5Util.getMD5(pwd));
发现只有name的对不上,也就是说,我的SQL语句的组装是没问题的
那么我就查数据库本身的信息
我新建了一条字段,也叫admin,并把上面的admin删除
然后登录进去了
发现原来是建表的时候,我在admin前面加了一个空格,导致始终匹配不上。
结束时间:2022-03-02