Spring+SpringMVC+Mybatis+SSM总结

Day37-Mybatis

1.概念

1.1 理解

​ 在JDBC增删改查的代码中,实质性是SQL语句不同导致方法不同,然而在我们代码中,每一次都一次都需要自己写SQL语句,前期的学习简单好写,但是在任务逻辑复杂的情况下就很难受,容易出错。所以这时候大佬就出来想法子了,写了个Mybatis框架,从底层自己生成sql语句实现增删改查。取代了JDBC的增删改查步骤。所以说Mybatis就是进化版的JDBC。

1.2 框架

​ 框架其实就是大佬们把写好的东西打包成jar包,程序员组合起来使用多了,然后约定俗成的称为框架。直白点框架就是解决问题的一些捷径,在底层写好了一部分代码,我们直接借来使用达到简化代码和提高效率的功能。

1.3 ORM

​ 全名:Object Relational Mapping,对象关系映射。是对象与数据库之间建立连接的一种技术。

​ 两种实现连接方式:

​ ① 半映射,即近日的Mybatis入门案例。自己写SQL语句去连接对象和数据库,几乎不用这种。

② 全映射,即今日的Mybatis进阶案例展示,直接用实体对象与数据库建立连接,由框架自己生成SQL语句。

1.4 数据库持久化

​ 数据库持久化就是讲代码生成的数据写进硬盘或者磁盘中永久保存,直观体现就是我们在java中写代码,可以保存在数据库中。

1.5 Mybatis的优点

​ 1.SQL语句与JAVA代码分离,出错了好检查,好修改。

​ 2.与JDBC相比,代码量更少,少死几个脑细胞,也提高了工作的效率。

2.Mybatis入门

2.1 jar包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hcipSLal-1596205009392)(C:\Users\吴永鑫\AppData\Roaming\Typora\typora-user-images\image-20200724121255089.png)]

2.2 资源目录

​ 创建一个与src平级的resources文件夹,在里面写数据库连接properties池db.和configuration.xml.以及XxxMapper.xml文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L8TI2vvu-1596205009395)(C:\Users\吴永鑫\AppData\Roaming\Typora\typora-user-images\image-20200724185334343.png)]

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!-- 非常重要!!! 与配置文件取得关联  -->
    <properties resource="db.properties"/>
    <!-- 配置环境 default默认运行哪个environment-->
	<environments default="development">
		<!-- 给每一个环境配置一个id 方便上级环境识别 -->
		<environment id="development">
			<!-- 事务管理的模式:JDBC -->
			<transactionManager type="JDBC" />
			<!-- 连接池 用EL表达式取得db.properties里面的连接池数据 -->
			<dataSource type="POOLED">
				<property name="driver" value="${driver}" />
				<property name="url" value="${url}" />
				<property name="username" value="${username}" />
				<property name="password" value="${password}" />
			</dataSource>
		</environment>
	</environments>
    <!-- mapp标签:连接读取指定xml文件 -->
	<mappers>
		<mapper resource="ProductMapper.xml" />
	</mappers>
</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- mapper 根标签
     namespace: 命名空间: 包路劲
     parameterType:方法传入参数的类型
     resultType:返回值类型
     #{id}  ?符号   待会传入的值      填充位置,传入的是一个普通值#{id}中id 写什么名字都可以
            对象:对象中的字段值,取出来填充Product   #{id}  #{productName}
 -->
<mapper namespace="cn.itsource.dao">
	<select id="loadOne" parameterType="long" resultType="cn.itsource.domain.Product">
		select * from product where id = #{id}
	</select>
</mapper> 

2.3 创建MVC结构

​ 实体类:撰写一个表,然后创建一个与之对应的实体类;

​ dao层:正常的方法接口;

​ 实现层:

@Override
	public Product loadOne(Long id) {
		//
		String resouce = "configuration.xml";
		Reader reader;
		SqlSession session = null;
		try {
			//读取配置文件
			reader = Resources.getResourceAsReader(resouce);
			//创建工厂对象
			SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
			session = factory.openSession();
			//获取session对象中namespace=cn.itsource.dao bean属性=laodOne的方法,然后传入所需要的ID
			Product pd = session.selectOne("cn.itsource.dao.loadOne", id);
			//返回对象
			return pd;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//关流
			if (session!=null) {
				session.close();
			}
		}
		return null;
	}

2.4 抽取工具类

增删改查的方法中每一次都需要或许session对象,代码重复。抽取出来创建一个工具类,获取一个session对象。
public class MyBatisUtil {
	//静态代码块,只需要创建一个对象,连接一次连接池,所以用静态代码块运行
	static SqlSessionFactory factory;
	static{
		String resouce = "configuration.xml";
		Reader reader;
		SqlSession session = null;
		try {
			//读取配置文件
			reader = Resources.getResourceAsReader(resouce);
			//创建工厂对象
			factory = new SqlSessionFactoryBuilder().build(reader);
		}catch (Exception e) {
				e.printStackTrace();
			}
	}
	public static SqlSession getSqlSession(){
		return factory.openSession();
	}
}

3.MyBatis进阶–映射器Mapper

