Spring介绍
Spring实际上指的是Spring Framework
使用Spring可以让java Bean之间进行有效的解耦
IOC(Inversion of Control)中文控制反转
使用Spring之后我们可以将对象的创建、初始化和销毁等操作交给Spring容器来管理。如果其他Bean需要使用这个Bean,可以直接去Spring容器去要。
1.创建一个Maven工程
2.从https://mvnrepository.com/查询sprint-context
在pom.xml文件中添加
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.4</version>
</dependency>
</dependencies>
3.在resources文件下创建applicationContext文件
4.获取容器
applicationContext.xml
<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 java反射实现的 -->
<bean class="org.brills.model.User" id="user"></bean>
</beans>
Main.java
public static void main(String[] args) {
//绝对路径加载 FileSystemXmlApplicationContext ftx= new FileSystemXmlApplicationContext("G:\\ideaWork\\ioc01\\src\\main\\resources\\applicationContext.xml");
ClassPathXmlApplicationContext ctx= new ClassPathXmlApplicationContext("applicationContext.xml");
//User u=(User)ctx.getBean("user");
// User u = ctx.getBean(User.class);
User u = ctx.getBean("user",User.class);
System.out.println("username:"+u.getName());
}
属性注入
1.通过bean构造方法注入属性
<!--用户bean java反射实现的 构造方法注入-->
<bean class="org.brills.model.User" id="user">
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="name" value="垃圾"></constructor-arg>
<constructor-arg name="sex" value="男"></constructor-arg>
</bean>
2.set方法注入
<!--set方法注入-->
<bean class="org.brills.model.User" id="user2">
<property name="age" value="20"></property>
<property name="name" value="爸爸"></property>
<property name="sex" value="?"></property>
</bean>
3.p名称空间注入
<!--p空间注入-->
<bean class="org.brills.model.User" id="user3" p:name="啊哈" p:sex="女" p:age="14"></bean>
4.静态工厂注入
OkHttpStaticFactory.java
public class OkHttpStaticFactory {
private static OkHttpClient okHttpClient;
public static OkHttpClient getInstance(){
if(okHttpClient==null){
okHttpClient=new OkHttpClient.Builder().build();
}
return okHttpClient;
}
}
<!--静态工厂注入 -->
<bean class="org.brills.model.OkHttpStaticFactory" factory-method="getInstance" id="okHttpClient"></bean>
5.实例工厂注入
OkHttpFatcory.java
public class OkHttpFatcory {
private OkHttpClient okHttpClient;
public OkHttpClient getInstance(){
if(okHttpClient==null){
okHttpClient=new OkHttpClient.Builder().build();
}
return okHttpClient;
}
}
<!--动态工厂注入-->
<bean class="org.brills.model.OkHttpFatcory" id="okHttpFatcory"></bean>
<bean class="okhttp3.OkHttpClient" factory-bean="okHttpFatcory" factory-method="getInstance" id="okHttpClient2"></bean>
复杂属性注入
6.对象注入
<!--复杂属性注入-->
<bean class="org.brills.model.Cat" id="cat">
<property name="name" value="Tom"></property>
<property name="age" value="3"></property>
</bean>
<!--set方法注入-->
<bean class="org.brills.model.User" id="user2">
<property name="age" value="20"></property>
<property name="name" value="爸爸"></property>
<property name="sex" value="?"></property>
<property name="cat" ref="cat"></property>
</bean>
7.数组注入
<property name="cats">
<array>
<ref bean="cat"></ref>
<bean class="org.brills.model.Cat" >
<property name="name" value="Tom"></property>
<property name="age" value="3"></property>
</bean>
</array>
</property>
8.Map注入
<property name="details">
<map>
<entry key="gender" value="男"></entry>
<entry key="age" value="58"></entry>
</map>
</property>
9.Properties注入
<property name="info">
<props>
<prop key="age">89</prop>
<prop key="name">javaboy</prop>
</props>
</property>
10.列表注入
<property name="favorites">
<list>
<value>看书</value>
<value>画画</value>
</list>
</property>
java配置
使用java代码配置spring而不是xml文件
JavaConfig.java
//@Configuration注释表示这是一个java配置类,配置作用类似applicationContext.xml
@Configuration
public class JavaConfig {
@Bean
SayHello sayHello(){
return new SayHello();
}
}
Main.java
public static void main(String[] args) {
AnnotationConfigApplicationContext atx= new AnnotationConfigApplicationContext(JavaConfig.class);
SayHello sayHello= atx.getBean("sayHello",SayHello.class);
System.out.println( sayHello.sayHello());
也可以这样写
JavaConfig.java
//@Configuration注释表示这是一个java配置类,配置作用类似applicationContext.xml
@Configuration
public class JavaConfig {
@Bean("hl")
SayHello sayHello(){
return new SayHello();
}
}
Main.java
public static void main(String[] args) {
AnnotationConfigApplicationContext atx= new AnnotationConfigApplicationContext(JavaConfig.class);
SayHello sayHello= atx.getBean("hl",SayHello.class);
System.out.println( sayHello.sayHello());
}
自动扫描注入(自动化配置)
- @Component
- @Repository
- @Service
- @Controller
这四个中三个都是基于@Component做出来的。
JavaConfig.java
@Configuration
@ComponentScan(basePackages = "org.brills.service")//自动扫描该包下
public class JavaConfig {
@Bean("hl")
SayHello sayHello(){
return new SayHello();
}
}
UserService.java
@Service
public class UserService {
public User getUser(){
return new User("babba",12,'男');
}
}
Main.java
UserService us= atx.getBean(UserService.class);
System.out.println(us.getUser().getName());
根据注解扫描
@ComponentScan(basePackages = "org.brills.service",useDefaultFilters = false,includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Service.class)})
useDefaultFilters = false//关闭自动默认扫描
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Service.class)//设置自定义扫描,只扫描service
根据XML文件注解
<context:component-scan base-package="org.brills.service" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
对象注入
自动扫描时对象注入的三种方式
- @Autowired
- @Resources
- @Injected
UserDao.java
@Repository
public class UserDao {
public String hello(){
return "hello brillsDao";
}
}
UserService.java
@Service
public class UserService {
@Autowired
UserDao userDao;
public User getUser(){
System.out.println(userDao.hello());
return new User("babba",12,'男');
}
}
条件注解
案例根据系统是Windows还是Linux输出不同语句
ShowCmd.java接口
public interface ShowCmd {
String showCmd();
}
WindowsShowCmd.java
public class WindowsShowCmd implements ShowCmd{
public String showCmd() {
return "windows";
}
}
LinuxShowCmd.java
public class LinuxShowCmd implements ShowCmd{
public String showCmd() {
return "Linux";
}
}
windowCondition.java
public class WindowsCondition implements Condition {
//前一个是环境信息,后一个是Spring信息
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
String osName= conditionContext.getEnvironment().getProperty("os.name");
return osName.toLowerCase().contains("win");
}
}
LinuxConditition.java
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
String osName = conditionContext.getEnvironment().getProperty("os.name");
return osName.toLowerCase().contains("linux");
}
JavaConfig.java
@Configuration
public class JavaConfig {
@Bean("cmd")
@Conditional(WindowsCondition.class)
ShowCmd winCmd(){
return new WindowsShowCmd();
}
@Bean("cmd")
@Conditional(LinuxCondition.class)
ShowCmd LinuxCmd(){
return new LinuxShowCmd();
}
}
多环境切换
JavaConfig.java
//开发环境下ds的设置
@Bean
@Profile("dev")
DateSource devDs(){
DateSource ds=new DateSource();
ds.setUrl("jdbc://mysql:vhr");
ds.setPassword("123");
ds.setUsername("root");
return ds;
}
//产品环境下ds的设置
@Bean
@Profile("prod")
DateSource prodDs(){
DateSource ds=new DateSource();
ds.setUrl("jdbc://mysql://192.168.23.56:3306//vhr");
ds.setPassword("dawdasdzfzf");
ds.setUsername("root");
return ds;
}
Main.java
public static void main(String[] args) {
AnnotationConfigApplicationContext atx =new AnnotationConfigApplicationContext();
atx.getEnvironment().setActiveProfiles("dev");
atx.register(JavaConfig.class);
atx.refresh();
DateSource ds=atx.getBean(DateSource.class);
System.out.println(ds.getUrl());
}
xml配置
applcationContext.xml
<?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 profile="dev">
<bean class="org.brills.ioc.DateSource" id="devDs">
<property name="password" value="1234"></property>
<property name="url" value="jdbc://mysql:vhr"></property>
<property name="username" value="root"></property>
</bean>
</beans>
<beans profile="prod">
<bean class="org.brills.ioc.DateSource" id="prodDs">
<property name="password" value="dwadasfza"></property>
<property name="url" value="jdbc://mysql://192.168.23.56:3306//vhr"></property>
<property name="username" value="root"></property>
</bean>
</beans>
</beans>
Main.java
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext();
ctx.getEnvironment().setActiveProfiles("prod");
ctx.setConfigLocation("applicationContext.xml");
ctx.refresh();
DateSource ds=ctx.getBean(DateSource.class);
System.out.println(ds.getUrl());
其他
Bean的作用域
手动配置,每次生成不同的bean,不是只返回一个bean(单例)
<bean class="org.brills.ioc.DateSource" id="devDs" scope="prototype">
也可以使用注解
@ Scope("prototype")
id和name区别
id不支持多个值,name支持多个,中间用,隔开。
混合配置
@Configuration
@ImportResource("classpath:applicationContext.xml")
public class JavaConfig {
}
Aware接口
@Service
@PropertySource(value = "javaboy.properties")
public class AwareService implements BeanNameAware, BeanFactoryAware, ResourceLoaderAware, EnvironmentAware {
private String beanName;
private ResourceLoader resourceLoader;
private Environment environment;
//获取生成工厂
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
}
//获取bean名字
@Override
public void setBeanName(String s) {
this.beanName=s;
}
//获得环境信息
@Override
public void setEnvironment(Environment environment) {
this.environment=environment;
}
//获得
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader=resourceLoader;
}
public void output() throws IOException {
System.out.println(beanName);
Resource resource=resourceLoader.getResource("javaboy.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream()));
String s = br.readLine();
System.out.println(s);
br.close();
String property = environment.getProperty("javaboy.address");
System.out.println(property);
}
}
Aop(Aspect Oriented Programming)面向切面编程
- 切点 要添加代码的地方
- 通知(增强)通知就是向切点动态添加的代码
- 切面 切点+通知
- 连接点 切点的定义
基于JDK动态代理Aop效果
MyCalculator.java接口
public interface MyCalculator {
int add(int a,int b);
}
MyCalculatorImpl.java
public class MyCalculatorImpl implements MyCalculator{
@Override
public int add(int a, int b) {
return (a+b);
}
}
CalculatorProxy.java
public class CalculatorProxy {
public static Object getInstance(MyCalculatorImpl myCalculator){
return Proxy.newProxyInstance(CalculatorProxy.class.getClassLoader(), myCalculator.getClass().getInterfaces(), new InvocationHandler() {
/**
*
* @param proxy 代理对象
* @param method 代理的方法
* @param args 方法的参数
* @return 方法的返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName()+"方法开始执行力");
Object invoke =method.invoke(myCalculator,args);
System.out.println("方法结束了");
return invoke;
}
});
}
}
Main.java
public class Main {
public static void main(String[] args) {
MyCalculatorImpl myCalculator=new MyCalculatorImpl();
MyCalculator calculator=(MyCalculator) CalculatorProxy.getInstance(myCalculator);
int add=calculator.add(3,3);
System.out.println("add="+add);
}
}
Spring中的Aop
注解方式(不常用)
Action.java
//使用范围是方法
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)//运行时候还要存在
public @interface Action {
}
MyCalculator.java
public interface MyCalculator {
int add(int a,int b);
void min(int a,int b);
}
MyCalculatorImpl.java
@Component
public class MyCalculatorImpl implements MyCalculator{
@Action
public int add(int a, int b) {
return a+b;
}
@Override
public void min(int a, int b) {
System.out.println(a-b);
}
}
LogAspect.java
@Component
//表示这是一个切面
@Aspect
public class LogAspect {
//前置通知
@Before("@annotation(Action)")
public void before(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
System.out.println("方法名:"+name);
}
}
JavaConfig.java
@Configuration
@ComponentScan
//开启自动代理
@EnableAspectJAutoProxy
public class JavaConfig {
}
Main.java
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext atx=new AnnotationConfigApplicationContext(JavaConfig.class);
MyCalculator c= atx.getBean(MyCalculator.class);
System.out.println("1+2=" + c.add(1,2));
}
}
五种通知
- @Before
- @After
- @AfterReturning返回通知
@AfterReturning(value = "@annotation(Action)",returning = "r")
public void returing(JoinPoint joinPoint,Integer r){
System.out.println("返回值是"+r);
}
- @AfterThrowing异常通知
@AfterThrowing(value = "@annotation(Action)",throwing = "r")
public void afterThrowing(JoinPoint joinPoint,Exception e){
System.out.println("异常是"+e.getMessage());
}
- @Around环绕通知
@Around(value = "@annotation(Action)")
public Object around(ProceedingJoinPoint pjp){
//这个类似method.invoke()
Object proceed= pjp.proceed(new Object[]{5,5});
以上的内容可以优化
@Pointcut("@annotation(Action)")
public void poitcut(){
}
//前置通知
@Before("poitcut()()")
public void before(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
System.out.println("方法名:"+name);
}
非入侵式定义切点
@Pointcut("execution(org.brills.aop.*.*(..)")
public void before(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
System.out.println("方法名:"+name);
}
XML配置Aop
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean class="org.brills.LogAspect" name="logAspect"></bean>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* org.brills.*.*(..))"/>
<aop:aspect ref="logAspect">
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"></aop:after-throwing>
</aop:aspect>
</aop:config>
<bean class="org.brills.MyCalulatorIml" name="myCalulatorIml"></bean>
</beans>
pom.xml
<dependencies>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.3</version>
</dependency>
</dependencies>
SpringMVC
- 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。
- HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。
- HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。
- HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
- HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
- Handler让具体的Controller执行。
- Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
- HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
- DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
- 视图解析器将解析的逻辑视图名传给DispatcherServlet。
- DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。最终视图呈现给用户。
添加web.xml
配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--注册servlet-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--初始化指定springMVC配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--启动顺序,数字越少,启动越早-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--所有请求都会被springMVC拦截-->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
配置springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--自动扫包,由IOC容器统一管理-->
<context:component-scan base-package="com.brills.controller"></context:component-scan>
<!--让SpringMVC不处理静态资源.css .js .html .mp3 .mp4-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<!--mvc注解驱动-->
<mvc:annotation-driven></mvc:annotation-driven>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"></property>
<!--后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
编写HelloController.java
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(Model model){
//封装数据
model.addAttribute("msg","这是后端发送的消息");
return "hello";//会被视图解析器解析
}
}
如果使用@RestController就不会被视图解析器解析,直接返回字符串
<mvc:annotation-driven></mvc:annotation-driven>
简化了
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
RestFul风格
HelloController.java
@Controller
public class HelloController {
@RequestMapping("/hello/{msg}/{name}")
public String hello(@PathVariable String msg,@PathVariable String name, Model model){
//封装数据
model.addAttribute("msg",name+msg);
return "hello";//会被视图解析器解析
}
}
- @PostMapping
- @RequestMapping
- @GetMapping
重定向和转发
转发
return "forward:/WEB-INF/jsp/test.jsp"
有视图解析器后直接return “test”
重定向(地址会变化)
return "redirect:/index.jsp
接收请求参数
public String hi(@RequestParam("msg") String msg,Model model){
传输对象(要求参数必须一致)
@GetMapping("/hu")
public String hi(User user, Model model){
model.addAttribute("msg",user.toString());
return "hello";
}
- LinkedHashMap
- ModeMap继承了LinkeMap
- ModelAndView可以在储存数据的同时,返回逻辑视图
- Model只有几个方法适合用于储存
乱码问题解决
在web.xml中配置乱码过滤器
<!--配置SpringMVC中的乱码过滤器-->
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
JSON
Fastjson
@Controller
public class UserController {
@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")//解决json乱码问题
@ResponseBody //他就不会走视图解析器,会直接返回一个字符串
public String json1() throws JsonProcessingException {
User u=new User();
u.setId(123);
u.setName("哈哈哈");
ObjectMapper mapper =new ObjectMapper();
String str= mapper.writeValueAsString(u);
return str;
}
}
也可以在springmvc.xml里面配置json乱码问题
<!--JSON乱码问题配置-->
<!--mvc注解驱动-->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"></constructor-arg>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"></property>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
输出时间,修改时间格式
@RequestMapping("/j2")
@ResponseBody //他就不会走视图解析器,会直接返回一个字符串
public String json2() throws JsonProcessingException {
Date date=new Date();
SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yy-MM-dd");
ObjectMapper mapper =new ObjectMapper();
mapper.setDateFormat(simpleDateFormat);
return mapper.writeValueAsString(date);
}
FastJson
@RequestMapping("/j3")
@ResponseBody //他就不会走视图解析器,会直接返回一个字符串
public String json3() throws JsonProcessingException {
User u=new User();
u.setId(123);
u.setName("哈哈哈");
return JSON.toJSONString(u);
}
@RequestMapping("/j4")
@ResponseBody //他就不会走视图解析器,会直接返回一个字符串
public String json4() throws JsonProcessingException {
Date date =new Date();
return JSON.toJSONStringWithDateFormat(date,"yyyy-MM-dd");
}
- JSON.toJSONString()//java对象转JSON字符串
- JSON.parseObject(str,User.class)//json字符串转Java对象
- (JSONObject)JSON.toJSON(user)//java对象转JSON对象
- JSON.toJavaObject(jsonObject,User.class)//json对象转java对象
Mbatis
引入依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
编写mybatis-config.xml
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/study?serverTimezone=GMT"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/brills/dao/UserMapper.xml"></mapper>
</mappers>
</configuration>
编写MybatisUtils工具类
public class MyBatisUtils {
private static SqlSessionFactory sqlSessionFactory=null;
static {
String resource = "mybatis-config.xml";
try {
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取sqlsession
public static SqlSession getSqlSession(){
SqlSession sqlSession = sqlSessionFactory.openSession();
return sqlSession;
}
}
编写UserMapper.xml
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--绑定一个对应的接口-->
<mapper namespace="com.brills.dao.UserDao">
<select id="getUserList" resultType="com.brills.pojo.User">
select * from t_user
</select>
</mapper>
编写测试方法
@Test
public void test(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
UserDao userDao =sqlSession.getMapper(UserDao.class);
List<User> userList=userDao.getUserList();
for (User u : userList){
System.out.println(u);
}
sqlSession.close();
}
注意,如果报Type interface com.brills.dao.UserDao is not known to the MapperRegistry.错误,就是xml配置中没有mappers
解决maven资源过滤问题在pom.xml文件添加
<!--maven资源过滤解决-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
CRUD增删改查
- id:就是对于namespace中的方法
- resultType:sql语句执行的返回值
- parameterType:参数类型
<!--绑定一个对应的接口-->
<mapper namespace="com.brills.dao.UserDao">
<select id="getUserList" resultType="com.brills.pojo.User">
select * from t_user
</select>
<insert id="addUser" parameterType="com.brills.pojo.User">
insert into t_user(uid,uname) values(#{uid},#{uname})
</insert>
<select id="getUser" resultType="com.brills.pojo.User">
select * from t_user where uid=#{uid}
</select>
<update id="updateUser" parameterType="com.brills.pojo.User" >
update t_user set uid=#{uid},uname=#{uname} where uid=#{uid}
</update>
<delete id="deleteUser">
delete from t_user where uid =#{uid}
</delete>
</mapper>
增删改最后要提交事务sqlSession.commit();
Map传输储存
UserMapper.xml
<insert id="addUser2" parameterType="map">
insert into t_user (uid,uname) values(#{uid},#{uname})
</insert>
UserDao.java
int addUser2(Map<String,Object> map);
UserDaoTest.java
Map<String,Object> map =new HashMap<>();
map.put("uid",1553);
map.put("uname","Map储存");
userDao.addUser2(map);
- Map传输参数,直接在sql中取出key即可!【parameterType= “map”】
- 对象传输参数,直接在sql中取出对象的属性即可【parameterType=“Object”】
- 只有一个基本类参数的情况下,可以直接在sql中取到!
- 多个参数用Map,或者注解
配置解析
环境配置(environments)
MyBatis 可以配置成适应多种环境,但每个 SqlSessionFactory 实例只能选择一种环境。
事务管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):
JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。例如:
数据源(dataSource)
- UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序。
- POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。
- JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。
属性(properties)
首先编写db.properties文件储存配置
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/study?serverTimezone=GMT
username=root
password=123456
其次在mybaties-config.xml中引入
<properties resource="db.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<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>
也可以在其中增加一些属性配置,优先使用外部配置
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
类型别名(typeAliases)
可以为java写一个缩写,仅限xml配置中
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
也可以指定一个包名,Mybatis会在包名下扫描Java Bean
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
也可以注解修改别名
@Alias("author")
public class Author {
...
}
设置(settings)
设置名 | 描述 |
---|---|
cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 true /false |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。true /false |
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
plugins插件
- mybatis-generator-core
- mybatis-plus
- 通用mapper
映射器
- 配置相对路径资源引用
<mapper resource="com/brills/dao/UserMapper.xml"></mapper>
- 使用映射器接口实现类
<mapper class="com.brills.dao.UserDao"></mapper>
- 将包内映射器接口实现全部注册为映射器
<package name="com.brills.dao"/>
接口和配置文件必须同名在同一个包下
生命周期
SqlSessionFactoryBuilder//一旦创建就不需要它
SqlSessionFactory//数据库连接池,一旦创建就一直存在
SqlSession//连接到连接池的一个请求,线程不是安全的所以不能共享,用完关闭避免资源被占用
Mapper//代表具体的一个业务
ResultMap解决属性名和字段名不一致的问题
- 起别名
select uid as id from t_user
- 结果集映射
<resultMap id="UserMap" type="User">
<result column="uid" property="id" ></result>
</resultMap>
日志工厂
- SLF4J
- Apache Commons Logging
- Log4j 2
- Log4j(掌握)
- JDK logging
- STDOUT_LOGGING(掌握)
在mybaties配置文件中设置
<configuration>
<settings>
...
<setting name="logImpl" value="LOG4J"/>
...
</settings>
</configuration>
log4j
导入依赖
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
在resources中创建log4j.properties文件
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=【%c】-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/logging.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=【%p】【%d{yy-MM-dd}】【%c】%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
log4j的使用
static Logger logger = Logger.getLogger(UserDaoTest.class);
logger.info("这是提示信息");
logger.debug("这是测试信息");
logger.error("这是错误信息");
分页插件MyBatis分页插件PageHelper
使用注解开发
需要绑定接口<mapper class="com.brills.work.dao.UserDao"></mapper>
//底层主要运用反射
@Select("select * from t_user")
List<User> getUsers() ;
//方法存在多个参数
@Select("select * from t_user" where id=#{id})
List<User> getUsers(@Param("id") int id) ;
@Insert(“insert into user(id,name,pwd) values (#{id},#{name},#{password})”)
int addUser(User user);
@Update("update user set name = #{name},pwd=#{password} where id =#{id}")
int updateUser(User user);
@Delete("Delete from user where id =#{id}")
int deleteUser(@Param("uid" int id));
使用注解来映射简单语句,会使得代码显得更加简洁,相对于一些复杂的语句,java显得力不从心。如果需要完成很复杂的查询,最好使用XML映射语句
设置自动提交SqlSession sqlSession = sqlSessionFactory.openSession(true);
复杂查询环境
多表查询举例
mysql> select u.uname '名字' , g.num '成绩' from t_user u,t_grade g where u.uid = g.gid;
在User实体类中增加Grade属性
//新增成绩
private Grade grade;
修改UserMapper.xml
<select id="getUserGradeList" resultMap="UserGrade">
select u.uid , u.uname , g.num from t_user u,t_grade g where u.uid = g.gid
</select>
<resultMap id="UserGrade" type="com.brills.pojo.User">
<result property="uid" column="uid"></result>
<result property="uname" column="uname"></result>
<!--复杂属性需要单独处理, 对象 association 集合 collection -->
<association property="grade" javaType="com.brills.pojo.Grade">
<result property="gid" column="uid"></result>
<result property="num" column="num"></result>
</association>
</resultMap>
查询结果:
User{uid=10, uname='前端', grade=Grade{gid=10, num=98}}
User{uid=1553, uname='Map储存', grade=Grade{gid=1553, num=125}}
多对一查询
查询每个老师带领的学生们
<select id="getTeacher" resultMap="TeacherStudent">
select s.id sid, s.name sname , t.id tid, t.name tname from student s, teacher t where s.tid = t.id
</select>
<resultMap id="TeacherStudent" type="com.brills.pojo.Teacher">
<result property="id" column="tid"></result>
<result property="name" column="tname"></result>
<!--复杂属性需要单独处理, 对象 association 集合 collection
javaType="" 指定属性的类型
集合中泛型信息,我们使用ofType获取
-->
<collection property="students" ofType="com.brills.pojo.Student">
<result property="id" column="sid"></result>
<result property="name" column="sname"></result>
</collection>
</resultMap>
动态SQL
- if
- choose(when , otherwise)
- trim(where , set)
- foreach
创建一个表
create table blog (
id varchar(50) not null comment '博客id',
title varchar(100) not null comment '博客标题',
author varchar(30) not null comment '博客作者',
create_time datetime not null comment '创建时间',
views int(30) not null comment '浏览量'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
创建一个实体类
public class Blog {
private String id;
private String title;
private String author;
private Date createTime;
private int views;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public int getViews() {
return views;
}
public void setViews(int views) {
this.views = views;
}
}
创建id生成工具类
@SuppressWarnings("all") //抑制警告
public class IDutills {
public static String getId(){
return UUID.randomUUID().toString().replaceAll("-","");
}
}
因为数据库中create_time对应实体类中的createTime,不能够直接映射,所以需要在mybatis-config.xml配置中添加驼峰命名模式映射
<settings>
<!-- 是否开启驼峰命名模式 映射 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
if标签
BlogMapper.xml
<select id="queryBlogIF" parameterType="map" resultType="com.brills.pojo.Blog">
select * from blog where title like '%${title}%'
<if test="author !=null">
and author =#{author}
</if>
</select>
Test方法
@Test
public void queryBlogIF(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
BlogDao blogDao = sqlSession.getMapper(BlogDao.class);
HashMap<String,String> map = new HashMap<>();
map.put("title","不");
map.put("author","彬彬");
List<Blog> blogList=blogDao.queryBlogIF(map);
for(Blog bl:blogList){
System.out.println(bl);
}
sqlSession.close();
}
chose标签
<select id="queryBlogChose" parameterType="map" resultType="com.brills.pojo.Blog">
select * from blog where title like '%${title}%'
<choose>
<when test="author != null">
AND author like '%${author}%'
</when>
<when test="views != null">
AND views = #{views}
</when>
<otherwise>
AND views = 7
</otherwise>
</choose>
</select>
Where标签
<select id="queryBlogWhere" parameterType="map" resultType="com.brills.pojo.Blog">
select * from blog
<where>
<if test="title !=null">
title like '%${title}%'
</if>
<if test="author !=null">
and author =#{author}
</if>
<if test="views !=null">
and views =#{views}
</if>
</where>
</select>
set标签
<update id="updateBlog" parameterType="map" >
update blog
<set>
<if test="title !=null">
title = #{title},
</if>
<if test="author !=null">
author = #{author},
</if>
<if test="views !=null">
views = #{views}
</if>
</set>
where id =#{id}
</update>
foreach 标签
<select id="queryBlogIn" resultType="com.brills.pojo.Blog">
select * from blog where id in
<foreach item="id" index="index" collection="list"
open="(" separator="," close=")">
#{id}
</foreach>
</select>
运行效果
Preparing: select * from blog where id in ( ? , ? )
也可以用map当参数传入list参数(map中必须存一个键值为list的列表)
<select id="queryBlogIn" resultType="com.brills.pojo.Blog" parameterType ="map">
select * from blog where id in
<foreach item="id" index="index" collection="list"
open="(" separator="," close=")">
#{id}
</foreach>
</select>
Mybatis缓存
用户将查询到数据不用在磁盘上查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题
Memcache 服务器实现三方面:Memcache内存缓存技术、静态化技术、mysql优化
减少和数据库交互的次数,减少系统开销,提高系统效率。
mybatis中定义了两级缓存:一级缓存和二级缓存
- 默认情况下,只有一级缓存开启。(SqlSession级别的呼延村,也成为本地缓存)
- 二级缓存需要手动开启和配置,它是基于namespace级别的缓存。
- 为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存
缓存失效情况
- 查询不同的东西
- 增删改操作,可能改变原来的数据,所以必定会刷新缓存
- 查询不同的Mapper.xml
- 手动清理缓存
sqlSession.clearCache();
二级缓存
在mapper.xml文件中加
<cache/>
1.首先开启全局缓存
<settings>
<!--开启全局缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
配置标签也可以这样详细设计
<cache eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true">
</cache>
2.将实体类实现序列化
public class Blog implements Serializable
自定义缓存-ehcache
SSM整合
1.导入依赖
<!--依赖: junit :数据库驱动,连接池,servlet,jsp,mybatis,mybattis-spring-->
<dependencies>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.9</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.9</version>
</dependency>
</dependencies>
2.maven资源过滤设置
<!--maven资源过滤解决-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
3.创建包
写实体类、dao层和service层
例:
public class UserServiceImpl {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
List<User> getUserList() {
return userDao.getUserList();
}
void addUser(User user) {
userDao.addUser(user);
}
User getUser(int uid) {
return userDao.getUser(uid);
}
void updateUser(User user) {
userDao.updateUser(user);
}
void deleteUser(int uid) {
userDao.deleteUser(uid);
}
int addUser2(Map<String,Object> map){
return userDao.addUser2(map);
}
List<User> getUserGradeList(){
return userDao.getUserGradeList();
}
}
4.配置
1.db.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/study?serverTimezone=GMT
jdbc.username=root
jdbc.password=123456
2.applicationContext.xml
<?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">
<import resource="spring-dao.xml"></import>
<import resource="spring-service.xml"></import>
<import resource="spring-mvc.xml"></import>
</beans>
3.mybatis-config.xml
<?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>
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
<!--配置数据源,交给Spring(让他们自己起别名)-->
<typeAliases>
<package name="com.brills.pojo"/>
</typeAliases>
<mappers>
<mapper resource="com/brills/dao/UserMapper.xml"></mapper>
<mapper resource="com/brills/dao/BlogMapper.xml"></mapper>
</mappers>
</configuration>
4.spring-dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.关联数据库配置文件-->
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!--2.连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--3.sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:mybatis-config.xml" />
</bean>
<!--配置dao接口扫描包,动态实现Dao接口可以注入到Spring容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--扫描dao包-->
<property name="basePackage" value="com.brills.dao"/>
</bean>
</beans>
5.spring-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--扫描service下的包-->
<context:component-scan base-package="com.brills.service"></context:component-scan>
<!--2.将所有的业务类,注入到spring,可以通过配置或者注解实现-->
<bean id="UserServiceImpl" class="com.brills.service.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<!--声明式事务配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--4.aop事务支持-->
</beans>
6.添加web支持
7.springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--1.注解驱动-->
<mvc:annotation-driven/>
<!--2.静态资源过滤-->
<mvc:default-servlet-handler/>
<!--3.扫描包:controller-->
<context:component-scan base-package="com.brills.controller"/>
<!--4.视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF"></property>
<property name="suffix" value=".html"></property>
</bean>
</beans>
8.拦截器
创建MyInterceptor
public class MyInterceptor implements HandlerInterceptor {
//处理前
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// System.out.println("拦截器已经运行");
// request.getRequestDispatcher("/WEB-INF/").forward(request,response);
return true;
}
//处理后
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
//清理
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
同时修改spring.xml文件添加如下代码
<!--拦截器配置-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.brills.config.MyInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
文件上传和下载
pom.xml中加入需要的依赖
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
在SpringMVC中注入文件上传配置
<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--请求的编码格式,必须和pageEncoding属性一致,默认为ISO-8859-1-->
<property name="defaultEncoding" value="utf-8"></property>
<!--上传文件大小上线,单位为字节(10485760=10m)-->
<property name="maxUploadSize" value="10485760"></property>
<property name="maxInMemorySize" value="40960"></property>
</bean>
在File.html中加入前端代码实现上传下载
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;">
<legend>拖拽上传</legend>
</fieldset>
<div class="layui-upload-drag" id="file">
<i class="layui-icon">🧑💻</i>
<p>点击上传,或将文件拖拽到此处</p>
<div class="layui-hide" id="uploadDemoView">
<hr>
<img src="" alt="上传成功后渲染" style="max-width: 196px">
</div>
</div>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;">
<legend>下载文件</legend>
</fieldset>
<div class="layui-btn-container" >
<a href="/SSM/file/download"><button type="button" class="layui-btn layui-btn-normal layui-btn-radius">下载按钮</button></a>
</div>
<script>
layui.use(['upload', 'layer'], function(){
var $ = layui.jquery
,upload = layui.upload
,layer = layui.layer;
//拖拽上传
upload.render({
elem: '#file'
,url: '/SSM/file/upload' //此处用的是第三方的 http 请求演示,实际使用时改成您自己的上传接口即可。
,done: function(res){
layer.msg(res.msg);
layui.$('#uploadDemoView').removeClass('layui-hide').find('img').attr('src', res.file);
console.log(res)
console.log("上传执行完成")
}
});
});
</script>
在FileController中添加代码实现文件上传下载
public class FileUpState{
int code;
String msg;
Map<String,String> data;
String file;
@Override
public String toString() {
return "FileUpState{" +
"code=" + code +
", msg='" + msg + '\'' +
", data=" + data +
", file='" + file + '\'' +
'}';
}
public String getFile() {
return file;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
public Map<String, String> getData() {
return data;
}
public FileUpState(int code, String msg, Map<String, String> data, String file) {
this.code = code;
this.msg = msg;
this.data = data;
this.file = file;
}
}
@RequestMapping("/index")
public String fileIndex(Model model){
return "file";
}
//批量上传CommonsMultipartFile为数组即可
@ResponseBody
@RequestMapping("/upload")
public String fileUpload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request)throws IOException {
//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
//通过CommonsMultipartFile的方法直接写文件
file.transferTo(new File(realPath+"/"+file.getOriginalFilename()));
System.out.println("上传成功");
Map<String,String> map =new HashMap<>();
map.put("src","www.baidu.com");
FileUpState fileUpState =new FileUpState(0,"你干的漂亮,崽种!",map,"http://localhost:8080/SSM/upload/"+file.getOriginalFilename());
System.out.println(JSON.toJSONString(fileUpState));
return JSON.toJSONString(fileUpState);
}
@RequestMapping("/download")
public String fileDownload(HttpServletRequest request, HttpServletResponse response)throws IOException {
String path = request.getServletContext().getRealPath("/upload");
String fileName = "a.jpg";
//1、设置response 响应头
response.reset(); //设置页面不缓存,清空buffer
response.setCharacterEncoding("UTF-8"); //字符编码
response.setContentType("multipart/form-data"); //二进制传输数据
//设置响应头
response.setHeader("Content-Disposition",
"attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));
File file = new File(path,fileName);
//2、 读取文件--输入流
InputStream input=new FileInputStream(file);
//3、 写出文件--输出流
OutputStream out = response.getOutputStream();
byte[] buff =new byte[1024];
int index=0;
//4、执行 写出操作
while((index= input.read(buff))!= -1){
out.write(buff, 0, index);
out.flush();
}
out.close();
input.close();
return null;
}