# 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容器来进行具体的控制
依赖注入:
依赖:
容器

pojos:自己定义的这些类
metadata:在spring的配置文件里面写的这些就是元数据
实例化容器:classpath...将配置文件传入,实例化完毕
##### 值的注入
setter()方法注入(最常用的方法)
必须其字段有对应的setter()方法才可完成
通过property子节点完成注入
构造注入