3.1 直接使用底层的增删改查方法

​ 入门阶段我们了解了Mybatis的主要功能,代替JDBC简化代码。现在在进一步,在Mybatis底层中有它的增删改查的方法,我们可以直接提取出来使用。

​ ① 重新写一个XxxMapper接口(和XxxDao层一样),不再需要写实现类,我们需要将接口的方法名取得和XxxMapper.xml里面的方法id属性值取得一样。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Os1Qmvq1-1596205009397)(C:\Users\吴永鑫\AppData\Roaming\Typora\typora-user-images\image-20200724195221875.png)]测试类中,我们不再是用session对象获取方法,我们是获取的session的mapper属性创建mapper对象,调用里面的增删改查。

	@Test
	public void testLoadOne() throws Exception {
		//先获取session对象。独立写出来方便后面提交事务和关流
		SqlSession session = MyBatisUtil.getSqlSession();
		//获取IProductMapper接口类的mapper对象
		IProductMapper mapper = session.getMapper(IProductMapper.class);
		//调用loadOne方法并传入参数
		Product one = mapper.loadOne(2L);
		//具有事务性,需要提交事务
		session.commit();
		//关流
		if (session!=null) {
			session.close();
		}
		System.out.println(one);
	}

注意点:

​ ① 获取mapper对象的时候,不是与实体类产生关联,是与mapper接口产生关联,这样才能调用里面的增删改查方法。

​ ② Mybatis本质上还是JDBC,是流的形式,需要我们关流。

​ ③ 操作完后需要提交事务,不提交事务的话,数据是没办法走完一个流程,是不会刻写在硬盘中的(即模板已经写好,但是没有流进数据库)。

3.2 简化XxxMapper.xml

​ 在XxxMapper.xml中,我们实体类的路径重复了N次,看着有些冗余,可以把实体类的包路径直接写进configuration.xml里面,在XxxMapper.xml里面就自动进去的实体类的包里面找对应实体类。

<configuration>
	<!-- 非常重要!!! 与配置文件取得关联  -->
    <properties resource="db.properties"/>
    <typeAliases>
		<!-- 包的配置:项目中使用,添加了包之后,类名或类名首字母小写就是别名 -->
		<package name="cn.itsource.domain" />
	</typeAliases>

注意点:configuration里面设置了书写的顺序。(properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9rAqNGSX-1596205009400)(C:\Users\吴永鑫\AppData\Roaming\Typora\typora-user-images\image-20200724182632370.png)]

<mapper namespace="cn.itsource.mapper.IProductMapper">
	<!-- 设置了typeAliases后会直接去包里面找product类 -->
	<select id="loadOne" parameterType="long" resultType="product">
		select * from product where id = #{id}
	</select>

4.查看log4j日志

4.1 jar包

​ log4j-1.2.17.jar

​ slf4j-api-1.7.2.jar

​ slf4j-log4j12-1.7.2.jar

4.2 配置文件

​ 在resources文件夹中创建一个**log4j.properties(名字必须是这个)**文件,导入下面文件,测试代码的时候,就可以看到日志,进行到哪一步,使用了什么sql语句等等都可以看到。

#5.控制台输出+自定义布局
log4j.rootLogger=DEBUG,my
#指定输出器
log4j.appender.my=org.apache.log4j.ConsoleAppender
#指定布局器(自定义布局)
#指定布局为自定义布局
log4j.appender.my.layout=org.apache.log4j.PatternLayout
#指定在自定义布局的格式,%d -- 表示当前系统时间,%t -- 执行该业务的线程名称,%p -- 日记器的级别,-5 -- 5表示输出字符的个数,符号表示右对齐
#%c -- 表示指定业务所在的类的完全限定名(包名.类名),%m -- 输出额外信息,%n -- 表示换行
log4j.appender.my.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
#设置package(可以是自定义的包也可以是api的包)输出级别
log4j.logger.org.springframework=info
log4j.logger.cn.itsource=debug

5.$与#区别

5.1 通过底层分析

​ 当使用#{id}时:拼接字符串,使用的ParperStatment类型

DEBUG [cn.itsource.mapper.IProductMapper.loadOne] - ==>  Preparing: select * from product where id = ?
DEBUG [cn.itsource.mapper.IProductMapper.loadOne] - ==> Parameters: 2(Long)

​ 当使用 v a l u e {value}时:不能用 {id},取不到值;直接注入,使用的Statment类型。

DEBUG [cn.itsource.mapper.IProductMapper.loadOne] - ==>  Preparing: select * from product where id = 2
[cn.itsource.mapper.IProductMapper.loadOne] - ==> Parameters:

5.2 使用场景(面试题)

​ 通过底层分析我们很明显的了解,Statment类型的注入是几乎被弃用的,有线程安全问题。只有一个情形下要使用这个,就是SQL语句有需要SQL拼接的时候。

Day37-Spring

1.Spring入门

1.1 JAR包

​ spring是一个最基本的但是非常重要的一个轻量级框架,很多框架都是需要基于spring的。

