从零开始学JAVA web,我学了些什么,这篇文章将会记录这一段学习历程。(暂告一段落)
JavaWeb-Spring
GitHub:Spring学习过程中创建的项目,包含一些例子
○一、🚶JavaSE
- [x] Java语言基础内容,已经掌握
○二、🐴JSP/Servlet
主要以理解Tomcat中Servlet的运行原理为重点
○JSP
Jsp本质是servlet,约等于分不清前后端,耦合性太强,已经被时代抛弃,大概了解即可,直接跳过学习。
○JSTL
JavaServer Pages Tag Library :JSP标准标签库
用于简化和替换jsp页面上的java 代码
○Servlet
-
Servlet:
注解声明
@WebServlet("path")
tomcat服务器的核心,主要是理解Http协议、
HttpServletRequest
以及HttpServletResponse
原理。req可以进行转发forward
(服务器内servlet间转发),resp可以进行重定向redirect
(由浏览器发送第二次请求,可跨服务器) -
Filter:
注解声明
@WebFilter("path")
过滤器,拦截request和response,可以对req和resp进行判断是否放行。
-
Listener:
注解声明
@WebListener
监听器,
ServletContextListener
监听ServletContext对象的创建(服务器启动)和销毁(服务器关闭),该接口主要用于加载资源和释放资源等操作。除此之外还有其他监听器。 -
ServletContext:
服务器内的一个全局上下文,可以从servlet或req中获取(单例类)。作用是获取服务器真实路径
getRealPath()
、设置和获取服务器内共享的数据域set/getAttribute()
和获取Content-typegetMimeType(filename)
,通过配置<context-param>
可以用getInitParam()
来加载资源文件 -
Cookie:保存于浏览器的数据,用来识别身份,保存sessionid等。可以设置存活周期。
-
Session:保存于服务器的数据,用来记录每个浏览器特定的信息,由一个id对应。可以设置存活周期,服务器关闭后会
钝化
,再次开启后活化
○EL表达式
语法:${expression}
-
运算
算数运算、比较运算、逻辑运算、判空运算
empty
-
获取值
从域对象中获取值
${域名称.keyName}
、${keyName}
域名称 说明 pageScope 从pageContext获取 requestScope 从request中获取 sessionScope 从session中获取 applicationScope 从ServletContext获取
○ExtraDetail
这里记录在学习这个模块的过程中额外学习到的内容。
○ProxyMode
代理模式,软件设计模式的一种,通过中间代理执行方法,来达到增强的目的。后续框架中经常使用该模式。
动态代理在Java中使用
class Proxy{
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfacies, InvocationHandler h){}
}
其中InvocationHandler
是抽象类,需实现
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {}
通过在该方法中调用method.invoke(obj,args)
来执行被代理的对象的方法。可以修改返回值或者参数等手段来增强该方法,也可以在方法调用前和调用后增加其他类的方法。
实例化的对象即代理对象,通过强制转化为传入的某个接口可以直接调用接口方法,且是通过InvocationHandler
执行。
○MVC开发模式
-
M: Model 模型
JavaBean
完成业务逻辑操作,如查询数据库、封装数据
-
V: View 视图
jsp
展示数据
-
C: Controller 控制器
servlet
分发工作,获取客户端的输入然后调用模型,将数据交给视图。
○三层架构
-
界面层(表示层 web)
SpringMVC
用户能够通过界面的组件和服务器进行交互,调用Service完成请求处理,转发jsp页面完成显示。
- 控制器:servlet,接受用户请求并封装参数信息到Servic层
- 视图:JSP,接受控制器提供的数据并展示出来给用户
-
业务逻辑层 (service)
Spring
处理业务逻辑,组合DAO层的简单方法,组成各种复杂的业务功能。
-
数据访问层 (dao)
MyBatis
操作数据存储文件,定义了对数据库最基本的CRUD操作
○Bootstrap/JQuery/AJAX
皆为前端框架
-
Boostrap
提供丰富的html标签和css样式,具有响应式布局,配合JQuery/Vue使用。
-
JQuery
对js的封装,提供了选择器等许多丰富API来帮助编写js动态生成页面。
-
AJAX
异步的JavaScript和XML,用于向服务器发送异步请求,可以在JQuery/Vue中便捷使用。
○三、🚲JDBC/SQL
两者是数据库的重要内容,SQL有MySQL、SQLserver
等,JDBC
则是Java操作数据库SQL的重要API,都应熟练掌握并理解原理。
○MySQL
学会数据库增删查改等操作,熟练运用操控数据库的高级技巧,重点理解数据库原理,学会优化数据库。
○事务
○基本介绍
事务指的是一个包含多个步骤的业务操作,如果这个操作被事务管理,则要么同时成功,要么同时失败。事务可以提供回滚操作,撤销出错的影响。
START TRANSACTION
开启事务管理ROLLBACK
回滚COMMIT
提交事务
SELECT @@autocommit
查看是否为自动提交,修改后可以改变默认管理方式
○四大特征
- 原子性:数据库操作中不可分割的最小单位,要么同时成功,要么同时失败
- 持久性:事务提交或回滚后,数据会持久化保存在数据库中
- 隔离性:多个事务之间相互独立
- 一致性:事务操作前后,数据总量不变
○隔离级别
多个事务操作同一批数据会引发一些问题,通过设置隔离级别可以解决这些问题。
- 脏读:一个事务,读取到另一个事务中没有提交的数据。
- 不可重复读:同一个事务中,两次读取到的数据不一样(可能被另一个事务修改了)MySql-MVCC原理
- 幻读:一个事务(同一个read view)在前后两次查询同一范围的时候,后一次查询看到了前一次查询没有看到的行。
级别 | 说明 | 安全性 |
---|---|---|
read uncommitted | 读未提交,允许读取未提交的数据 | 0 |
read committed | 当前读、读已提交,只有已经提交的数据才能被读取 | 1 |
repeatable read | 可重复读,使一个事务周期内的数据不受其他事务影响 | 2 |
serializable | 串行化,锁定一张表,相当于单线程执行事务 | 3 |
从小到大安全性越来越高,效率越来越低!不同的数据库隔离级别原理不同,如MySql的MMVC,因此能解决的问题也不同
通过SELECT @@tx_isolation
查询隔离级别,SET GLOBAL TRANSACTION ISOLATION LEVEL 级别名
设置隔离级别
○JDBC
JDBC是Java用来操作数据库的接口,具体实现由不同数据库公司实现,他的实现类被称为**“驱动”(Driver)**。
常见驱动类:
- MySql:“com.mysql.cj.jdbc.Driver”
- SqlServer:“com.microsoft.sqlserver.jdbc.SQLServerDriver”
○使用方法
-
注册驱动
/* 通过该方法把类加载到内存 驱动类来自每个不同的数据库公司,以下是mysql的驱动类 该方法执行时,类的静态代码块会被执行,Driver会使用registerDriver方法注册DriverManager mysql5以上的版本可以省略这个注册过程 */ Class.forName("com.mysql.cj.jdbc.Driver");
-
获取数据库连接对象
import java.sql.*; /* url: 数据库地址 jdbc:mysql://域名:端口/dbName user: 管理员用户名 pwd: 管理员密码 */ Connection conn = DriverManager.getConnection(url,user,pwd);
-
定义sql语句
String
-
获取执行sql对象
import java.sql.*; //satement 可以执行sql语句 Statement stat = conn.createStatement();
-
执行sql获取返回结果
//sqlStr 为数据库执行语句,如DML(insert、update、delete)、DDL(create、alter、drop) //返回影响的行数:可以通过这个值判断DML语句是否执行成功 stat.excuteUpdate(sqlStr);
-
释放资源
//执行对象释放 stat.close(); //数据库连接释放 conn.close(); //结果对象释放 resultSet.close();
○常用对象详解
Connection:
-
获取sql对象
createStatement()
、preparedStatement(sqlStr)
-
管理事务
关闭自动提交事务的功能即可开启手动事务管理
开启:
setAutoCommit(false)
、提交:commit()
、回滚:rollback()
Statement:
excuteUpdate(sql)
:执行DML(insert、update、delete)、DDL(create、alter、drop),返回影响的行数executeQuery(sql)
:执行DQL(select)语句,返回ResultSet
ResultSet:
-
next()
:移动游标到下一行,游标初始于第0行(表头),如果下一行没有数据则返回false -
getXxx(int/str)
获取当前行的数据,
Xxx
为数据类型名,返回类型为Xxx
方法指定参数为int时,表示columIndex获取第几列的数据
方法指定参数为str时,表示columName获取名为str的列的数据
PreparedStatement:
-
解决SQL注入问题
某些sql特殊关键字参与字符串拼接会造成安全性问题,如
WHERE
后存在恒等式则表示没有约束作用 -
预编译sql
sql语句的参数使用
?
占位符,使用setXxx(pos, value)
方法赋值,该方法传入占位符的位置(第几个)和值来进行sql参数补充,value类型为Xxx
-
excuteUpdate()
-
executeQuery()
○事务管理
事务指的是一个包含多个步骤的业务操作,如果这个操作被事务管理,则要么同时成功,要么同时失败。
- 开启 提交 回滚 使用Connection管理
○使用方法
try {
conn.setAutoCommit(false); //open
// TODO: do sql
conn.commit(); //commit if no exception occur
} catch (Exception e){
conn.rollback(); //rollback if has any exception
}
当rollback()
执行时,刚刚执行的sql操作都会撤销。
○数据库连接池
优化Connection操作,提高数据库访问性能
○原理
使用连接对象容器管理Connection,从容器中获取,归还到容器中去,由容器管理是否断开连接。
○实现方法
*Interface DataSource:*由Driver实现,Druid性能较高
-
C3P0:ComboPooledDataSource
使用classpath:
c3p0.properties/c3p0-config.xml
配置参数 -
Druid:DruidDataSourceFactory
使用
druid.properties
配置参数,需要手动加载。通常封装成工具类静态加载配置文件。
○Spring JdbcTemplete
由Spring封装的JDBCUtils,简化操作。详细见下文
○Junit4
Junit单元测试属于白盒测试的一种。
○注解
注解 | 说明 |
---|---|
@Before | 在所有测试方法前执行 |
@After | 在所有测试方法后执行,无论是否存在异常 |
@Test | 标注方法为测试方法 |
○测试方法
所有测试方法都是无参的,测试方法内最好不要直接输出数值,应该尽量使用assert
断言结果于预期是否相符合。对于测试期间出现的异常应该尽量捕获并写入文件中,标明异常方法和异常原因。
○Redis/Jedis
非关系型数据库,有缓存功能。。。
○四、🚗SSM
JavaWeb框架集合之一,由Spring+SpringMVC+Mybatis
组成,适用于轻量级微服务开发,要深入理解原理。
○Spring
Spring框架属于Service层框架,但是也管理了Web层和DAO层
○IOC
○ioc容器
Bean容器,spring在内部创建Java类,我们或Spring可以从容器中取出Bean
○XML式依赖注入
对<bean id="" class=""></bean>
对象的属性进行配置
分别为:对象注入ref
、普通数据类型注入value
、集合类型
-
集合类型:配置文件使用
<list><value>
、<map><entry key="" value-ref="">
、<props><prop key="">
组合使用 -
构造方法:有参构造,配置文件中使用
<constructor-arg name="" ref=""/>
注入 -
set方法:配置文件中使用
<property name="" ref=""/>
子标签标签设置属性值注入
模块开发
<import resource="applicationContext-xxx.xml" />
○注解式依赖注入
-
原始注解
使用前须在配置文件中配置组件扫描,指定需要注解开发的包
<context:component-scan base-package=""> <!--用于排除不需要被扫描的类--> <context:exclude-filter type="" expression="" /> </context:component-scan>
注解 说明 @Component 类上实例化Bean,代替Bean标签 @Controller web层类上实例化Bean @Respository dao层上实例化Bean @Service service层上实例化Bean @Autowired 依赖注入标签,加在成员变量/setter/构造方法 @Qualifier 结合Autowired一起使用根据名称进行依赖注入 @Resource 相当于前两者的结合,是javaEE的注解,不是Spring的注解 @Value 注入普通属性(int等) @PostConstruct 声明Bean的初始化方法 @PreDestroy 声明Bean的销毁方法 @Scope 标志Bean的范围,singleton/prototype -
新注解
可以完全替代xml配置文件
注解 说明 @Configuration 指定类为配置类,创建容器时从该类上加载注解 @ComponentScan 指定要扫描的包,同 <context:componnet-scan>
,使用excludeFilters排除不需要被扫描的类@Bean 标注方法的返回值储存于容器中 @PropertySource 用于加载 .properties
文件的配置@Import 用于导入其他配置类
○AOP
○概念
面向切面编程,是动态代理的规范化编程,动态代理如何增强方法见上文。SpringAOP底层使用的动态代理为以下两种:
-
Java原生接口代理
通过接口反射出代理对象,使用的是 ProxyMode
-
cglib子类代理
外部的工具库,已经集成在springframework-core中,使用的是Enhancer类。通过指定父类反射出代理对象。
根据目标对象[1]是否有接口来选择其中一个方法。
○XML配置动态代理
maven导入依赖aspectjweaver
、spring-aop
-
配置目标对象和切面对象Bean
切面类和目标类都需要配置为Bean才能被Spring从IOC容器中取出来
-
配置织入(前置、后置……)
使用命名空间
xmlns:aop
<aop:config> <!--声明切面类--> <aop:aspect ref="beanName"> <!--配置切面:切点+通知--> <!--类似的还有aop:after等等--> <aop:before method="adviceName" pointcut="execution('方法声明')" /> </aop:aspect> </aop:config>
切面标签
名称 标签 说明 前置通知 aop:before 略 后置通知 aop:after-returning 略 环绕通知 aop:around 前后都执行,比前置更前,比后置更后 异常抛出通知 aop:throwing 出现异常时执行 最终通知 aop:after 最后执行,无论是否抛出异常 ℹ️环绕通知方法需要携带参数
ProceedingJoinPoint
表示连接点[2]对象,要在方法中执行该对象的proceed()
方法并return该方法的返回值。⚠️环绕通知方法的返回值都为
Object
,表示被增强的方法会返回一个对象或者NULL
,因此需要注意被增强的方法不能返回boolean
、int
等基础类型,需要用对应的包装类替换! -
切点表达式
execution([修饰符] 返回值 包名.类名.方法(参数))
-
修饰符可以省略(public、private……)
-
可以用通配符(*)代表任意
-
参数可以用
..
表示任意个数,任意类型的参数列表(可变参数)
ex:
execution(* cn.test.*.*(..)) //cn.test包下任意类的任意方法
**表达式抽取:**替换
point-cut
为point-cut-ref
,引用<aop:pointcut id="" expression=""/>
标签设定好的表达式idargs()
限制并自动抽取切点的方法参数,可以使用
..
表示缺省,一般配合通知方法获取方法参数,如:@Before("pointCut() && args(.., name)") public void before(String name) {} //表示pointCut限制下 要求“存在”参数【String name】
-
○注解配置动态代理
在配置文件中添加<aop:aspect-autoproxy />
自动代理aop
或者在配置类上用@EnableAspectJAutoProxy
标注
注解 | 说明 |
---|---|
@Aspect | 标注为切面类 |
@Before | 标志为前置通知,参数为execution表达式 |
@AfterReturning | 标志为后置通知,参数为execution表达式 |
@Around | 标志为环绕通知,参数为execution表达式 |
@AfterThrowing | 标志为异常抛出通知,参数为execution表达式 |
@After | 标志为最终通知,参数为execution表达式 |
**切点[3]表达式抽取:**在切面类中定义空实现方法,在方法上用@PointCut(’表达式‘)
标注,引用时按照className.methodName()
来描述
public class Aspect {
@PointCut("excution(*.cn.shijh.*.*(..))")
public void myPointCut(){}
@Before("Aspect.myPointCut()")
public void beforeEnhance(JoinPoint jp)
}
// 所有通知方法都能使用JoinPoint作为参数,Spring自动注入
○Spring事务控制
底层基于AOP实现事务管理,一般在Service层进行。
切点:Service方法
通知:事务管理
⚠️ ⚠️ ⚠️ 关于这个问题的详细说明
Spring事务管理与AOP之间存在神坑,被环绕通知的方法是无法进行事务控制的!!!!坑了我两三个小时!原因是事务管理本身就是环绕通知!!解决办法:设定Aspect和advisor的Order,且事务控制的Order要比环绕通知的大,否则无法完成事务回滚
○编程式控制
- PlatfromTransactionManager
spring事务管理器的接口,依据不同Dao层技术使用不同的实现类。
- DataSourceTransactionManager
Jdbc or MyBatis 对应的实现类。
- TransacitonDefinition
事务的定义对象,封装事务的隔离级别、传播行为、超时时间等属性。
-
ISOLATION_DEFAULT
:数据库默认级别ISOLATION_READ_UNCOMMITTED
ISOLATION_READ_COMMITTED
ISOLATION_REPEATABLE_READ
ISOLATION_SERIALIZABLE
-
传播行为
REQUIRED
:默认值,防止嵌套的两个事务发生,后一个事务会加入到前一个事务中。SUPPORTS
:后一个事务将不会开启MANDATORY
:强制加进入前一个事务中,没有前一个事务就报错
-
TransactionStatus
事务的运行状态对象。是否完成、是否回滚等状态。
○XML声明式控制
<!--配置事务管理的增强方法-->
<tx:advice id="" transaction-manager="">
<tx:attributes>
<!--name可以使用通配符‘*’和字符串组合使用
如‘update*’表示以update开头的所有方法名-->
<tx:method name="methodName" isolation="" propogation=""/>
</tx:attributes>
</tx:advice>
<!--transactionManager需要注入到IOC容器中-->
<!--配置增强方法的织入,使用aop-->
<aop:config>
<!--事务管理增强专用标签-->
<aop:advisor advice-ref="tx:advice" pointcut="execution"/>
</aop:config>
标签 | 说明 |
---|---|
tx:advice | 配置事务管理的通知,需指定transactionManager |
tx:attributes | 配置事务的属性,具体由多个tx:method配置 |
tx:method | 指定一个方法名,配置一个业务方法的属性,包括隔离级别等 |
aop:advisor | 用于事务管理的aop增强方法,引用配置好的tx:advice作为通知 |
配置事务属性时,只需指定方法名,不需要指定包名类名等,具体位置在织入时配置
○注解声明式控制
注解 | 说明 |
---|---|
@EnableTransactionManagement | 在配置类中标注,表示开启spring事务管理 |
@Transactional | 在方法或者类上标注,表示类下的方法都会被spring事务进行管理,可以加参数来配置事务的属性 |
使用注解配置时,driver会由spring自动配置,只需要将transactionManager放到IOC容器中
○Spring-Junit
通过注解集成Junit
注解 | 说明 |
---|---|
@RunWith | 指定使用Spring内置的测试类 |
@ContextConfiguration | 指定Spring配置文件、配置类 |
@AutoWired | 从IOC容器中注入测试对象 |
○Spring-JdbcTemplate
对JDBC API的封装,使调用更加简单
maven需要导入依赖spring-jdbc
和spring-tx
常用方法
-
setDataSource()
:设置连接池对象 -
update()
、query()
:执行sql语句 -
RowMapper<T>
可以自动完成数据封装的接口,是query()
的方法参数,对应实现类有BeanPropertyRowMapper<T>
,需要构造参数:new BeanPropertyRowMapper<JavaBean>(JavaBean.class)
query()
将返回List<T>
类型的集合 -
queryForObject()
同query()
一样,但是只返回一个对象 -
查询简单对象只需要传入
Class<T>
可以使用IOC容器来创建jdbcTemplate、dataSource对象,完成参数的注入。
○Spring-web
用于集成web环境的maven依赖spring-web
,提供获取应用上下文(ApplicationContext)的工具类和监听器。获取的原理是在服务器启动时创建上下文并放入ServletContext域中,即可在服务器共享。方便在 Servlet
中获取应用上下文,且可以避免多次创建带来的性能开销。
-
web.xml中配置监听器
ContextLoaderListener
-
配置
<context-param>
指定applicationContext.xml/.class的路径<context-param> <param-name>contextConfigLocation</param-name> <param-value>xx.xx.xx.ClassName</param-value> </context-param> <!--如果使用类配置则一定要指定下面的参数--> <context-param> <param-name>contextClass</param-name> <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> </context-param>
-
使用
WebApplicationContextUtils
获取上下文
○SpringMVC
属于web层框架,提供轻量级的MVC开发 ,核心是用servlet
实现的前端控制器。该控制器执行servlet的共有行为,并调用特有行为servlet,称为 Controller
○组件解析
○原理图解
○组件详解
-
HandlerMapping
-
HandlerAdaptor
执行对应的Controller,并把Controller的返回值包装成ModelAndView对象。
-
ModelAndView
setViewName()
设置页面跳转的页面名称addObject()
设置request域中的参数new ModelAndView(JsonView, ModelMap)
用一个Map和JsonView对象创建Json数据视图
-
ViewResolver
视图解析器,SpringMvc内部有很多解析器,默认使用的
InternalResourceViewResolver
。主要作用是把一个ModelAndView解析为一个真正的视图。其中一种视图解析使用了一种拼接url的方式,内部规定了前缀(prefix)、后缀(suffix),与视图的名称,如"index",拼接后就得到视图URL了。url方式可以在
ViewName
中加上前缀指定,有"redirect:“和"forward:”,表示重定向和转发。视图解析器会把这些包装成View对象返回前端控制器。 -
View
由解析器产生的对象,分为URL(jsp, jstl)、文档(excel, pdf)、报表、JSON。
○XML配置
-
在
web.xml
中配置前端控制器DispatcherServlet
<servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--设定SpringMVC配置文件的地址 使用类配置时要指定contextClass类型,同spring-web--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>配置文件地址</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>
-
使用独立的
spring-mvc.xml
配置SpringMVC的各种属性-
配置组件,ViewResolver、HandleAdapter等
用
<bean>
标签配置,同Spring一样
-
-
<mvc:annotation-driven>
自动配置一些组件的属性
○注解配置
注解 | 说明 | 参数 |
---|---|---|
@EnableWebMvc | 启用mvc注解驱动 | 无 |
@RequestMapping | 请求映射地址,用于类或方法中 | value:路径;method:请求方式;params:限定请求参数 |
@GetMapping | Request的细分 | value:路径 |
@PostMapping | 同上 | 同上 |
@ResponseBody | 标注返回值到content中 | 无 |
@RequestParam | 取request的参数 | value:所需参数的名称; require:强制要求?;defaultValue:默认值 |
@RequestBody | 标注方法参数上,注入JSON请求参数 | 无 |
@PathVariable | 标注方法参数上,用于restful风格的参数 | value;require;defaultValue; 同RequestParam |
@RequstHeader | 获取请求头数据 | value; require; |
WebMvcConfigurer
Mvc配置类需要实现的接口,用于配置更多SpringMvc的属性,如资源解析、拦截器等。
○注解配置web.xml
配置web.xml的类需要实现接口AbstractAnnotationConfigDispatcherServletInitializer
,并实现其中方法,Spring会自动查找该实现类来代替web.xml
/**
* 指定 ContextLoaderListener 所需的配置类
*/
@Override
protected Class<?>[] getRootConfigClasses() {}
/**
* 指定mvc的核心配置类
*/
@Override
protected Class<?>[] getServletConfigClasses() {}
/**
* 等同于设置 DispatcherServlet 的 url-pattern
*/
@Override
protected String[] getServletMappings() {}
/**
* 配置过滤器
*/
@Override
protected Filter[] getServletFilters() {
return new Filter[]{
new CharacterEncodingFilter("UTF-8"),
};
}
○数据响应
服务的的数据响应分为页面跳转和回写数据。
○页面跳转
-
直接返回字符串,如页面的名称"index",默认为转发
-
返回ModelAndView对象
通过
setViewName()
指定页面名称,addObject()
保存数据供JSP
调用ModelAndView对象可以放在形参中,Spring会自动注入一个空的对象。
○回写数据
-
ModelAndView
Json数据内容由
LinkedHashMap
转化而来,Json转化驱动可以是jackjson
、fastjson
,需要添加maven依赖。return new ModelAndView(new FastJsonJsonView(), map);
-
字符串
方法上标注
@ResponseBody
表示返回值直接写入response的content。Json也可以作为字符串直接返回,使用json驱动转化。 -
对象或集合
通过配置消息转换器,可以直接返回集合或者对象自动转化成Json字符串,同时要在方法上标注
@ResponseBody
。-
XML
配置
RequestMappingHandlerAdapter
bean标签,把Json转化驱动注入messageConverters
中。 -
注解、类配置
在Mvc配置类中继承
WebMvcConfigurer
接口,实现以下方法@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 此处配置FastJson FastJsonConfig config = new FastJsonConfig(); FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); config.setSerializerFeatures( SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty ); converter.setFastJsonConfig(config); converters.add(converter); }
*返回Map集合时,最好使用LinkedHashMap来保证Json内数据顺序不会乱掉
-
○获得请求参数
-
spring自动注入方法的参数中
限制:基本类型、数组和 Javabea(POJO)。集合对象(List等)需要包装到Bean中才能自动注入。当方法参数名与请求参数名一致时不需要加
@RequestParam
-
@RequestBody
直接接收request的参数数据注释在参数上,一般用于非表单的数据,如
application/json
、application/xml
用Json格式的数组作为请求参数,可以通过该标签直接注入到集合类型的方法参数中。
-
获得Restful风格的请求参数
使用
@PathVariable
获取,具体使用如下@RequsetMapping("/api/{id}/{name}") public void testController(@PathVariable("id") int id, @PathVariable("name") Stirng name) {}
-
获取请求头
使用
@RequstHeader(name)
在方法参数中注入。@CookieValue
直接获取Cookie数据。
○文件上传
Post Content类型为 Multipart/form-data
时,需要借助第三方工具简化获取参数的过程。
导入maven依赖 commons-io
、commons-fileupload
SpringMvc获取到上传的文件时,会打包成MulitpartFile
对象,因此用于获取文件的Controller方法需要有此类型的参数。
MultipartFile
getOriginFilename()
获取文件名transferTo(File)
通过IO保存本地或其他服务器
○自定义类型转换器
SpringMvc从Request中获取参数时会使用Converter进行类型转化来匹配Controller方法中的参数类型。
实现 Convert<S,D>
接口,并配置到SpringMvc中。接口泛型分别为转换前类型和转换后类型。
<bean id="" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean id="" class=""></bean>
</list>
</property>
</bean>
<mvc:annotation-driven conversion-service=""/>
○静态资源访问
当 spring-mvc 的 dispatcher-servlet 路径配置为/
,访问资源时也会去寻找Handler,无法访问到资源文件。解决方法有两种,第一种是配置资源文件的映射,第二种是交由tomcat来寻找资源文件。
-
XML配置
<!--1.配置资源文件的映射--> <mvc:resource mapping="url" location="path" /> <!--2.启用默认servlet-handler管理资源文件--> <mvc:default-servlet-handler />
-
注解、类配置
在Mvc配置类中继承
WebMvcConfigurer
接口,实现以下方法@Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); }
○Session管理
SpringMvc可以使用注解对Session进行一些简单的管理操作,如向session域中存入数据等。
-
方法一:
在Controller方法中使用HttpSession对象作为参数,Spring会自动注入。HttpSession能够同时完成添加、删除、查询Attribute的功能。
-
方法二:
在Controller类上使用
@SessionAttributes
并指定参数为该类需要使用的AttributeNames,然后方法上的参数就可以使用@ModelAttribute(name)
注入Session域的数据。在方法参数中使用Model类型,Spring会把该类的所有Session注入到Model对象中,因此也能够获取Session中的值,同时能够向Session中添加值。需要注意的是,使用该方法清除Session时,需要使用SessionStatus(作为方法参数,spring自动注入)的SetComplete()
来清除,并且只会清除@SessionAttributes
中标记的键值对。
✋Spring官方文档中提出,对于用户登录验证的session最好使用方法一,实际上我们会使用安全框架来完成这个功能,如 Shiro
○拦截器 Interceptor
与Filter过滤器类似,用于预处理和后处理,原理为AOP。只对控制器方法进行拦截,不拦截资源访问
○自定义拦截器
实现HandlerInterceptor
接口,并进行配置。
-
类配置
@Override public void addInterceptors(InterceptorRegistry registry){ registry.addInterceptor(interceptor).addPathPatterns("/"); }
-
xml配置
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path=""/> <bean/> </mvc:interceptor> </mvc:interceptors>
-
HandlerInterceptor
// 执行前拦截 public boolean preHandle(req, resp, handler); // 执行后,返回前拦截 public void postHandle(req,resp, handler, modelAndView); // 流程完毕后拦截 public void afterCompletion(req, resp, handler, exception)
preHandle
返回为True
时,后续操作才能执行。Handler
为控制器方法执行对象(Method)
○拦截器执行顺序
多个拦截器执行时,并非串行,而是嵌套的,也就是说拦截器执行链最后执行的方法时第一个拦截器的afterCompletion
。执行的顺序与配置的顺序有关,先配置先执行。
○异常处理机制
把异常处理抽取出来,通过异常处理组件统一解决,在SpringMvc中异常处理可以由DispatcherServlet
调用响应组件处理。
○异常处理器
HandlerExceptionResolver
-
SimpleMappingExceptionResolver
框架自带的实现类。Mapping——发生异常时跳转到异常视图,映射关系通过配置完成。
<bean class="org.xx.x.SimpleMappingExceptionResolver"> <property name="defalutErrorView" vlaue=""/> <property name="exceptionMappings"> <map> <entry key="" value=""/> </map> </property> </bean>
○自定义异常处理器
-
异常处理方法
使用注解
@ExceptionHanlder
标注在方法上时,该方法为所在类的异常处理方法。 -
异常处理类
使用注解
@ControllerAdvice
标注在类上时,该类为全局的异常处理类。类内的方法使用@ExceptionHandler
标注的方法将用于处理发生的异常。
注解 | 说明 | 参数 |
---|---|---|
@ExceptionHanlder | 用于方法上,异常处理方法 | 可以指定异常类,表示只处理个别异常 |
@ControllerAdvice | 用于类上,全局的异常处理类 | 无 |
*异常处理方法,会被当做一个Controller处理,因此其返回值最终会包装成ModelAndView对象,所以可以使用 @ResponseBody
注解
○在Junit中使用MockMvc
由于SpringMvc面向web层,因此无法直接调用Controller组件进行测试。
○使用方法
- 在Junit测试类上注解
@WebAppConfiguration
引入Web层配置文件 - 使用IOC注入
WebApplicationContext
对象 - 使用MockMvcBuilders创建MockMvc对象,需要传入WebApplicationContext初始化
- 使用MockMvc进行测试
○MockMvc
MockMvc主要使用perform()
方法向Controller发出请求,无需启动Tomcat服务器。perfrom
方法的参数由MockMvcRequestBuilders
创建,并返回一个ResultActions
对象。
MockMvcRequestBuilders
:创建一个模拟请求,有get或post类型,能够设置请求体和请求头参数ResultActions
:通常使用andDo
方法输出请求和响应的所有信息,执行andReturn
返回MvcResult
结果对象MvcResult
:结果对象,包含request和response信息
测试样例:
@Test
public void test3() throws Exception{
MvcResult res = mockMvc.perform(
MockMvcRequestBuilders
.post("/user/login")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.characterEncoding("UTF-8")
.param("userName", "zhangsan")
.param("password", "123")
).andDo(MockMvcResultHandlers.print()).andReturn();
System.out.println(res.getResponse().getContentAsString());
}
○Mybatis-Spring
前置-关于Mybatis的详细内容:Mybatis原始教程
Maven:mybatis-spring
○IOC注入
将Mybatis的SqlSessionFactory
等对象配置到SpringIOC容器中。
-
配置
SqlSessionFactory
,主要是配置其数据源dataSource
和核心配置文件configLocation
(非必须) -
mapper组件扫描
注解方式:
@MapperScan(basepackage="")
简洁方式:
<mybatis:scan base-package="" />
,这个方式不需要额外注解,但是也支持配置自定义注解来限制其扫描范围,指定annotation
为自定义的注解即可。以上两种方法将映射器(DAO)z注入到SpringIOC时,默认使用首字母小写作为Bean的名称,可以在自定义注解中设置org.springframework.stereotype.Component
这样的注解既可以作为标记,也可以作为一个名字提供器来使用了。
经典方式(不推荐使用了):
-
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="xx.xx"/> </bean>
配置完毕后即可使用依赖注入直接创建DAO/Mapper
接口对象。
○事务控制
配置事务管理器transactionManager
和事务增强,同样可以使用注解,同上文。配置完成后就可以像使用JdbcTempelate一样进行事务管理。
○ExtraDetail
○Properties/ResourceBundle
properties是一种键值对key=value
储存文件,Java中自带的Properties类可以简单的读写properties文件,但是ResourceBundle类更好的支持了不同的语言,比前者要好一点。
○Restful
Restful是一种软件架构、设计风格,提供了一些原则和约束,可以帮助软件设计变得更加简介有层次,更易于实现缓存机制等。Restful风格表现为“url+请求方式”来表现一次HTTP请求,特点是请求参数用/
接在url后面,而不再使用?
来表示请求参数。如:http://url/api?id=1
使用restful风格后应该是http://url/api/1
。
Restful规定请求方式具有如下几个含义:
- GET 表示获取
- POST 表示新建
- PUT 表示更新
- DELETE 表示删除
在前端中,form表单形式的请求是不支持PUT/DELETE的,需要使用隐藏的参数配合后端Filter
完成请求映射,在spring-mvc使用自带的HiddenHttpMethodFilter
来完成这个功能,通过指定隐藏参数的名自动从前端请求中获取Method值,但是前端显式的Method必须是"POST"形式。
○FastJson
由阿里巴巴开发的Json转化驱动。其中FastJsonHttpMessageConverter
可以用于SpringMvc的消息转换器中。
@JSONType
: 可以标注在类上,通过指定orders参数可以决定转化该类时解析属性的顺序。@JSONFiled
: 标注在成员变量上,可以指定转化后名称以及转化顺序@ResponseJSONP
:标注在Controller类或方法上,并配置Bean:JsonpResponseAdvice
,可实现注解方法返回Jsonp格式的数据,格式头取决于前端参数callback
,也可通过注解参数重新指定。(中文乱码问题)