# SSM **Repository Path**: xuzhi7162/SSM ## Basic Information - **Project Name**: SSM - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2019-01-03 - **Last Updated**: 2021-05-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # SSM框架学习 ##--个人网站后台开发 ##### 软件架构: 基于流行SSM框架:Spring+SpringMVC+Mybatis WEB页面设计:Bootstrap 项目配置: 使用Maven进行项目jar导入 ​ 使用Git进行版本控制,并将每次编写的代码上传到Gitee进行保存 ##### 环境需求: ​ Eclipse(装有Web相关插件以及Maven插件和Git插件) ​ Navcat(mysql 5.7 图形化管理工具) ​ JDK 1.8 ##### 环境配置 ​ Eclipse中的Maven配置,Git配置,请自行查阅,网上有相关资源 ##### 参考网站: Maven Repository : https://mvnrepository.com/ Gitee:https://gitee.com/ Gitee 项目仓库:https://gitee.com/xuzhi7162/SSM GitHub项目仓库:https://github.com/xuzhi7162/SSM/tree/master/NewProject/JavaWebTest (使用IntelliJ IDEA尝试开发) Mybatis教程:https://blog.csdn.net/hellozpc/article/details/80878563#3Mybaits_109 ## Mybatis #### 日志工具 ##引入相关依赖 ```xml log4j log4j 1.2.17 ``` ##在全局配置文件中添加相应的setting设置 ```xml ``` ##在resources目录下建立log4j.properties配置文件,并在内部做出相应修改 ```properties # Global logging configuration log4j.rootLogger=ERROR, stdout # MyBatis logging configuration... log4j.logger.com.xuzhi.mapper=DEBUG # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n ``` ###修改内容如下 官方语句为 ```properties log4j.logger.org.mybatis.example.BlogMapper.selectBlog=TRACE ``` 修改为 ```properties log4j.logger.com.xuzhi.mapper=DEBUG ``` 即将原先的org.mybatis.example.BlogMapper.selectBlog修改为你mapper所在的包,并将后面的TRACE修改为DEBUG以便于在控制台打印 #### mybatis-config.xml ##Mybatis的全局配置文件 ```xml ``` ##两种mapper引入方法:直接引入配置文件,引入实体类所在的包 #### UserInfoMapper.xml ##UserInfoMapper实体类的配置文件,该配置文件必须在全局配置文件**mybatis.cfg,xml**中注册 ```xml insert into user_info(user_name,user_pass,user_phone) values(#{userName},# {userPass},#{userPhone}) ``` ##对相应数据表的GRUD操作的语句都写于该配置文件中, **#{}和${}** #{} 只是替换?,相当于PreparedStatement使用占位符去替换参数,可以防止sql注入。 ${} 是进行字符串拼接,相当于sql语句中的Statement,使用字符串去拼接sql;$可以是sql中的任一部分传入到Statement中,不能防止sql注入。 注:所谓SQL注入,就是通过把SQL命令插入到Web[表单](https://baike.baidu.com/item/%E8%A1%A8%E5%8D%95/5380322)提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。 #### MybatisUtil.java工具类 ##用与返回SqlSession ```java package com.xuzhi.util; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; /** * 单例类,在程序中仅有一个类 * @author 绪志 * */ public class MybatisUtil { private static SqlSessionFactory sqlSessionFactory; /** * 静态代码块,在程序的所有运行过程中,该代码块仅执行一次,类似于单例 */ static { //指定全局配置文件 String resource="mybatis.cfg.xml"; InputStream in=null; try { //读取配置文件 in = Resources.getResourceAsStream(resource); //构建SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); } catch (IOException e) { e.printStackTrace(); }finally { if(in != null){ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static SqlSession getSession(){ //返回SqlSession return sqlSessionFactory.openSession(); } } ``` #### UserInfoMapper.java ```java package com.xuzhi.mapper; import com.xuzhi.po.UserInfo; /** * 该接口中主要是对UserInfo实体类的GRUD操作,不需要实现该接口,仅需要在UserInfoMapper.xml中添加相应的sql语句既可 * @author 绪志 * */ public interface UserInfoMapper { int insert(UserInfo userInfo); } ``` #### SQL语句 ##### select复合查询语句 ##推荐使用注解方法 **@Param()** ```java /** * 通过name和flower进行复合查询,通过注解可以在mapper的配置文件中直接使用#{name}和#{flower}来接收参数 * 否则必须使用mybatis默认的参数接收方式,param1,param2或者arg0,arg1 * 推荐使用注解的方式来进行传递参数 * @param name * @param flower * @return */ Girl queryByNameFlower(@Param("name") String name,@Param("flower") String flower); ``` ##通过就Javabean进行参数传递 ```java /** * 通过javabean来传递参数 * mapper.xml中调用参数时只需要使用实体类中的属性名即可 * @param girl * @return */ Girl queryByNameFlower1(Girl girl); ``` ###在传入多个javabean时,在接收参数时可以使用param1.XXX,此方法是不友好的,可以在定义方法时使用@Param注解, 例:@Param(“a”) Girl girl==========使用时可以使用"a.XXX" ##通过hashmap进行参数传递(在mapper中按照键的名称取值) ```java /** * 通过hashmap传参 * @return */ Girl queryByNameFlower2(Map map); ``` #### 动态SQL ##本部分没有做测试类,完全摘自Mybatis官方文档 - if - choose (when, otherwise) - trim (where, set) - foreach - bind - sql ​ ##### if 动态 SQL 通常要做的事情是根据条件包含 where 子句的一部分。比如: ```xml ``` ##在使用where条件是可以使用专门的标签,从而使mybatis自动处理查询条件前面的‘and’关键字,推荐在所有的if语句中所有的查询关键字前面都加上and关键字,即使是第一个在其内容中也要加入and关键字,因为mybatis会帮我们处理好这个and关键字,例如 ```xml AND state = #{state} ``` ##### choose, when, otherwise ##有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。 ```xml ``` ##### trim, where, set 标签代码同标签内的代码 标签可以看成为的自定义标签,可以通过内部的某些属性来处理AND/OR,还可以处理“,” ```xml ... ``` ###官方文档没有完全给出标签内的所有属性,具体使用时需要具体百度 标签可以处理标签中多余的“,”,例如update中的set后项目的“,” ```xml update Author username=#{username}, password=#{password}, email=#{email}, bio=#{bio}, where id=#{id} ``` ###同标签处理AND/OR一样,可以在每个语句的后面都填上“,”,标签都可以帮我们处理掉 ##### foreach ```xml ``` ​ · item:自命名,用来表示需要遍历的集合的其中的一个子项 ​ ·index:当前遍历到的下标 ​ ·collection:需要遍历的类型 #list、set、map ​ ·open:以什么为开始 ​ ·separator:每个子项之间用什么符号分隔开 ​ ·close:以什么为结尾 上述代码可“编译出”, ```sql select * from post p where ID in (a,b,c,d) ``` [^]: 仅作为参考,实际编译出的并不为此 ##### bind ###`bind` 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如: ```xml ``` [^注]: 多用于模糊查询 ##### sql 这个元素可以被用来定义可重用的 SQL 代码段,可以包含在其他语句中。它可以被静态地(在加载参数) 参数化. 不同的属性值通过包含的实例变化. 比如: ```xml ${alias}.id,${alias}.username,${alias}.password ``` 这个 SQL 片段可以被包含在其他语句中,例如: ```xml ``` #### Mybatis关系映射 ##使用mybatis处理一般的单表时常使用resultType属性,但是用mybatis处理多表查询时,使用resultType进行结果集的封装不太适用,所以此时要使用自定义封装结果集,多使用resultMap进行自定义结果集的封装 ##### **一对一关系映射** ##简要说明,一对一举例,一个用户拥有自己独特的个人信息,一个用户对应一个用户详情信息 <方法一:使用assocation进行具体对象的封装> ```xml ``` ##对于javabean的封装多使用oop思想 **Girl.java** ```java package com.xuzhi.model; import java.io.Serializable; import java.util.Date; public class Girl implements Serializable { private long id; private String name; private String flower; private Date birthday; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getFlower() { return flower; } public void setFlower(String flower) { this.flower = flower; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public Girl(String name, String flower){ this.name=name; this.flower=flower; } public Girl(){ } @Override public String toString() { return "Girl{" + "id=" + id + ", name='" + name + '\'' + ", flower='" + flower + '\'' + ", birthday=" + birthday + '}'; } } ``` **GirlWithDetail.java** ```java package com.xuzhi.model; import java.io.Serializable; public class GirlWithDetail implements Serializable { private Integer gid; private String address; private Girl girl; public Integer getGid() { return gid; } public void setGid(Integer gid) { this.gid = gid; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Girl getGirl() { return girl; } public void setGirl(Girl girl) { this.girl = girl; } @Override public String toString() { return "GirlWithDetail{" + "gid=" + gid + ", address='" + address + '\'' + '}'; } } ``` **GirlDetail.java** ```java package com.xuzhi.model; import java.io.Serializable; public class GirlDetail extends Girl{ private GirlWithDetail girlWithDetail; public GirlWithDetail getGirlWithDetail() { return girlWithDetail; } public void setGirlWithDetail(GirlWithDetail girlWithDetail) { this.girlWithDetail = girlWithDetail; } @Override public String toString() { return "Girl{" + "id=" + getId() + ", name='" + getName() + '\'' + ", flower='" + getFlower() + '\'' + ", birthday=" + getBirthday() + '}'+ "GirlDetail{" + "girlWithDetail=" + girlWithDetail + '}'; } } ``` ##### 一对多关系映射 ##一对多关系映射举例:一个用户可以写多篇博客 ##废话不多说,几段代码可以说明一切 **GirlWithBlogMapper.xml** ```xml ``` **Blog.java** ```java package com.xuzhi.model; import java.util.List; public class Blog { private Integer id; private String title; private String summary; private String content; private Girl girl; private List comments; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getSummary() { return summary; } public void setSummary(String summary) { this.summary = summary; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Girl getGirl() { return girl; } public void setGirl(Girl girl) { this.girl = girl; } public List getComments() { return comments; } public void setComments(List comments) { this.comments = comments; } @Override public String toString() { return "Blog{" + "id=" + id + ", title='" + title + '\'' + ", summary='" + summary + '\'' + ", content='" + content + '\'' + ", girl=" + girl + ", comments=" + comments + '}'; } } ``` **Comment.java** ```java package com.xuzhi.model; public class Comment { private Integer id; private String content; private Blog blog; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Blog getBlog() { return blog; } public void setBlog(Blog blog) { this.blog = blog; } @Override public String toString() { return "Comment{" + "id=" + id + ", content='" + content + '\'' + '}'; } } ``` **GirlBlog.java** ```java package com.xuzhi.model; import java.util.List; public class GirlBlog extends Girl { private List blog; public List getBlog() { return blog; } public void setBlog(List blog) { this.blog = blog; } @Override public String toString() { return "Girl{" + "id=" + getId() + ", name='" + getName() + '\'' + ", flower='" + getFlower() + '\'' + ", birthday=" + getBirthday() + '}'+ "GirlBlog{" + "blog=" + blog + '}'; } } ``` ###简要说明: ​ 在该例中,一个Girl用户可以拥有多个Blog,一个Blog又可以拥有多个Comment,这就构成了简单的一对多关系,其中还是使用了oop思想,最终想要封装的结果集类型是GirlBlog类型,在该类型包含了用户的部分个人信息,还包括了该用户的Blog,在每个Blog中有包含了该Blog所拥有的Comment,在Blog和GirlBlog中分别使用了List和List来反应一对多关系 ### Spring #### 基础技术 - java - 反射 - xml - xml解析 - 代理 - 大量设计模式 #### 环境搭建 ​ 1、添加spring依赖 ​ 2、编写一个spring的配置文件 ​ 3、通过spring的应用程序上下文对象获取对象 ##### 环境配置测试 **spring全局配置文件** ```xml ``` **bean类** ###**Girl.java** ```java package com.xuzhi.pojo; public class Girl { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Girl{" + "name='" + name + '\'' + ", age=" + age + '}'; } } ``` ###测试类-->**SpringTest.java** ```java package com.xuzhi.spring; import com.xuzhi.pojo.Girl; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringTest { @Test public void test1(){ // 1、获取上下文对象,spring里面声明对象都需要通过上下文来获取 //在引入配置文件的时候,可以同时引入多个配置文件,在ClassPathXmlApplicationContext中使用String数组作为参数 /* 例:ApplicationContext ctx= new ClassPathXmlApplicationContext(new String[]{"xxx1.xml","xxx2.xml"}); */ ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); // 2、通过这个对象来获取girl Girl girl= (Girl) ctx.getBean("girl"); //因为后面指定了class,所以不需要进行强制类型转换(个人感觉这种方式比较好) //Girl girl =ctx.getBean("girl",Girl.class); System.out.println(girl); } } ``` ##### 普通代码编写与spring方式编写的 ​ 普通的获取对象的方式,所有的对象之间的依赖,类之间的依赖关系都是在java代码里面维护的,很难维护的,如果说我们有替换方案,替换比较困难 ​ 对象的产生全部是在配置里面完成的,其实我们想分析关系,直接在配置文件里面就看出来了。 ##### 核心内容学习 - IOC - AOP​ **IOC概念(依赖注入):** ​ 控制反转(inverse of contril ):什么控制,谁反转了谁 ​ 控制:创建对象,彼此关系的权利 ​ 普通方式:控制权是在开发人员在程序代码当中进行掌控,new ​ spring方式:夺取控制权,反转给spring的容器 ​ **反转过程:** ​ 声明要什么 ​ spring容器来进行具体的控制 ​ 依赖注入: ​ 依赖: ​ 容器 ​ ![容器魔术](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/images/container-magic.png) ​ pojos:自己定义的这些类 ​ metadata:在spring的配置文件里面写的这些就是元数据 ​ 实例化容器:classpath...将配置文件传入,实例化完毕 ##### 值的注入 ​ setter()方法注入(最常用的方法) ​ 必须其字段有对应的setter()方法才可完成 ​ 通过property子节点完成注入 ​ 构造注入 ​