com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
com.springsource.org.apache.commons.logging-1.1.1.jar
com.springsource.org.apache.commons.pool-1.3.0.jar
jsp-api.jar
jstl.jar
mysql-connector-java-5.1.26-bin.jar
servlet-api.jar
spring-aop-4.1.2.RELEASE.jar
spring-beans-4.1.2.RELEASE.jar
spring-context-4.1.2.RELEASE.jar
spring-core-4.1.2.RELEASE.jar
spring-expression-4.1.2.RELEASE.jar
spring-jdbc-4.1.2.RELEASE.jar
spring-test-4.1.2.RELEASE.jar
spring-tx-4.1.2.RELEASE.jar
spring-web-4.1.2.RELEASE.jar
spring-webmvc-4.1.2.RELEASE.jar
standard.jar

1.2 spring优点

​ 1.在之前的代码中,我们需要每次创建对象基本都是new 出来,spring就是可以将对象打包成一个工厂,我们将我们所需要的对象类交给他管理,在工厂中提取对象,简单方便,降低代码的耦合度。

​ 2.spring将Junit4测试包含其中,测试代码方遍。

​ 3.spring 的依赖注入功能。

​ 4.spring是以后组合框架的基础,基本都是基于spring的框架组合。

2.Spring功能

2.1 spring的配置文件

​ 1.导入jar包

​ 2.创建一个动态web项目

​ 3.创建一个resources文件夹,在里面创建applicationContext.xml文件 ,这就是spring的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
	
</beans>

2.2 管理类

​ 在applicationContext.xml文件中,配置bean标签

	<!-- bean标签, id就是spring识别这个标签属性名, class就是类的完全限定路径 -->
	<bean id="mybean" class="cn.itsource._01bean.MyBean"></bean>

2.3 获取factory的两种方式

2.3.1 BeanFactory

	@Test
	public void testBeanFactory() throws Exception {
		//拿到applicationContext.xml文件
		ClassPathResource resource = new ClassPathResource("applicationContext.xml");
		//拿到工厂对象
		XmlBeanFactory factory = new XmlBeanFactory(resource);
		
		//用工厂的getbean属性拿到对象
//		MyBean bean = factory.getBean("mybean", MyBean.class);
//		System.out.println(bean);
	}

2.3.2 ClassPathXmlApplicationContext

	@Test
	public void testClassPathXmlApplicationContext() throws Exception {
		String conf = "applicationContext.xml";
		ApplicationContext factory = new ClassPathXmlApplicationContext(conf);
		
//		MyBean bean = factory.getBean("mybean", MyBean.class);
        //date有两种导入包,一定要和class后面的那个对应,否者爷查不出来
//		Date date = factory.getBean("date", Date.class);
//		
//		System.out.println(bean);
//		System.out.println(date);
	}

2.3.3 两种方式比较(面试题)

两种拿到对象的方式特点(面试题):
通过在MyBean类中构造一个无参构造,然后两种方式都只创建factory对象而不去拿对象,运行发现
BeanFactory方式:不会运行构造方法,懒加载,只有创建对象的时候才会去运行构造方法
ClassPathXmlApplicationContext方式:迫切加载,只要创建了factory对象,就会去加载所有的bean的对象,会直接运行构造方法
当迫切加载碰到多例模式,也不会直接加载对象。

2.4 依赖注入

​ 依赖注入:就是在配置文件中给对象赋值

<!-- 依赖注入:用property标签给dibean里面的的属性赋值
				name=属性名	
				属性值是某个被spring的类时,ref=标签id,不是spring管理的时候,ref=类的全限定
				普通属性可以直接通过value赋值
				 -->
	<bean id="dibean" class="cn.itsource._02di.DiBean">
		<property name="mbBean" ref="mybean"></property>
		<property name="name" value="黑山"></property>
	</bean>

2.5 测试spring

两个注解:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")

2.6 spring细节

2.6.1 生命周期,懒加载,作用域

​ 对象创建—初始化–调用服务方法----销毁

	<!-- 
			init-method="init:配置初始化方法,创建对象后一定先执行初始化方法
			destroy-method="distory":配置销毁方法,执行完一个流程后一定会执行销毁方法
			lazy-init="true":配置加载属性 true代表懒加载,false代表迫切加载
			scope="prototype":表示加载模式- 	prototype代表多例
											singleton-代表单例加载
		 -->
		<bean id="scope" class="cn.itsource.scope.Scope" init-method="init" destroy-method="distory" lazy-init="true" scope="prototype">
			
		</bean>

3.spring和tomcat合并启动

​ 1 撰写一个dao层和是实现类,将实现类交给spring管理,直接直接用测试类测试对象。

​ 2 撰写一个service层以及实现类,同时交给spring管理,在service层中私有化daoimpl的对象,所以在applicationContext.xml中都需要将dao层丢给service层中,同时由于spring是通过setting方法给对象赋值的,所以需要在service层建立一个setting方法。

public class UserServiceImpl implements IUserService{
	private UserDaoImpl udi;	
	public void setUdi(UserDaoImpl udi) {
		this.udi = udi;
	}
	@Override
	public MyBean getMyBean() {
		MyBean myBean = udi.get();
		return myBean;
	}
}
	<bean id="service" class="cn.itsource.service.impl.UserServiceImpl">
		<property name="udi" ref="dao"></property>
	</bean>

