进程:一个程序,各种资源分配好放到内存中叫进程,进程是资源分配的基本单位
线程:程序开始之后之后,各种不同的执行路径,同时开始并行运行,是运行的基本单位;
线程切换/上下文切换:执行某个线程时,存储做计算的寄存器存放该线程的数据,pc记录执行到哪,然后切换另一个线程
Spring 解决的是业务层与各层之间的松耦合问题
控制反转 --帮助我们创建对象
依赖注入--给全局的属性或者对象进行赋值操作
面向切面--提升代码的扩展与功能
声明事务--事务管理
mybatis解决的层之间的松耦合的问题
为什么要引入接口,在软件设计中最难处理的就是需求的复杂变化,需求的复杂变化更对体现在具体的实现上,我们变成如果围绕具体实现来展开就会陷入更加复杂变化的汪洋中,软件也就不能最终实现。我们必修围绕某种稳定东西展开,以静制动,实现规范的高质量项目。接口就是规范,是项目中最为稳定的核心,面向接口编程而不是面向实现编程,可以大大降低程序模块之间的耦合性,提高整个系统的可扩展性和可维护性。另外,java是一种单继承多实现的语言,接口可以提供多继承的大多数好处,同时还能避免多继承的复杂行和低效性。
上图中接口规范了controller层中B类中的oo方法实现;但是却不能解决B类的更改问题,如果我们想在controller中不把B类改变为C类,但是controller层中可能有很多B类需要要更改,可见使用接口的方式仍然不能解决耦合问题,因此spring框架为我们提供了IOC容器的方式,因此我们用不自己创建对象,而是将创建对象的任务交给spring,spring通过需要在spring配置文件总配置相应的bean,以及设置相关的属性,通过反射的机制,让 spring容器来生成类的实例对象以及管理对象
控制反转
控制:创建对象的过程
反转:从开发者手动创建对象转变为spring自己创建对象
Spring创建对象的三种方法
1.无参构造器
//(1)传统方式:创建类,构建有参函数
public class Orders {
//属性
private String oname;
private String address;
}
<!--1 配置User对象创建-->
<bean id="user" class="com.atguigu.spring5.User"></bean>
2.有参构造
//(1)传统方式:创建类,构建有参函数
public class Orders {
//属性
private String oname;
private String address;
//有参数构造
public Orders(String oname,String address) {
this.oname = oname;
this.address = address;
}
}
<!--(2)spring方式:有参数构造注入属性-->
<bean id="orders" class="com.atguigu.spring5.Orders">
<constructor-arg name="oname" value="Hello"></constructor-arg>
<constructor-arg name="address" value="China!"></constructor-arg>
</bean>
无法辨认精确的构造是 ,要指定index (按顺序来)
或type=“Java.lang.String” 注意:基本类型直接写,引用类型要写全路径
3.工厂模式
设计模式:解决某种特定问题的代码解决方案
工厂设计模式的好处:之前我们创建对象是直接创建的,现在交给工厂统一处理
依赖注入三种实现方式:
1.有参构造
2.set方法注入
3.自动注入
bean的作用域
spring 每个对象默认都是单例的(有效范围 :同哟个bean 标签)
Scope属性可取值:
singleton:默认值单例的,使用ApplicationContext启动加载配置文件时实例化对象
prototype:原型,每次调用时实例化
另外 还有request 和 session
bean生命周期
(1)通过构造器创建 bean 实例(无参数构造)
(2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
(3)把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
(4)调用 bean 的初始化的方法(需要进行配置初始化的方法)
(5)把 bean 实例传递 bean 后置处理器的方法 postProcessAfterInitialization
(6)bean 可以使用了(对象获取到了)
(7)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法
注解
1、什么是注解
(1)注解是代码特殊标记,格式:@注解名称(属性名称=属性值, 属性名称=属性值…)
(2)使用注解,注解作用在类上面,方法上面,属性上面
(3)使用注解目的:简化 xml 配置
2.Spring针对Bean管理中创建对象提供注解
1.@Compment 普通类
2.Service 用于业务逻辑层
3.Controller 用于控制层
4.@Repository 用于Dao层
上面的四个注解功能一样,都是用来创建对象的
3.基于注解方式实现对象
第一步 引入依赖 (引入spring-aop jar包)
第二步 开启组件扫描
<!--开启组件扫描
1 如果扫描多个包,多个包使用逗号隔开
2 扫描包上层目录
-->
<context:component-scan base-package="com.atguigu"></context:component-scan>
第三步 创建类,在类上面添加创建对象注解
//在注解里面 value 属性值可以省略不写,
//默认值是类名称,首字母小写
//UserService -- userService
@Component(value = "userService") //注解等同于XML配置文件:<bean id="userService" class=".."/>
public class UserService {
public void add() {
System.out.println("service add.......");
}
}
4.开启组件细节扫描配置
<!--示例 1
use-default-filters="false" 表示现在不使用默认 filter,自己配置 filter
context:include-filter ,设置扫描哪些内容
-->
<context:component-scan base-package="com.atguigu" use-defaultfilters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--代表只扫描Controller注解的类-->
<!--示例 2
下面配置扫描包所有内容
context:exclude-filter: 设置哪些内容不进行扫描
-->
<context:component-scan base-package="com.atguigu">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/><!--表示Controller注解的类之外一切都进行扫描-->
</context:component-scan>
5.基于注解方式实现属性注入
(1)@AutoWired 根据属性类型进行自动装配
第一步 把 service 和 dao 对象创建,在 service 和 dao 类添加创建对象注解
第二步 在 service 注入 dao 对象,在 service 类添加 dao 类型属性,在属性上面使用注解
@Service
public class UserService {
//定义 dao 类型属性
//不需要添加 set 方法
//添加注入属性注解
@Autowired
private UserDao userDao;
public void add() {
System.out.println("service add.......");
userDao.add();
}
}
//Dao实现类
@Repository
//@Repository(value = "userDaoImpl1")
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("dao add.....");
}
}
(2) @Qualifier 根据属性名注入 和Autowired配合使用
一个接口有多个实现类 用Qualifier指定那个实现类
@Service
public class UserService {
//定义 dao 类型属性
//不需要添加 set 方法
//添加注入属性注解
@Autowired
@Qualifier(value="userDaoImpl1")
private UserDao userDao;
public void add() {
System.out.println("service add.......");
userDao.add();
}
}
//Dao实现类
@Repository(value = "userDaoImpl1")
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("dao add.....");
}
}
(3)@Resource 即可以根据名称注入,也可以根据类型注入,注意Resource不是Spring包中的而是扩展包中的,不建议用;
@Service
public class UserService {
//定义 dao 类型属性
//不需要添加 set 方法
//添加注入属性注解
//@Resource///根据名称注入
@Resource(name = "userDaoImpl1")
private UserDao userDao;
public void add() {
System.out.println("service add.......");
userDao.add();
}
}
//Dao实现类
@Repository(value = "userDaoImpl1")
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("dao add.....");
}
}
(4)@Value:注入普通类型属性
@Value(value = "abc")
private String name
6、完全注解开发
(1)创建配置类,替代 xml 配置文件
@Configuration //作为配置类,替代 xml 配置文件
@ComponentScan(basePackages = {"com.atguigu"})
public class SpringConfig {
}
(2)编写测试类
@Test
public void testService2() {
//加载配置类
ApplicationContext context
= new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean("userService",
UserService.class);
System.out.println(userService);
userService.add();
}
Spring-AOP
1、AOP 基本概念
(1)面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得 业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
(2)通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
(3)使用登录例子说明 AOP
web服务器
服务器是一种被动的操作,用来用户的请求和给用户响应
IIS 微软的
Tomcat
谈谈网站是如何进行访问的?
1.输入一个域名;回撤
2.检查本机的C:\Windows\System32\drivers\etcs\hosts配置文件下没有这个域名的映射;
&有,直接返回对应的Ip地址,这个地址中有我们需要访问的web程序,可以直接访问 127.0.0.1
&没有;去DNS服务器去找,找到的话就返回,找不到返回找不到
发布一个网站
传统MVC
M 模型 (dao :连接数据库 service:业务层)
V 视图(jsp)
V 控制器(servlet 接受前端的数据)
Spring MVC 是spring的一部分,底层还是servlet
注册servlet
servlet配置文件
HandlerMapping 根据url请求先找到处理器,执行操作,把结果返回给DispatcherServlet
Controller
jsp页面
原来的方式:http://localhost:8080/add?a=1&b=2
RestFul风格:http://localhost:8080/add/a/b
RestFul 风格的好处就是 提高安全性
@Controller
public class RestFulController {
@RequestMapping("/add/{a}/{b}")
public String test1(@PathVariable int a,@PathVariable int b, Model model){
int res=a+b;
model.addAttribute("msg","结果为"+res);
return "test";
}
}
如果不加描述,那么默认的请求方式是GET,当然还有其他方式 如 post,delete,put,get 详细写的出来的方法是下面的方式
@Controller
public class RestFulController {
@RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.GET)
public String test1(@PathVariable int a,@PathVariable int b, Model model){
int res=a+b;
model.addAttribute("msg","结果为"+res);
return "test";
}
}
也可以进一步简化
@Controller
public class RestFulController {
@GetMapping("/add/{a}/{b}")
public String test1(@PathVariable int a, @PathVariable int b, Model model){
int res=a+b;
model.addAttribute("msg","结果为"+res);
return "test";
}
}
使用RESTful操作资源 :可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!
http://127.0.0.1/item/1 查询,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 删除,DELETE
结果跳转方式
ModelAndView
设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面 .
页面 : {视图解析器前缀} + viewName +{视图解析器后缀} 即 /WEB-INF/jsp/test.jsp
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
public class ControllerTest1 implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//返回一个模型视图对象
ModelAndView mv = new ModelAndView();
mv.addObject("msg","ControllerTest1");
mv.setViewName("test");
return mv;
}
}
ServletAPI
通过设置ServletAPI , 不需要视图解析器 .
1、通过HttpServletResponse进行输出
2、通过HttpServletResponse实现重定向
3、通过HttpServletResponse实现转发
@Controller
public class ResultGo {
@RequestMapping("/result/t1")
public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
rsp.getWriter().println("Hello,Spring BY servlet API");
}
@RequestMapping("/result/t2")
public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
rsp.sendRedirect("/index.jsp");
}
@RequestMapping("/result/t3")
public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Exception {
//转发
req.setAttribute("msg","/result/t3");
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,rsp);
}
}
SpringMVC
通过SpringMVC来实现转发和重定向 - 无需视图解析器;
测试前,需要将视图解析器注释掉
<?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.kuang.controller"/>
<!-- 让Spring MVC不处理静态资源 -->
<mvc:default-servlet-handler />
<!--
支持mvc注解驱动
在spring中一般采用@RequestMapping注解来完成映射关系
要想使@RequestMapping注解生效
必须向上下文中注册DefaultAnnotationHandlerMapping
和一个AnnotationMethodHandlerAdapter实例
这两个实例分别在类级别和方法级别处理。
而annotation-driven配置帮助我们自动完成上述两个实例的注入。
-->
<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>-->
</beans>
转发:
@Controller
public class RestFulController {
@GetMapping("/add/{a}/{b}")
public String test1(@PathVariable int a, @PathVariable int b, Model model){
int res=a+b;
model.addAttribute("msg","结果为"+res);
return "forward:/WEB-INF/jsp/test.jsp";
}
}
重定向:
@GetMapping("/result/{a}/{b}")
public String test2(@PathVariable int a, @PathVariable int b, Model model){
int res=a+b;
model.addAttribute("msg","结果为"+res);
return "redirect:/index.jsp";
}
重定向的的结果
通过SpringMVC来实现转发和重定向 - 有视图解析器;
重定向 , 不需要视图解析器 , 本质就是重新请求一个新地方嘛 , 所以注意路径问题.
可以重定向到另外一个请求实现 .
@Controller
public class RestFulController {
@GetMapping("/add/{a}/{b}")
public String test1(@PathVariable int a, @PathVariable int b, Model model){
int res=a+b;
model.addAttribute("msg","结果为"+res);
return "test"; //转发
}
@GetMapping("/result/{a}/{b}")
public String test2(@PathVariable int a, @PathVariable int b, Model model){
int res=a+b;
model.addAttribute("msg","结果为"+res);
return "redirect:/index.jsp";//重定向
}
}
数据处理
处理提交数据
1、提交的域名称和处理方法的参数名一致
提交数据 : http://localhost:8080/hello?name=kuangshen
处理方法 :
@RequestMapping("/hello")
public String hello(String name){
System.out.println(name);
return "hello";
}
后台输出 : kuangshen
2、提交的域名称和处理方法的参数名不一致
提交数据 : http://localhost:8080/hello?username=kuangshen
处理方法 :
//@RequestParam("username") : username提交的域的名称 .
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name){
System.out.println(name);
return "hello";
}
后台输出 : kuangshen
3、提交的是一个对象
要求提交的表单域和对象的属性名一致 , 参数使用对象即可
1、实体类
@Data
@AllArgsConstructor //有参构造
@NoArgsConstructor //无参构造
public class User {
private int id;
private String name;
private int age;
}
2、提交数据 : http://localhost:8080/mvc04/user?name=kuangshen&id=1&age=15
3、处理方法 :
@RequestMapping("/user")
public String user(User user){
System.out.println(user);
return "hello";
}
后台输出 : User { id=1, name='kuangshen', age=15 }
说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。
数据显示到前端
数据显示到前端
第一种 : 通过ModelAndView
我们前面一直都是如此 . 就不过多解释
public class ControllerTest1 implements Controller { public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { //返回一个模型视图对象 ModelAndView mv = new ModelAndView(); mv.addObject("msg","ControllerTest1"); mv.setViewName("test"); return mv; } }
第二种 : 通过ModelMap
ModelMap
@RequestMapping("/hello") public String hello(@RequestParam("username") String name, ModelMap model){ //封装要显示到视图中的数据 //相当于req.setAttribute("name",name); model.addAttribute("name",name); System.out.println(name); return "hello"; }
第三种 : 通过Model
Model
@RequestMapping("/ct2/hello")
public String hello(@RequestParam("username") String name, Model model){
//封装要显示到视图中的数据
//相当于req.setAttribute("name",name);
model.addAttribute("msg",name);
System.out.println(name);
return "test";
}
对比
就对于新手而言简单来说使用区别就是:
Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解; ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性; ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。
当然更多的以后开发考虑的更多的是性能和优化,就不能单单仅限于此的了解