是一款优秀的持久层框架,用于简化 JDBC的开发:持久层也就是三层架构里面的dao层,JDBC是规范;框架就是一个半成品的软件,是一套可重复用,通用的,软件基础代码模型;
硬编码:
1.注册驱动,获取链接
2.SQL语句
操作繁琐:
1.手动设置参数
将硬编码字符串写到配置文件里,对于操作繁琐的代码自动完成,即免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作
1.创建模块,导入坐标;
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <groupId>org.example</groupId>
- <artifactId>mybatis-demo</artifactId>
- <version>1.0-SNAPSHOT</version>
-
- <properties>
- <maven.compiler.source>8</maven.compiler.source>
- <maven.compiler.target>8</maven.compiler.target>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.mybatis</groupId>
- <artifactId>mybatis</artifactId>
- <version>3.5.5</version>
- </dependency>
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>5.1.46</version>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.13</version>
- <scope>test</scope>
- </dependency>
- <!-- 这里其他的日志以来会自动导入-->
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-classic</artifactId>
- <version>1.2.3</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-access</artifactId>
- <version>1.1.7</version>
- <exclusions>
- <exclusion>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- </dependencies>
- </project>
2.编写核心配置文件
- "1.0" encoding="UTF-8" ?>
- configuration
- PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
- "https://mybatis.org/dtd/mybatis-3-config.dtd">
- <configuration>
- <environments default="development">
- <environment id="development">
- <transactionManager type="JDBC"/>
- <dataSource type="POOLED">
- <property name="driver" value="com.mysql.jdbc.Driver"/>
- <property name="url" value="jdbc:mysql:///chatroomperson?useSSL=false"/>
- <property name="username" value="root"/>
- <property name="password" value="root"/>
- dataSource>
- environment>
- environments>
- <mappers>
- <mapper resource="PersonMapper.xml"/>
- mappers>
- configuration>
4.编写SQL映射文件
- "1.0" encoding="UTF-8" ?>
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="test">
- <select id="selectAll" resultType="pojo.Person">
- select * from person;
- select>
- mapper>
5.编码
{
定义POJO类
- public class Person {
- private String account;
- private String name;
- private String image;
- private String signature;
- private Date birthday;
- private String email;
- private String gender;
-
- public String getAccount() {
- return account;
- }
-
- public void setAccount(String account) {
- this.account = account;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getImage() {
- return image;
- }
-
- public void setImage(String image) {
- this.image = image;
- }
-
- public String getSignature() {
- return signature;
- }
-
- public void setSignature(String signature) {
- this.signature = signature;
- }
-
- public Date getBirthday() {
- return birthday;
- }
-
- public void setBirthday(Date birthday) {
- this.birthday = birthday;
- }
-
- public String getEmail() {
- return email;
- }
-
- public void setEmail(String email) {
- this.email = email;
- }
-
- public String getGender() {
- return gender;
- }
-
- public void setGender(String gender) {
- this.gender = gender;
- }
-
- @Override
- public String toString() {
- return "Person{" +
- "account='" + account + '\'' +
- ", name='" + name + '\'' +
- ", image='" + image + '\'' +
- ", signature='" + signature + '\'' +
- ", birthday=" + birthday +
- ", email='" + email + '\'' +
- ", gender='" + gender + '\'' +
- '}';
- }
- }
加载核心配置文件获取SqlSessionFactory对象获取该对象执行SQL语句,释放资源
- public class MybatisDemo01 {
- public static void main(String []args) throws IOException {
- //加载mybatis的核心配置文件,获取SqlSessionFactory
- //如果在resources目录下面只要写一个名就可以了
- String resource = "mybatis-config.xml";
- InputStream inputStream = Resources.getResourceAsStream(resource);
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- //获取SqlSession对象执行sql
- SqlSession sqlSession=sqlSessionFactory.openSession();
- List<Person>persons=sqlSession.selectList("test.selectAll");
- System.out.println(persons);
- //释放资源
- sqlSession.close();
-
- }
- }
}
目的:
解决原生方式中的硬编码,简化后期执行SQL
简化开发:
1.
2.
- "1.0" encoding="UTF-8" ?>
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="mapper.PersonMapper">
- <select id="selectAll" resultType="pojo.Person">
- select * from person;
- select>
- mapper>
3.
- //接口类
- public interface PersonMapper {
- List
selectAll() ; - }
-
4.
- public class MybatisDemo02 {
-
- public static void main(String []args) throws IOException {
- //加载mybatis的核心配置文件,获取SqlSessionFactory
- //如果在resources目录下面只要写一个名就可以了
- String resource = "mybatis-config.xml";
- InputStream inputStream = Resources.getResourceAsStream(resource);
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- //获取SqlSession对象执行sql
- SqlSession sqlSession=sqlSessionFactory.openSession();
- //获取UserMapper接口的代理对象
- PersonMapper personMapper=sqlSession.getMapper(PersonMapper.class);
- List<Person>persons=personMapper.selectAll();
- System.out.println(persons);
- //释放资源
- sqlSession.close();
-
- }
-
-
- }
细节:
- <mappers>
- <package name="mapper"/>
-
- mappers>
enviroments:配置数据库连接环境信息,可以配置多个environment,通过default属性切换不同的environment
typeAlias:别名可以简化配置:
- <typeAliases>
- <package name=""/>
- </typeAliases>
引号里面写要连接的接口的包,然后就可以在对应的接口包里面不要写这个包了例如:
- <typeAliases>
- <package name="pojo"/>
- </typeAliases>
然后在对应的 PersonMapper的xml文件里面可以做这样的改变:
- <select id="selectAll" resultType="pojo.Person">
- select * from person;
- </select>
变成
- <select id="selectAll" resultType="Person">
- select * from person;
- </select>
注意:配置各个标签时,需要遵守前后顺序 ;
MybatisX插件是一款基于IDEA快速开发插件,为效率而生
具体步骤如下:
06-MyBatis案例-环境准备_哔哩哔哩_bilibili
步骤:
1.编写接口方法;
2.编写SQL语句;SQL映射文件;
3.执行方法测试;
注意:如果表的类里面有和表里面的字段不一样的,那么就不会自动封装,这时候就可以将查询的字段起别名使得别名和该类属性一样;但是这样的话如果有多个片段就要多次操作,所以可以通过导入一个sql片段。变成这样:
但是还有更灵活的方法:
- <!--namespace:名称空间-->
- <mapper namespace="mapper.PersonMapper">
- <resultMap id="personResultMap" type="pojo.Person">
- <result column="name" property="nameCopy"/>
-
- </resultMap>
-
- <select id="selectAll" resultMap="personResultMap">
- select * from person;
- </select>
- </mapper>
get小知识:接口里面默认方法都是public
mybatis里面有两种参数占位符的不同书写格式:
- 1.#{}替换为?,为了防止SQL注入
- 2.${}拼接sql语句,会存在sql注入问题
- 3.使用时机:
- 参数传递用#{}
- 表名或列名不固定的情况下${}会存在SQL语句注入的问题
- 特殊字符处理:
- 1.转义字符:< 小于号
- 2.CDATA区
-
- -----------------------------------------------------------
- </select>
- <select id="selectAccount" resultMap="personResultMap">
- select * from person where account=#{account};
- </select>
- 参数类型parameterType可以省略
参数接收三种方式:
- <select id="selectByCondition" resultMap="personResultMap">
- select *
- from person
- where gender=#{gender}
- and name like #{nameCopy}
- <!-- 注意这里一定后面的要对应对象的属性名-->
- </select>
- ------------------------------------------------------------------------
- public void selectByCondition() throws IOException {
- //接收参数
- String gender="女";
- String nameCopy="小麻子";
- //处理参数
- nameCopy=nameCopy+"%";
- Map map=new HashMap();
- map.put("gender",gender);
- map.put("nameCopy",nameCopy);
- String resource = "mybatis-config.xml";
- InputStream inputStream = Resources.getResourceAsStream(resource);
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- //2.获取SqlSession对象
- SqlSession sqlSession=sqlSessionFactory.openSession();
- //3。获取Mpper接口的代理对象
- PersonMapper personMapper=sqlSession.getMapper(PersonMapper.class);
- //4.执行方法
- //List<Person>persons=personMapper.selectByCondition(gender,nameCopy);
- // List<Person>persons=personMapper.selectByCondition(person);
- List<Person>persons=personMapper.selectByCondition(map);
- System.out.println(persons);
- //5.释放对应的资源
- sqlSession.close();
- }
注意:这个#号里面的属性要对应对象类里面的属性;
步骤:
1.编写接口方法:Mapper接口
void add(Person person);
2.编写SQL语句:SQL映射文件
- <insert id="add">
- insert into person(name,account,gender)
- values(#{nameCopy},#{account},#{gender})
- </insert>
3.执行方法,测试
- @Test
- public void add() throws IOException {
- //接收参数
- String gender="女";
- String nameCopy="小麻子";
- //处理参数
- nameCopy=nameCopy+"%";
- Person p=new Person();
- p.setGender(gender);
- p.setNameCopy(nameCopy);
- p.setAccount("1111111111");
- String resource = "mybatis-config.xml";
- InputStream inputStream = Resources.getResourceAsStream(resource);
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- //2.获取SqlSession对象
- SqlSession sqlSession=sqlSessionFactory.openSession();
- //3。获取Mpper接口的代理对象
- PersonMapper personMapper=sqlSession.getMapper(PersonMapper.class);
- //4.执行方法
- //List<Person>persons=personMapper.selectByCondition(gender,nameCopy);
- // List<Person>persons=personMapper.selectByCondition(person);
- personMapper.add(p);
- //提交事务
- sqlSession.commit();
- //5.释放对应的资源
- sqlSession.close();
- }
本来代码交了之后会发现没有报错,运行成功,但是没有出现新的记录在数据库里面,这是由于mybatis默认事务提交是false,这样的话执行之后没有提交就会回滚;解决方法:(上面代码采用了第一种解决方式)
1.在释放资源之前手动提交事务;
2.在openSession的时候写入参数true;
附上:主键返回:
对于添加的信息里面没有包括主键,但是后面还要返回主键这种情况下,可以用这个:
- <insert id="add" useGeneratedKeys="true" keyProperty="account">
- insert into person(name,account,gender)
- values(#{nameCopy},#{account},#{gender})
- </insert>
这样可以做到在调用完add方法之后就可以得到主键值了,这里的account是我自己输入的,并且我这个是可以直接返回的,这只是做测试用例;
int update(Person person);
- <update id="update">
- update person
- set name=#{nameCopy},
- gender=#{gender}
- where account=#{account};
-
- </update>
- @Test
- public void update() throws IOException {
- //接收参数
- String gender="女";
- String nameCopy="小麻子+++";
- //处理参数
- nameCopy=nameCopy+"%";
- Person p=new Person();
- p.setGender(gender);
- p.setNameCopy(nameCopy);
- p.setAccount("1111111111");
- String resource = "mybatis-config.xml";
- InputStream inputStream = Resources.getResourceAsStream(resource);
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- //2.获取SqlSession对象
- SqlSession sqlSession=sqlSessionFactory.openSession();
- //3。获取Mpper接口的代理对象
- PersonMapper personMapper=sqlSession.getMapper(PersonMapper.class);
- //4.执行方法
- //List<Person>persons=personMapper.selectByCondition(gender,nameCopy);
- // List<Person>persons=personMapper.selectByCondition(person);
- System.out.println(personMapper.update(p));
- //提交事务
- sqlSession.commit();
- //5.释放对应的资源
- sqlSession.close();
- }
删除一个:
void deleteByAccount(Person person);
- <delete id="deleteByAccount">
- delete from person where account=#{account};
- </delete>
- @Test
- public void deleteByAccount() throws IOException {
- //接收参数
-
- //处理参数
- Person p=new Person();
- p.setAccount("1111111111");
- String resource = "mybatis-config.xml";
- InputStream inputStream = Resources.getResourceAsStream(resource);
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- //2.获取SqlSession对象
- SqlSession sqlSession=sqlSessionFactory.openSession();
- //3。获取Mpper接口的代理对象
- PersonMapper personMapper=sqlSession.getMapper(PersonMapper.class);
- //4.执行方法
- //List<Person>persons=personMapper.selectByCondition(gender,nameCopy);
- // List<Person>persons=personMapper.selectByCondition(person);
- personMapper.deleteByAccount(p);
- //提交事务
- sqlSession.commit();
- //5.释放对应的资源
- sqlSession.close();
- }
- </select>
- <select id="selectByCondition" resultMap="personResultMap">
- select *
- from person
- <where>
- <!-- 几点要注意:首先if里面的属性要和类对象对应,而且字符串类型要注意判断空字符串,并且用!=和不带空格的单引号-->
- <if test="gender!=null and gender!=''">
- gender=#{gender}
- </if>
- <if test="nameCopy!=null and nameCopy!=''">
- and name like #{nameCopy}
- </if>
-
- </where>
-
- <!-- 注意这里一定后面的要对应对象的属性名-->
- </select>
choose(when,otherwise)
- </select>
- <select id="selectByConditionSingle" resultMap="personResultMap">
- select *
- from person
- where
- <choose><!--相当于switch-->
- <when test="gender!=null and gender!=''">
- gender=#{gender}
- </when>
- <when test="nameCopy!=null and nameCopy!=''">
- name like #{nameCopy}
- </when>
-
- </choose>
- </select>
但是在这种情况下,当什么都没有的时候时会报错的,这时候的格式问题还是可以用where来处理;
修改字段和普通修改字段类似,也是用if标签,但是对于格式和规范化问题,这里用的不是where而是update;
批量删除参数要变成主键(一般来说)的数组
void deleteByAccounts(@Param("accounts") String []accounts);
- <delete id="deleteByAccount">
- delete from person where account=#{account};
- </delete>
- <delete id="deleteByAccounts">
- delete from person where account in(
- <foreach collection="accounts" item="account" separator=",">
- #{account}
- </foreach>
- )
- </delete>
- @Test
- public void deleteByAccounts() throws IOException {
- //接收参数
- String []accounts={"0866170880","1106231296"};
- //处理参数
- Person p=new Person();
- p.setAccount("1111111111");
- String resource = "mybatis-config.xml";
- InputStream inputStream = Resources.getResourceAsStream(resource);
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
- //2.获取SqlSession对象
- SqlSession sqlSession=sqlSessionFactory.openSession();
- //3。获取Mpper接口的代理对象
- PersonMapper personMapper=sqlSession.getMapper(PersonMapper.class);
- //4.执行方法
- //List<Person>persons=personMapper.selectByCondition(gender,nameCopy);
- // List<Person>persons=personMapper.selectByCondition(person);
- personMapper.deleteByAccounts(accounts);
- //提交事务
- sqlSession.commit();
- //5.释放对应的资源
- sqlSession.close();
- }
注意:这里由于有写可以简化的:比如在上面的xml的文件里面可以将两个括号去掉改成这样效果是一样的:
- </delete>
- <delete id="deleteByAccounts">
- delete from person where account in
- <foreach collection="accounts" item="account" separator="," open="(" close=")">
- #{account}
- </foreach>
-
- </delete>
如果之前的接口代码里面没有用注解改的话,一般时array数组,比如做这样的修改:
void deleteByAccounts(String []accounts);
- </delete>
- <delete id="deleteByAccounts">
- delete from person where account in
- <foreach collection="array" item="account" separator="," open="(" close=")">
- #{account}
- </foreach>
- </delete>
即将配置文件里面的SQL语句直接在接口类里面用注解完成:
- @Select("select * from person")
- List
selectAll();
但是这样会导致在配置文件处理的东西就会失效,所以说注解适合处理比较简单的SQL语句;
把对资源的请求拦截下来
1.定义类,实现Filter接口,并重写其所有方法
- package webtest.filter;
-
- import javax.servlet.*;
- import javax.servlet.annotation.WebFilter;
-
- import java.io.IOException;
- @WebFilter("/*")
- public class FilterDemo implements Filter {
-
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
-
- }
-
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
- System.out.println("filterDemo...");
- filterChain.doFilter(servletRequest,servletResponse);
- }
-
- @Override
- public void destroy() {
-
- }
- }
2.配置拦截资源的路径,在类定义上@WebFilter注解,这里一定要注意是@WebFilter注解,别搞错了,不然会一直拦截不了;
3.在doFilter方法中输出一句话,并放行
对于web资源和浏览器的交互,中间如果有一个过滤器的话,有这样的执行流程:
先是服务器向web资源请求数据,然后经过过滤器处理,也就是执行过滤器doFilter方法前面的代码,然后访问资源里面的数据,之后再执行过滤器后面的代码;
如果有多个过滤器,对于过滤器的执行顺序,按照类名的字符串的自然排序来进行的;
执行顺序和这样的顺序一样:
练习:
1.定义类,实现ServletContextListener接口
2.在类上添加@WebListener注解
- @WebListener
- public class LoaderListener implements ServletContextListener {
-
- @Override
- public void contextInitialized(ServletContextEvent servletContextEvent) {
- System.out.println("初始化。。。");
- }
-
- @Override
- public void contextDestroyed(ServletContextEvent servletContextEvent) {
-
- }
- }
一种权限控制的数据库表设计(...)
05_RBAC_菜单管理案例_需求介绍_数据库设计_尚学堂_哔哩哔哩_bilibili
一种维护浏览器状态的方法,服务器需要识别多次请求是否来自同一浏览器,以便在同一次会话的多次请求中共享数据(HTTP是无状态的,每次浏览器向服务器请求时,服务器都会将该请求视为新的请求,因此我们需要会话跟踪技术来实现会话内数据共享)
客户端会话跟踪技术:Cookie
服务端会话跟踪技术:Session
发送:
获取:
默认情况下,存活时间在浏览器内存中,当浏览器关闭,内存释放则销毁
Cookie不能直接存储中文:
如需储存,则进行URL编码的转码;
- HttpSession session= req.getSession();
- session.setAttribute("username","zs");
- HttpSession session=req.getSession();
- Object username=session.getAttribute("username");
- System.out.println(username);
Session是基于Cookie实现的
钝化:在服务器正常关闭后,Tomcat会自动将Session数据写入硬盘的文件中
活化:再次启动服务器后,从文件加载数据到Session中;
Session销毁:
默认情况下,无操作,30分钟自动销毁,但是可以配置:
调用Session对象的invalidate方法也可以销毁;
储存位置:Cookie是将数据存储在客户端,Session将数据存储在服务器端;
安全性:Cookie不安全,Session安全
数据大小:Cookie最大3KB,Session无大小限制
存储时间:Cookie可以长期储存,Session默认三十分钟
服务器性能:Cookie不占服务器资源,Session占用服务器资源
request获取请求对象:
response设置请求对象:
tomcat创建request对象 ,创建实现类;
请求头:
请求体:
示例代码:
- Map<String,String[]>map= req.getParameterMap();
- for(String key:map.keySet())
- {
- System.out.println(key+":");
- //获取值
- String[]values=map.get(key);
- for (String value:values)
- {
- System.out.println(value+"");
- }
-
- }
- System.out.println("------------------------------------------------------------");
- //根据key获取参数值数组,
- String[] hobbies=req.getParameterValues("hobby");
- for(String hobby:hobbies)
- {
- System.out.println(hobby);
- }
- //根据key获取参数值:
- String username=req.getParameter("username");
- System.out.println(username);
- }
post解决方式:
get解决方式:
乱码原因:
解决方法:虽然两个程序的编解码方式不同,但是底层的字节数组是一样的,可以将后面的带的乱码的数据按相应的规则解码成相应的字节数组,然后再转换成汉字字符串;
- String username=req.getParameter("username");
- System.out.println(username);
- //编码成字节数组
- byte[]bytes=username.getBytes(StandardCharsets.ISO_8859_1);
- //解码成字符串
- username=new String(bytes,StandardCharsets.UTF_8);
- System.out.println(username);
请求转发的特点:
浏览器地址栏路径不发生变化;
只能转发到当前服务器的内部资源;
一次请求,可以在转发的资源间使用request共享数据
一种资源跳转方式,
- //重定向
- //方法一:
- //设置响应状态码 302
- //resp.setStatus(302);
- //设值响应头
- //注意:这里路径要加上虚拟目录,默认虚拟目录是项目名
- //resp.setHeader("location","/web-demo/demo02");
- //方法二:
- resp.sendRedirect("/web-demo/demo02");
重定向特点:
浏览器地址栏路径发生变化
可以重定向道任意位置的资源(服务器内部,外部均可)
两次请求,不能再多个资源使用request共享数据
浏览器使用:需要加虚拟目录(项目访问路径)
服务端使用:不需要加虚拟目录
虚拟目录可以动态配置:
所以可以动态获取虚拟目录:getContextPath方法
响应字符数据:
- resp.setContentType("text/html;charset=utf-8");
- //1.获取字符输出流
- PrintWriter writer= resp.getWriter();
- writer.write("你好");
- writer.write("
你好
");
响应字节数据:
- //读取文件
- FileInputStream fileInputStream=new FileInputStream("D://a.jpg");
- // 获取response字节输出流
- ServletOutputStream os=resp.getOutputStream();
-
- //完成流的copy
- // byte[]buff=new byte[1024];
- // int len=0;
- // while((len=fileInputStream.read(buff))!=-1)
- // {
- // os.write(buff,0,len);
- // }
- //
- // fileInputStream.close();
- IOUtils.copy(fileInputStream,os);
点击Settings,Editor中的File and Code Templates,选择Other选框:Web里面Java Code Templates里面的Servlet Annotated Class;
分层开发的模式
好处:
职责单一,互不影响;
有利于分工协作:
有利于组件重用:
mvc和三层架构关系:
假期结束了,又要好好学习了。。。、
任何事情在尘埃落定之前都是未知的 付出不一定跟收获成正比 但尽全力去做是绝对不会错的 哪怕做不好也没关系 就是不要在开始之前就说我不行 这很重要。