​ 3 撰写Controller层次,目前还在使用servlet编写controller,这里涉及了一个问题,servlet是tomcat管理的,而dao和service是spring管理,两个独立的服务,怎么搞-------------启动tomcat的时候将spring也开启。

​ 4 tomcat是由web.xml管理的,我们在web.xml中设置监听器和加载spring的配置文件

	<!-- 监听器 
			作用:当检查到servlet启动的时候,自动启动spring容器-->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- 加载sprin的 配置文件 
		ServletContext  application 加载sprin的 配置文件
		contextConfigLocation  : 名字不能改监听程序,通过这个名字获取参数
		classpath:applicationContext.xml  : 编译路劲取获取配置文件-->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>

​ 5 tomcat启动有一个初始化的方法,将加载spring容器的方法放进tomcat初始化方法中

@WebServlet("/user")
public class UserServlet extends HttpServlet {
	private UserServiceImpl usi;
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		MyBean bean = usi.getMyBean();
		System.out.println(bean);
	}
	
	@Override
	public void init(){
		System.out.println("init------------------------");
		//获取上下文对象
		ServletContext sc = this.getServletContext();
		//Spring容器对象
		WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(sc);
		usi = context.getBean("service", UserServiceImpl.class);
	}
}

Day39-springMVC

1.springMVC理解

​ springMVC就是一个基于spring的框架,其实就是将spring的web-Controller层改良为了MVC层结构。

2.springMVC配置

2.1 jar包

Spring和springMVC以及JDBC汇总jar包
com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
com.springsource.org.apache.commons.logging-1.1.1.jar
com.springsource.org.apache.commons.pool-1.3.0.jar
jsp-api.jar
jstl.jar
mysql-connector-java-5.1.26-bin.jar
servlet-api.jar
spring-aop-4.1.2.RELEASE.jar
spring-beans-4.1.2.RELEASE.jar
spring-context-4.1.2.RELEASE.jar
spring-core-4.1.2.RELEASE.jar
spring-expression-4.1.2.RELEASE.jar
spring-jdbc-4.1.2.RELEASE.jar
spring-test-4.1.2.RELEASE.jar
spring-tx-4.1.2.RELEASE.jar
spring-web-4.1.2.RELEASE.jar
spring-webmvc-4.1.2.RELEASE.jar
standard.jar

2.2 配置文件

​ 在resources文件夹创建spring-mvc.xml文件,基本配置和spring的初始xml配置文件一样。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.1.xsd">
       <!-- 
			没有/  只是一个普通的Bean
             有/   /my---class对应类的映射路径
        -->
	  	<bean id="/my" class="cn.itsource._01Controller.MyContrller"
	   <!-- 静态资源放行 = 静态资源可以不拦截 -->
	   <mvc:default-servlet-handler/>
	   <!-- 扫描包
	        检查类是否有@Controller注解:  根据这个注解类交给Spring管理了,并且Spring会为你创建对象
	    -->
	   <context:component-scan base-package="cn.itsource"></context:component-scan>
	   <!-- 开启Spring对Mvc的支持 = 能够使用@Requestmapping注解 -->
	   <mvc:annotation-driven/>
</beans>

同时,spring-mvc需要交给tomcat管理,所以需要去web.xml中配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">

	<servlet>
		<servlet-name>DispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<!-- 参数名字不能随便取[DispatcherServlet 参数而已] -->
			<param-name>contextConfigLocation</param-name>
			<--配置spring-mvc.xml的读取路径-->
            <param-value>classpath:spring-mvc.xml</param-value>
		</init-param>
		<!-- 启动tomcat的时候创建servlet 放在后面Servelt准备好,参数准备好,再创建 -->
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>DispatcherServlet</servlet-name>
        <!-- 匹配所有的页面 -->
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<!-- 自定义过滤器配置 没特殊需求不用自己配置,内置文件有 -->
	<!-- <filter> 
			<filter-name>myfilter</filter-name> 
			<filter-class>cn.itsource._05Filter.EncodingFilter</filter-class> 
			<init-param> 
				<param-name>encoding</param-name> 
				<param-value>utf-8</param-value> 
			</init-param> 
		</filter> 
		<filter-mapping>
        	<filter-name>myfilter</filter-name> 
			<--匹配所有的路劲:根据路劲决定拦截那些资源 -->
			<url-pattern>/*</url-pattern> 
		</filter-mapping> -->
	
	<!-- SpringMVCy已经写好的过滤器,我们直接配置使用就可以了 -->
	<filter>
		<filter-name>characterEncoding</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>characterEncoding</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

2.3 业务处理器的三种方式

​ 1.实现Controller接口

public class MyController implements Controller{
	@Override
	public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
		System.out.println("愿你在冬天不缺暖阳");
		return null;
	}
}

​ 2.实现HttpRequestHandler接口

public class YouController implements HttpRequestHandler {

	@Override
	public void handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
		System.out.println("小老弟,你不行啊");
	}

}

​ 3.添加注解------基本都是用这种,简单方便,代码简洁,需要在spring-mvc.xml中开启注解和扫描包

@Controller  /*告诉Spring创建一个该类的对象*/
@RequestMapping("/user")
public class HeiController {
	
