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}时:不能用 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
-
导入jar包
jackson-annotations-2.5.0.jar jackson-core-2.5.0.jar jackson-databind-2.5.0.jar
-
方法用@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;
}
-
日期显示的处理
从前端到后台:在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 文件上传
-
配置前端
<!-- 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>
-
配置文件上传解析器,在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>
-
后端代码实现
@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)]
- 发送请求到达DispatcherServlet
- 根据xml或者注解的方式 获得映射器管理器HandleMappling
- Controller 实现接口 普通类 适配器管理
- 数据验证
- 方法处理、ModelAndView
- 视图解析器解析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 <= #{sal}
</when>
<when test="sal == 5000">
and sal <= #{sal} and sal >= #{sal}-2000
</when>
<when test="sal == 8000">
and sal <![CDATA[ <= ]]>
#{sal} and sal >= #{sal}-3000
</when>
<when test="sal == 8001">
and sal >=#{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 <= #{sal}
</when>
<when test="sal == 5000">
and sal <= #{sal} and sal >= #{sal}-2000
</when>
<when test="sal == 8000">
and sal <![CDATA[ <= ]]>
#{sal} and sal >= #{sal}-3000
</when>
<when test="sal == 8001">
and sal >=#{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引入作为判断条件,是界面简洁化。