Spring
1.IOC and DI
将new的权力交给spring,由工厂提供对象,同时通过DI维护对象与对象之间的关系
2.AOP
底层原理:动态代理的封装
通过产生动态代理来实现附加操作,来减少代码冗余
切面 = 通知(额外功能) + 切入点(加在哪里,哪些service类的哪些方法)
通知和切入点可以随意组合成切面
1. 引言
项目管理框架,不是替换别的框架,而是将框架进行整合管理
对组件(controller service Dao )进行对象管理(创建 使用 销毁),entity通常不交给spring
1 2 3 4
| 原来: new 去创建,然后调用 userDao = new UserDaoImpl(); userDao.save() 现在:xml配置bean,然后直接取出来
|
导入依赖 org.springframework下的spring-webmvc
配置applicationContext.xml
bean来管理对象的创建,class指定类UserDaoImpl,id唯一标识在spring容器中取出来(最好首字母小写)
1
| <bean id="userDao" class="init.UserDaoImpl"></bean>
|
启动工程,绑定xml文件,取出bean
1 2 3 4 5
| public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("init/applicationContext.xml"); UserDao usertest = (UserDao)context.getBean("userDao"); usertest.save("小明"); }
|
2. 核心思想
IOC(Inversion of Control)控制反转
由手动new变为配置文件配置,交给spring工厂。在tomcat中,也是该思想帮助我们创建了response对象
原理Class.forName(“UserDaoImpl”).newInstance() 反射调用构造方法
AOP面向切面
DI:dependency Injection IOC的补充
存在嵌套service调用dao,也就是serviceImpl中需要拿到daoImpl。
1 2 3 4 5 6 7 8 9 10 11 12
| public class UserServiceImpl implements UserService{ private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; }
@Override public void save(String name) { userDao.save(name); } }
|
都要先声明一个成员对象,然后
原来:new UserDaoImpl();
现在:需要set方法,在配置中完成赋值操作(注入) set注入
1 2 3 4 5
| ref:工程里的标识 bean的id,name:注入哪个属性 <bean id="userService" class="userServiceImpl"> <property name="userDao" ref="userDao" /> </bean>
|
IOC 创建对象,DI 维护对象与对象之间的关系
3. 注入
除了一个对象的注入,其他的用的很少
- set 注入 property标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| 1. 对象注入 ref <property name="userDao" ref="userDao" /> 2. String、日期、八种基本类型 value注入 <property name="name" value="xiao"></property> <property name="data" value="2012/12/12 23:54:57"></property> 日期需要/ :格式 3. array list set <property name="hobbys"> <array> 这里不同 <value>听歌</value> 字符串用value <ref bean="userDao"></value> 类用ref </array> </property> map <property name="card"> <map> <entry key="1" value="123"></entry> <entry key-ref="userDao" key-ref="userDao"></entry> 类 </map> </property> properties 无序键值对集合 <property name="info"> <props> <prop key="driver">com.mysqljdbc.Driver</prop> <prop key="姓名">jdbc:mysql://localhost:3306/test</prop> </props> </property>
|
- 构造注入 constructor-arg 标签
1 2 3 4
| 使用公开的有参构造方法 index代表参数的位置 <constructor-arg index="0" name="name" value="小明"/>
如果想单独赋值某些元素,就要对应的构造方法,很麻烦!!
|
- 自动注入 autowire = ”byType“ “byName”
底层是set 需要在组件标签上开启
Autowired
属于 Spring 内置的注解,默认的注入方式为byType
(根据类型进行匹配),也就是说会优先根据接口类型去匹配并注入 Bean (接口的实现类)。
问题: 当一个接口存在多个实现类的话,byType
这种方式就无法正确注入对象了
这种情况下,注入方式会变为 byName
(根据名称进行匹配),这个名称通常就是类名(首字母小写)。
SmsService
接口有两个实现类: SmsServiceImpl1
和 SmsServiceImpl2
,且它们都已经被 Spring 容器所管理。
1 2 3 4 5 6 7 8 9 10 11
| @Autowired private SmsService smsService;
@Autowired private SmsService smsServiceImpl1;
@Autowired @Qualifier(value = "smsServiceImpl1") private SmsService smsService;
|
4. 工厂特征
默认单例,多次getBean还是同一个。 struct2用成员对象存储信息,所以这时要多例 bean中scope = “prototype”
原理: 反射 + 构造方法
生命周期
单例:工厂启动时创建,正常关闭工程时销毁 context.close()
多例:getBean时创建,创建完成后脱离spring的管理,jvm去销毁
1 2
| 自己写的方法 init-method="" destroy-method=""
|
好处:
- 解耦合,更换类只需要修改配置文件
- 减少内存占用
- 建立对象与对象之间的关系 打开配置文件就可看到
5. 代理
代理对象:完成传化,也可以附加操作,同时也可以中断
好处:原始业务逻辑不变,同时可以附加
- 代理对象和原始逻辑对象实现相同的接口
- 代理对象 依赖 原始业务逻辑对象
原始逻辑中,除了具体事务,还有开启事务、提交事务、回滚事务的方法。后面这部分是重复的
在代理中,负责处理这些额外的方法,同时需要调用原始对象。总体的处理逻辑不变
1 2 3 4 5
| public void save(){ sout("开启事务") userService.save(name) out("结束事务") }
|
静态代理
每一个业务对象都开发一个代理对象,上面的逻辑
动态代理
在程序运行中自动生成
getSqlSession().getMapper(UserMapper.class).getUser(); 这一步也是通过代理实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 1. ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 类加载器 2. Class[] classes = {UserService.class} 目标对象的接口数组 3. new InvocationHandleer() 附加操作 额外功能 proxy = (UserServic)Proxy.newProxyInstance(classLoader, classes, new InvocationHandleer(){ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { log(method.getName()); Object result = method.invoke(new UserServiceImpl(), args); return result; } public void log(String msg){ System.out.println("执行了"+msg); } }); 生成动态对象 porxy.save(); 直接调用
|
封装成通用的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target) { this.target = target; }
public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this); }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { log(method.getName()); Object result = method.invoke(target, args); return result; }
public void log(String msg){ System.out.println("执行了"+msg); } }
---------
ServiceImpl service = new ServiceImpl();
ProxyInvocationHandler phi = new ProxyInvocationHandler();
phi.setTarget(service);
Service proxy = (Service) phi.getProxy();
proxy.add();
|
6. AOP
Aspect Oriented Programing 核心就是动态代理
附加操作:如日志打印,每个controller都加的话代码冗余
通过动态代理完成附加操作(通知、Advice)。开发通知类,配置切入点
通知(Advice):前置通知、后置通知、环绕通知、异常通知
切入点(pointcut):指定通知应用在哪里。一般用于业务层
切面(Aspect):通知(Advice)+ 切入点(pointcut)
导入依赖
开发通知 继承接口 MethodIntercept MethodBeforeAdvice ..
1 2 3 4 5
| public class Log implements MethodBeforeAdvice { public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println("执行了"+method.getName()+"方法"); } }
|
配置切面 .xml
被切的类都会创建代理对象,之后.getBean(“UserserviceImpl”)返回的是proxy,和5中动态代理一样,但每个被切的类不用单独创建
环绕通知
MethodInterceptor
计算运行时间 、处理异常
切入点表达式
7. 复杂对象
- 简单对象:可以直接new的对象,因此可以直接通过< bean >交给spring
- 复杂对象:不能直接new,接口Connction、抽象类Calendar
Implements FactoryBean<类名>
8.整合mybatis
spring:项目管理
mybatis:持久层CRUD。把mybatis中的对象创建交给spring
mybatis写法: .xml包含 数据源 以及 mapper注册 。 sqlSessionFactory =》sqlSession =》 usermapper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| 1.配置文件mybatis.xml 包含数据源信息(数据库账号密码等) 2.从配置文件.xml得到SqlSessionFactory,再openSession生成SqlSession执行sql语句 (封装成工具类) private static SqlSessionFactory sqlSessionFactory; static { String resource = "mybatis-config.xml"; try { InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } }
public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); }
3.编写Dao接口,接口实现类(.xml) 4.注册Mapper.xml <mappers> <mapper resource="com/kuang/dao/userMapper.xml"/> </mappers> 5.测试,调用工具类得到SqlSession,再调用getMapper,该mapper执行函数完成查询
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userList = mapper.getUserList();
|
8.1拿到sqlSessionFactory
SqlSessionFactoryBuilder 读配置文件,构建Factory
sqlSessionFactory 核心对象, 因此整合的核心就是接管这个!!!
sqlSession
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| sqlSessionFactory 是接口,因此利用第七节的方法完成配置,并把xml文件位置通过依赖注入到bean中
spring将这个类封装了,叫做SqlSessionFactoryBean 注入.xml,细粒度化,把dataSource分开了,同时配置mapperLocations;mybatis.xml中配置日志等其他对象(可以不要)
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8"></property> <property name="username" value="root"></property> <property name="password" value="123456"></property> </bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="mapperLocations" value="classpath:com/kuang/mapper/*.xml"></property> <property name="configLocation" value="classpath:mybatis-config.xml"/> (可以不要) </bean>
到这一步拿出sqlSessionFactory,就可以取出sqlSession.getmapper操作数据库 但我们的核心是在Dao部分,所以不想每次拿Dao时都先拿出sqlSessionFactory,想直接拿出Dao
|
8.2整和Dao
1 2
| factory中指向mapper文件 <property name="mapperLocations" value="classpath:com/kuang/mapper/*.xml"></property>
|
进一步封装,就可以直接getBean(UserDao)
1 2 3 4 5 6 7 8 9 10 11
| sqlSessionFactory和userDao绑定,就可以直接getMapper,等价 @Mapper,每一个都要写。@Repository没有用 <bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> <property name="mapperInterface" value="com.kuang.mapper.UserDao"></property> </bean>
这里每一个Dao都要配置,直接只写一个mapperscan可以解决 等价 @MapperScan <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="org.mybatis.spring.sample.mapper" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean>
|
或者将sqlsession作为一个成员放到UserDaoImpl中,间接调用,狂神的课程
1 2 3 4 5 6 7 8 9 10 11 12
| public class UserMapperImpl implements UserMapper{ private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) { this.sqlSession = sqlSession; }
public List<User> getUser() { UserMapper mapper = sqlSession.getMapper(UserMapper.class); return mapper.getUser(); } }
|
1 2 3 4 5 6 7 8 9
| <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory"/> </bean>
<bean id="userMapper" class="com.kuang.mapper.UserMapperImpl"> <property name="sqlSession" ref="sqlSession"></property> </bean>
|
9.Service事务
1
| 用DataSourceTransactionManager实现事务,自己写try-catch -> 写环绕通知 -> 用spring的环绕通知(细粒度)
|
service直接注入Dao即可,但需要处理事务
9.1.编程式
每个impl中注入事务管理对象实现
JDBC中
1 2 3
| connection.setAutoCommit(false); connection.commit(); connection.rollback();
|
datasouce中可以取出connection,但是service中的connection和dao中的可能不是同一个
DataSourceTransactionManager:全局事务管理,使得service和Dao连接对象相同,控制数据源的线程安全问题
1 2 3 4
| <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>
|
serviceImpl中,添加transactionManager, .commit() .rollback()。每一个serviceImpl都要写,用AOP解决冗余
9.2 声明式事务
aop实现事务处理
自己写:环绕通知,大家都一样的,所以spring封装了
封装后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add"/> <tx:method name="delete"/> <tx:method name="update*"/> 方法名需要对应上 </tx:attributes> </tx:advice>
<aop:config> <aop:pointcut id="tranPointCut" expression="execution(* com.kuang.mapper.*.*(..))"></aop:pointcut> <aop:advisor advice-ref="txAdvice" pointcut-ref="tranPointCut"></aop:advisor> </aop:config>
|
9.3事务传播
业务层中调用别的业务,可以把事务传播过去。
1 2 3 4 5 6 7 8 9 10 11 12
| OrderService.save(){ userService.update(); } <tx:method name="add" /> propagation="" REQUIRED:外层没有则开启,有则融入 增删改 默认 SUPPORTS:外层没有不开,有则融入;实现事务传播 查询 REQUIRE_NEW: 自己开一个新的 隔开 银行日志,总是要个新的 NOT_SUPPORTED: 不用事务 isolation="" read-only time-out: 事务超时 -1永不超时 秒
|
行锁为一条数据,在同一事务中多次查询,不会受到别人update印象
表锁为表的数据,多一条少一条不受印象
10.日志
log4j
ERROR WARN INFO DEBUG
配置文件在resource根目录下
1
| log4j.logger.com.baizhi.dao=DEBUG 展示sql
|
11.注解
装配
service太多了,每次都要添加
前置条件:开启注解扫描
1 2
| <context:component-scan base-package="com.kuang"/>
|
@component(value = “指定id”),装配到Spring中,等价与< bean>, 唯一标识为类名小写
- Dao **@Repository (只是告诉spring要加这个bean,和mybatis无关) ** @Mapper 和 @MapperScan结合使用为了结合spring和mybatis。如果不加@Repository可能爆红 但能正常运行
- Service @Service
- controller @ Controller
@Scope(value=”singleton\prototype”) 单例多例
注入
对象注入 属性或者set方法上。在属性上用时可以不用添加set方法,底层会自动提供set方法
@Autowired 默认类型
@Qualifier(value = “cat1”) 指定名称
JavaEE
@Resource 默认名字,找不到再类型
基本类型注入
@Value(“XX”) @Value(“${spring.datasource.username}”)
事务
@transactional(propagation = , ) 添加事务,加载类或者单个方法 serviceimpl上加
不需要事务通知对象以及添加切面,但还是添加开启注解事务
1
| <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven >
|
Dao还是扫描进行装配的
P21整合SM
SpringMVC
MVC中的C层,控制器框架。代替struts2
0.Struct2
1.C层:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class ProductAction extends ActionSupport { private List<Product> productList;
public String list() { productList = ProductService.getProductList(); return SUCCESS; }
public List<Product> getProductList() { return productList; } }
|
2.路由:封装servlet,Struts2的前端控制器DispatcherServlet接收并分发到对应的Action处理。
定义名为productList
的Action,并将其关联到ProductAction
类中的list()
方法。当请求到达/productList
时,Struts2会调用list()
方法并将结果返回到productList.jsp
页面中。
1 2 3 4 5 6 7
| <struts> <package name="product" extends="struts-default"> <action name="productList" class="com.example.ProductAction" method="list"> <result name="success">/WEB-INF/views/productList.jsp</result> </action> </package> </struts>
|
3.V层:配置Struts2的视图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Product List</title> </head> <body> <table> <thead> <tr> <th>ID</th> <th>Name</th> <th>Price</th> <th>Description</th> </tr> </thead> <tbody> <s:iterator value="productList"> <tr> <td><s:property value="id"/></td> <td><s:property value="name"/></td> <td><s:property value="price"/></td> <td><s:property value="description"/></td> </tr> </s:iterator> </tbody> </table> </body> </html>
|
1.基本思想
在servlet基本思想中,编写一个控制器,就要去web.xml中去注册,在SpringMVC中,使用dispatchservlet拦截所有
1 2 3 4 5 6 7 8
| <servlet> <servlet-name>loginout</servlet-name> <servlet-class>com.xiao.servlet.user.LogoutServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>loginout</servlet-name> <url-pattern>/jsp/logout.do</url-pattern> </servlet-mapping>
|
配置web.xml(拦截全部的请求) 配置springmvc.xml 编写controller(component-scan)
web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> </servlet>
<servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
|
springmvc.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?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">
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>
</beans>
|
1 2
| <mvc:annotation-driven /> 包含映射器、适配器 实验发现是必须要
|
编写controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 手动配置,这里的id就是访问的路径 <bean id="/helloserv" class="com.kuang.controller.Helloservlet"></bean>
或者 不可以同时配置
<!-- 注解扫描 --> <context:component-scan base-package="com.kuang.controller"/>
@Controller public class HelloServlet { @RequestMapping("/helloserv") public String hello(Model model){ model.addAttribute("msg","hello annotation"); return "hello"; } }
|
- 在 Controller 中,根据业务逻辑查询出需要显示的动态数据,并将其封装成一个 Model 对象。
- 将 Model 对象作为参数传递给模板引擎(根据返回值定位页面),通过 Thymeleaf 的表达式语言 ${} 将动态数据注入到 HTML 模板中。
- Thymeleaf 模板引擎会根据 HTML 模板中定义的逻辑和数据,生成渲染后的 HTML 页面,并将其返回给客户端浏览器。
- 客户端浏览器接收到 HTML 页面后,根据 HTML 标签和 CSS 样式渲染页面,并显示给用户。
想访问一个商品列表页面:
- controller定义toList接口,
- 加载数据到model里,return “toList”跳转到toList.html,thymeleaf会自动渲染数据进入页面对应的${}
2.跳转
servlet
- forward 请求转发 地址栏不变,获得商品列表后转发到商品界面
- redirect 重定向
controller -> 页面
- 默认返回就是forward
- 重定向return “redirect:/index.jsp” 不经过视图解析器
controller -> controller
- return “forward:/path”
- return “redirect:/path”
3.参数接受
vo:专门用来传值的对象
struts2:成员变量接收参数 多例
springmvc:
@RequestBody 反序列化 @ResponseBody 序列化成json
1 2 3 4 5 6 7 8 9 10
| 局部变量,无线程安全问题,单例
@RequestMapping("/test2/{pageNo}“) @PathVariable int pageNo 将URL中的占位符参数绑定到控制器处理方法的入参 @RequestParam String name Url Form表 User user url中自动对应
@RequestBody User user Body中raw格式下的json参数
|
前端可以混用,一个在params,一个在data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @RequestParam String resourceId, @RequestParam String examId, @RequestBody List<UpdateExamAnswer> examAnswerList, @RequestParam(value = "writeType", defaultValue = "0") int writeType
return request({ url: BASE_URL + '/submit_all_save', method: 'post', params: { resourceId, examId, writeType }, data: questionRes })
|
此外,以上默认post为application/json
格式发送接受数据
application/x-www-form-urlencoded
前端URLSearchParams或Qs.Stringify(data) 后端@RequestParam或不加
1 2 3 4 5 6 7 8
| 数据格式:loginName=lst&password=1
百分号编码: 丁 十六进制下是0xE4B881占3字节 转成字符串‘E4B881’,占六字节 每两个字节前加上百分号前缀,得到字符串“%E4%B8%81”,占九个字节(十六进制下是0x244534254238253831) 把这九个字节拼接到数据包里,这样就可以传输“非ascii字符的 utf8编码的 十六进制表示的 字符串的 百分号形式”
|
3.multipart/form-data
前端FormData格式,后端@RequestParam或不加
4.返回参数:
request(单次请求) session(浏览器) application(全体用户共享)
1 2 3 4 5 6 7
| forward跳转 Model model 对request的封装,作用一样 model.addAttribute("msg","hello annotation"); 取出:${requestScope.msg} redirect 1.地址栏拼接 2.session req.getSession.setAttribute
|
5.拦截器
javaweb:filter过滤器,可以拦截一切资源。springmvc只能拦截controller
编写拦截器类,再注册:注入bean,定义拦截的地方。(或者定义和拦截写在一起)
这里继承HandlerInterceptor,有处理前,(controller)处理后,清理后
AOP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public class JWTInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if ("OPTIONS".equals(request.getMethod())) { return true; }
String token = request.getHeader("token"); HashMap<String, Object> map = new HashMap<>(); if(token == null){ map.put("msg","未携带token"); }else{ try{ JWTUtils.verity(token); return true; }catch (SignatureVerificationException e){ e.printStackTrace(); map.put("msg","无效签名"); }catch (TokenExpiredException e){ e.printStackTrace(); map.put("msg","token过期"); }catch (AlgorithmMismatchException e){ e.printStackTrace(); map.put("msg","token算法不一致"); }catch (Exception e){ e.printStackTrace(); map.put("msg","token无效"); } }
map.put("code",500); map.put("data",null); String json = new ObjectMapper().writeValueAsString(map); response.setContentType("application/json;charset=UTF-8"); response.getWriter().println(json); return false; } }
|
1 2 3 4 5 6 7 8
| <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.kuang.config.JWTInterceptor"></bean> 或者分开 <ref bean = "beanname"> </mvc:interceptor > </mvc:interceptors>
|
6.异常处理
编写异常处理类,注册bean就行。可以根据不同的异常if判断处理不同逻辑
SSM
这里7.a scan可以只扫描service下的,因为mapper和controller都扫描了;mapper可以不使用注解(mapperscanconfig是和spring整合的;等价在springboot中使用了@Mapper或@MapperScan)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| <context:component-scan base-package="com.kuang.service"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>
<tx:annotation-driven transaction-manager="transactionManager"/> <context:property-placeholder location="classpath:database.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="maxPoolSize" value="30"/> <property name="minPoolSize" value="10"/> <property name="autoCommitOnClose" value="false"/> <property name="checkoutTimeout" value="10000"/> <property name="acquireRetryAttempts" value="2"/> </bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> </bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> <property name="basePackage" value="com.kuang.dao"/> </bean>
|
1.ab 让mvc在服务器启动时创建工厂(提供service Dao)。
实际项目中,可以把所有的文件整合到一起applicationContext,在servlet中配置
C:\Users\13000\Desktop\study\vue-spring\2.vue-spring\7.springmvc\0代码———————————-\ssmbuild
spring.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
|
<context:property-placeholder location="classpath:database.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="maxPoolSize" value="30"/> <property name="minPoolSize" value="10"/> <property name="autoCommitOnClose" value="false"/> <property name="checkoutTimeout" value="10000"/> <property name="acquireRetryAttempts" value="2"/> </bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> </bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> <property name="basePackage" value="com.kuang.dao"/> </bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven >
<context:component-scan base-package="com.kuang.service"/>
|
springmvc.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <context:component-scan base-package="com.kuang.controller"/>
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>
web.xml <servlet> <servlet-name>dispatchservlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatchservlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
|