	@RequestMapping("/add")//配置访问路径,这个类映射地址是/user/add
	public void add(){
		System.out.println("普通类:add");
	}
	@RequestMapping("/update")
	public void update(){
		System.out.println("普通类:update");
	}
}

2.4 全注解

​ 第一步在spring-xml中配置注解+开启扫描包路径,扫描包路径后,包里面的所有子包以及所有类都被放进了spring的容器内打理了,通过不同类型的注解实现不同的功能

@Controller-------表示控制层

@Service-----------表示服务层

@Repository-----表示实现层

@Component—普通类的注解

 		<!-- 扫描包
	        检查类是否有@Controller注解:  根据这个注解类交给Spring管理了,并且Spring会为你创建对象
	    -->
	   <context:component-scan base-package="cn.itsource"></context:component-scan>
	   <!-- 开启Spring对Mvc的支持 = 能够使用@Requestmapping注解 -->
	   <mvc:annotation-driven/>

3.控制层传接参数

3.1 接收参数

​ 1.repuest请求接收参数

	@RequestMapping("/form1")
	public void from1(HttpServletRequest req){
		String name = req.getParameter("name");
		String password = req.getParameter("pwd");
		System.out.println(name+"+++++++"+password);
	}

​ 2.直接用字段传值

	@RequestMapping("/form2")
	public void from2(String name,String password){
		System.out.println("name:"+name+"----------pwd:"+password);
	}

​ 3.创建一个实体类,字段对应表单的属性,创建对象传值

	@RequestMapping("/form3")
	public void from3(User user){
		String name = user.getName();
		String password = user.getPwd();
		System.out.println("name:"+name+"----------pwd:"+password);
	}
	

​ 4.URL地址传值

	@RequestMapping("/form4/{id}/{num}")
	public void form4(@PathVariable("num")String num,@PathVariable("id")String id){//自动根据表单名字,与Bean属性名字匹配
		System.out.println(id);
		System.out.println(num);
	}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mp3WXdBI-1596205009402)(C:\Users\吴永鑫\Desktop\Xmin学习\自己的画图理解\URL传值.png)]

3.2 过滤器

​ 在tomcat的重定向或者转发中,post请求会需要设置字符集,不然会出现乱码问题,不可能在每次请求的时候都设置一下字符集,springMVC底层代码可以直接设置,在web.xml中配置

	<!-- SpringMVCy已经写好的过滤器,我们直接配置使用就可以了 -->
	<filter>
		<filter-name>characterEncoding</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>characterEncoding</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

3.3 传递参数

​ 1.用req传递参数

	@RequestMapping("/form5")
	public void from5(HttpServletRequest req,HttpServletResponse rosp) throws ServletException, IOException{
        //给页面的message5传递(好像是那么回事)的参数
		req.setAttribute("message5", "好像是那么回事");
        //转发回model2.jsp界面
		req.getRequestDispatcher("/jsp/model2.jsp").forward(req, rosp);
	}

2. 用Model对象传值,注意要有返回值

	@RequestMapping("/form6")
	public String from6(Model model){
		model.addAttribute("message6", "也就那么亿点点差距");
		//返回/jsp/model2.jsp界面
		return "/jsp/model2.jsp";
	}

​ 3.用ModelAndeView传递,将参数传入ModelAndeView对象中

	@RequestMapping("/form7")
	public ModelAndView from7(){
		ModelAndView mv = new ModelAndView();
		mv.addObject("message7", "时间会证明我多爱你啊");
		List<Integer> list =new ArrayList();
		list.add(1);
		list.add(4);
		list.add(3);
		list.add(8);
		mv.addObject("list", list);
		mv.setViewName("/jsp/model2.jsp");
		return mv;		
	}

3.4 视图解析器

​ 每次返回都是/开头,.jsp结尾,所以咋说,能省就省,将这一头一尾配置在配置文件中就OJBK了,配置在spring-mvc.xml中

特点:方法有返回值的才会经过视图解析器,没有返回值的不会经过视图解析器。

	  <!-- 设置视图路径的前后缀,该配置可以让我们写视图路径的时候更简单 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	 	<property name="prefix" value="/" />
	 	<property name="suffix" value=".jsp" />
	</bean>
	@RequestMapping("/form6")
	public String from6(Model model){
		model.addAttribute("message6", "也就那么亿点点差距");
//		return "/jsp/model2.jsp";//没有视图解析器
//		return "jsp/model2";//经过视图解析器的
		return "forward:/jsp/model2.jsp";//显示转发,走绝对路径,不会经过视图解析器
	}

3.5 重定向和转发【面试题】

​ springMVC默认的方式是转发,两者都不会经过视图解析器

​ forword:相当于一次请求:共享请求对象 forword:/form6/jsp/model2.jsp

​ Redirect:重定向:请求对象不同,多次请求。 redirect:/jsp/model2.jsp

Day40-Json&SpringMVC

1.Json

1.1 Json语法

​ Json是类似与xml的一种轻量级数据格式,语法是和js同步的。

​ var obj = {“name”: tom,“age”: 24,“User”: user}

1.2 SpringMVC转换JSON

  1. ​ 导入jar包

    jackson-annotations-2.5.0.jar
    jackson-core-2.5.0.jar
    jackson-databind-2.5.0.jar
    
  2. 方法用@ResponseBody注解

    	没有@ResponseBody注解时,返回一个emp对象,在springMVC底层会自动加载入一个MpdelAndView对象,将emp对象传入里面当属性元素,返回的值也会被视图解析器加载
     			ModelAndView mv = new ModelAndView();
    			mv.addObject("employee", emp);
    			mv.setViewName("/json/get1");//经过视图解析器会成为//json/get1.jsp
    
	@RequestMapping("/get1")
	@ResponseBody
	public Employee get1(){
		Employee epm = new Employee("二蛋", 24, new Date());
		return epm;				
	}
  1. 日期显示的处理

    从前端到后台:在set方法添加注解格式

    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    public void setDate(Date date) {
    	this.date = date;
    }
    

    从后台到前端:在get方法添加注释

    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
    public Date getDate() {
    	return date;
    }
    

2.文件上传和下载

2.1 文件上传

  1. 配置前端

    	<!-- enctype="multipart/form-data" 表示这是复杂表单
    			必须用post请求,因为文件的大小可能超过2MB get请求不能够 -->
    	<form action="/file/upload" method="post" enctype="multipart/form-data">
    		账号:<input type="text" value="tom" name="username"></br>
    		头像:<input type="file" name="photo" ></br>
    		<input type="submit" value="提交">
    	</form>
    
  2. 配置文件上传解析器,在spring-mvc.xml中

    <!-- 文件上传解析器 -->
    	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    	<!-- 设置上传文件的最大尺寸为1MB -->
    		<property name="maxUploadSize">
    			<!-- spring el写法:1MB -->
    			<value>#{1024*1024}</value>
    		</property>
    	</bean>
    
  3. 后端代码实现

    @Controller
    @RequestMapping("/file")
    public class FileController {
    	/**
    	 * 上传步骤分析
    	 * 		1.获取路径
    	 * 		2.获取输入流
    	 * 		3.获取输出流
    	 * 		4.IOUtils.copy
    	 * @param username
    	 * @param ptoto  复杂表单属性,值的名字必须和表单的name属性一致
    	 * @param rep
    	 * @throws IOException 
    	 */
    	@RequestMapping("/upload")
    	public void upload(String username,MultipartFile photo,HttpServletRequest rep) throws IOException{
    
    		System.out.println("表单名字:"+username);
    		
    		System.out.println("上传文件是否为空:" + photo.isEmpty());
    		System.out.println("上传文件的大小(字节):" + photo.getSize());
    		System.out.println("上传文件的类型:" + photo.getContentType());
    		System.out.println("上传表单name属性值:" + photo.getName());
    		System.out.println("上传文件名:" + photo.getOriginalFilename());
    		
    		
    		//第一步获取文件的真实路径
    		String realPath = rep.getServletContext().getRealPath("/img");
    		//将文件保存在路径中
    		File file = new File(realPath);
    		System.out.println(file.toString());
    		//对文件进行判断
    		if (!file.exists()) {
    			file.mkdirs();
    		}
    		//增添一个UUID给文件名字,防止文件名字重复
    		String uuid = UUID.randomUUID().toString().replaceAll("-", "");
    		String filename = uuid+"-"+photo.getOriginalFilename();
    		System.out.println("文件名字:"+filename);
    		
    		//获取输入流
    		InputStream is = photo.getInputStream();
    		//获取输出流H:\JAVAstudy\Day40_Json_SprinfMVC\WebContent\img+
    		FileOutputStream os = new FileOutputStream(new File(realPath,filename));
    		
    		//工具流赋值
    		IOUtils.copy(is, os);
    		System.out.println("上传成功");
    		//关流
    		is.close();
    		os.close();
    	}
    

2.2 文件下载

	@RequestMapping("/download")
	public void download(HttpServletRequest req,String filename,HttpServletResponse resp) throws Exception {
		//第一步,获取文件路径
		String realPath = req.getServletContext().getRealPath("/img");
		File file = new File(realPath, filename);
		
		//获取文件输入流
		FileInputStream is = new FileInputStream(file);
		
		//处理不同浏览器的字符集问题
		if(req.getHeader("User-Agent").toUpperCase().indexOf("TRIDENT")!=-1){//IE
			filename = URLEncoder.encode(filename, "utf-8");
		}else if(req.getHeader("User-Agent").toUpperCase().indexOf("EDGE")!=-1){//电脑自带edge【edʒ】浏览器	
			filename = URLEncoder.encode(filename, "utf-8");
		}else{
			//其他浏览器默认的都是ISO-8859-1字符集,所以要将UTF-8转换为ISO-8859-1
			filename = new String(filename.getBytes("UTF-8"),"ISO-8859-1");//转码的方式
		};
		
		//设置文件下载的名字
		resp.setHeader("Content-Disposition", "attachment; filename=" + filename);
		
		//获取输出流
		ServletOutputStream os = resp.getOutputStream();
		
		//拷贝
		IOUtils.copy(is, os);
		is.close();
		os.close();
		
	}

3.SpringMVC拦截器

​ 拦截器是配置在spring-mvc.xml中拦截请求的,写个类实现HandlerInterceptor类

public class MyInterceptor implements HandlerInterceptor {
	
	// afterCompletion()方法在DispatcherServlet完全处理完请求后被调用 
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println("第三层拦截器");
	}	
	// postHandle()方法在业务处理器处理请求之后被调用   
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		System.out.println("第二层拦截器");
	}	
	//preHandle()方法在业务处理器处理请求之前被调用 
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		System.out.println("进来第一层拦截器");
		//返回的是true代表放行,返回false代表全部拦截
		return true;
	}
}

​ 在spring-mvc.xml中配置拦截器

<!-- 配置拦截器组-->
	<mvc:interceptors>
		<!-- 拦截器 -->
		<mvc:interceptor>
			<!-- 要拦截的配置,该配置必须写在不拦截的上面,/*拦截一级请求,/**拦截多级请求 -->
			<mvc:mapping path="/**"  />
			<!-- 设置不拦截的配置 -->
			<mvc:exclude-mapping path="/login"/>
			<!-- 配置拦截器 -->
			<bean class="cn.itsource.springmvc._06_interceptor.MyInterceptor" />  
		</mvc:interceptor>
	</mvc:interceptors>

4.SpringMVC流程理解【面试重点题】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-usxsfowv-1596205009404)(C:\Users\吴永鑫\Desktop\Xmin学习\自己的画图理解\SptingMVC执行流程.png)]

  1. 发送请求到达DispatcherServlet
  2. 根据xml或者注解的方式 获得映射器管理器HandleMappling
  3. Controller 实现接口 普通类 适配器管理
  4. 数据验证
  5. 方法处理、ModelAndView
  6. 视图解析器解析ViewResolver 解析 response响应

Day41-SSM&高级查询

1.SSM搭建

​ SSM框架就是spring+springMVC+Mybatis三个框架集成一个项目框架。

1.1 Jar包

​ 三个框架各自需要的jar包+数据库jar包+(spring+Mybatis),G:\JAR包管理\SSM框架

1.2 配置文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BjdcCcY0-1596205009405)(C:\Users\吴永鑫\Desktop\Xmin学习\自己的画图理解\SSM框架配置文件关系图.png)]

​ 配置applicationContext.xml:spring需要连接数据库,连接Xxxmapper.xml,连接MyBatis

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.1.xsd">
    
       <!--1. 引入数据库连接的配置文件 -->
       <context:property-placeholder location="classpath:db.properties"/>
       <!--2. 配置连接池  -->
       <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
       		<property name="driverClassName" value="${jdbc.driverClassName}"></property>
			<property name="url" value="${jdbc.url}"></property>
			<property name="username" value="${jdbc.username}"></property>
			<property name="password" value="${jdbc.password}"></property>
       </bean>	
    
       <!--3.SqlSessionFactory  -->
       <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!-- 连接池 -->
       		<property name="dataSource" ref="dataSource"></property>
       		<!-- 配置mybatis (mapper)映射器路径  xml纳入到sqlSessionFactory  mybatis知道有这些xmL -->
			<property name="mapperLocations" value="classpath:cn/itsource/mapper/*Mapper.xml" />
			<!-- 配置别名 -->
			<property name="typeAliasesPackage" value="cn.itsource.domain" ></property>
       </bean>
    
       <!-- 
			4.配置扫描Mapper接口:动态创建mapper包中所有接口的动态实例 
            ProductMapper.java  接口的实例&  Spring自己创建了    你需要用直接向Spring取即可 
            ProductMapper.xml
       -->
		<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
			<!-- 这句可以省略,自动注册 -->
			<!-- <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> -->
			<property name="basePackage" value="cn.itsource.mapper"></property>
			<!-- 指定注解的类,一般不配置 -->
		    <!-- <property name="annotationClass" value="com.fire.annotation.Mybatis"></property> -->
		</bean>
	   <!-- 配置扫描Service domain service层交给Spring管理    Controller需要service  @Autowired注入-->
		<context:component-scan base-package="cn.itsource.service"></context:component-scan>
</beans>

​ 配置spring-mvc.xml文件:扫描包路径+放行静态资源+开启RequestMapping注解+视图解析器

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.1.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">
    <!-- 1. 配置扫描包路径子容器只扫描controller包 -->
	<context:component-scan base-package="cn.itsource"></context:component-scan>
	<!-- 2. 配置静态资源放行 -->
	<mvc:default-servlet-handler></mvc:default-servlet-handler>
	<!-- 3. 配置开启Spring对mvc的支持,支持@RequestMapping注解 -->
	<mvc:annotation-driven></mvc:annotation-driven>
	<!-- 4.配置视图解析器 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>
</beans>

​ db.properties和log4J.xml 的配置稳定固定死了

​ 配置web.xml:读取applicationContext和springmvc文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
    <!-- Spring实现的上下文监听器:启动Spring容器 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>
	<!-- SpringMVC前端控制器 -->
	<servlet>
		<servlet-name>dispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring-mvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcherServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<!-- SpringMVC过滤器:针对请求对象设置编码 -->
	<filter>
		<filter-name>EncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<!-- 以前的其他请求过滤器做了编码设置:  通过我这个过滤器的时候,强制设置你为UTF-8 -->
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>EncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

1.3 编写后端代码

​ 1.数据库表对应的实体类;

​ 2.三层架构,从前端穿请求到Controller层—>Service服务层—>Dao实现层,这里的Dao实现层被MyBatis中的mapper代替,实现类由底层的XxxMapper.xml代替。

<mapper namespace="cn.itsource.mapper.EmployeeMapper">
	<!-- 查询所有,不需要传递参数,返回一个product对象 -->
	<select id="loadAll" resultType="employee">
		select * from employee
	</select>
</mapper> 

​ 3.总归围绕三层架构思想不变动,一层一层的传递数据信息,当报错的时候,按照此思想一层一层的排查错误。

2.高级查询

2.1概念

​ 所谓高级查询,就是带条件的查询方式,也就是SQL语句的变化,通常需要对SQL语句进行拼接。在XxxMapper.xml中,用where标签连接条件,然后用if标签撰写判断条件。

		<where>
			<if test="deptno != null"><!-- 当被判断的类型是Interger类型时,只需要判断他是否为空 -->
				and deptno = #{deptno}
			</if>
	
			<!-- 当被判断的类型为String字符串时,第一个判断他是否为空,第二个还需要判断字符串是否为空字符串 -->
			<if test="ename != null and !''.equals(ename.trim())">
				<!-- 拼写%String% 其中String需要去除空格 -->
				and ename like concat('%',trim(#{ename}),'%')
			</if>

		<if test="address != null and !''.equals(address.trim())">
			<!-- 拼写%String% 其中String需要去除空格 -->
			and address like concat('%',trim(#{address}),'%')
		</if>
	
		<if test="sal != null">
			<choose>
				<when test="sal == 3000">
					and sal &lt;= #{sal}
				</when>
				<when test="sal == 5000">
					and sal &lt;= #{sal} and sal &gt;= #{sal}-2000
				</when>
				<when test="sal == 8000">
					and sal <![CDATA[ <= ]]>
					#{sal} and sal &gt;= #{sal}-3000
				</when>
				<when test="sal == 8001">
					and sal &gt;=#{sal}-1
				</when>
			</choose>
		</if>
	<where>

2.2 特殊符号

(1) 在xml的转义字符:

​ ① 符号:<【<】、<=【<=】、>【>】、>=【>=】、&【&】、’【’】 、 “【”】

​ ② 【gt -> greater than(大于 )lt -> less than(小于)】

(2) 或者可以用CDATA代码段:

​ ① 大于等于 <![CDATA[ >= ]]>

​ ② 小于等于 <![CDATA[ <= ]]>

2.3 抽取和include引入

询,就是带条件的查询方式,也就是SQL语句的变化,通常需要对SQL语句进行拼接。在XxxMapper.xml中,用where标签连接条件,然后用if标签撰写判断条件。

		<where>
			<if test="deptno != null"><!-- 当被判断的类型是Interger类型时,只需要判断他是否为空 -->
				and deptno = #{deptno}
			</if>
	
			<!-- 当被判断的类型为String字符串时,第一个判断他是否为空,第二个还需要判断字符串是否为空字符串 -->
			<if test="ename != null and !''.equals(ename.trim())">
				<!-- 拼写%String% 其中String需要去除空格 -->
				and ename like concat('%',trim(#{ename}),'%')
			</if>

		<if test="address != null and !''.equals(address.trim())">
			<!-- 拼写%String% 其中String需要去除空格 -->
			and address like concat('%',trim(#{address}),'%')
		</if>
	
		<if test="sal != null">
			<choose>
				<when test="sal == 3000">
					and sal &lt;= #{sal}
				</when>
				<when test="sal == 5000">
					and sal &lt;= #{sal} and sal &gt;= #{sal}-2000
				</when>
				<when test="sal == 8000">
					and sal <![CDATA[ <= ]]>
					#{sal} and sal &gt;= #{sal}-3000
				</when>
				<when test="sal == 8001">
					and sal &gt;=#{sal}-1
				</when>
			</choose>
		</if>
	<where>

2.2 特殊符号

(1) 在xml的转义字符:

​ ① 符号:<【<】、<=【<=】、>【>】、>=【>=】、&【&】、’【’】 、 “【”】

​ ② 【gt -> greater than(大于 )lt -> less than(小于)】

(2) 或者可以用CDATA代码段:

​ ① 大于等于 <![CDATA[ >= ]]>

​ ② 小于等于 <![CDATA[ <= ]]>

2.3 抽取和include引入

​ 可以将写好的标签的判断条件以及语句外部用围住并取ID,然后在where中用include标签将sql引入作为判断条件,是界面简洁化。

猜你喜欢

转载自blog.csdn.net/yydsuzi/article/details/107722626
今日推荐