https://raw.githubusercontent.com/AzurTian/ImgBed/master/blog/logo.png

AzurTian's Blog

SpringMVC学习

执行流程

  1. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心,用户发出请求,DispatcherServlet接收请求并拦截请求
  1. 假设URL为:http://localhost:8080/SpringMVC/hello
  2. 如上URL拆分为三部分
  3. http://localhost:8080服务器域名
  4. SpringMVC部署在服务器上的web站点
  5. hello表示控制器
  6. 通过分析,url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器
  1. HandlerMapping为处理器映射,DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler
  2. HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器
  3. HandlerExecution将解析后的信息传递给DispatcherServlet
  4. HandlerAdapter表示处理适配器,其按照特定的规则去执行Handler
  5. Handler让具体的Controller执行
  6. Controller将具体的执行信息返回给HandlerAdapter
  7. HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet
  8. DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名
  9. 视图解析器将解析的逻辑视图名传给DispatcherServlet
  10. DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图
  11. 最终视图呈现给用户

基于XML实现

1.引入相关依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.0</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
</dependency>
<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.2</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

2.创建类

public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView mv = new ModelAndView();
        //业务代码
        String result = "你好,我是MVC";
        mv.addObject("msg",result);
        //视图跳转
        mv.setViewName("test");
        return mv;
    }
}

3.配置web.xml文件

<!--配置DispatcherServlet,这个是sptingmvc的核心-->
<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--DispatcherServlet要绑定的spring配置文件-->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc-servlet.xml</param-value>
    </init-param>
    <!--启动级别:1-->
    <load-on-startup>1</load-on-startup>
</servlet>
	<!--
    springmvc中, /   /*
    /:只匹配所有的请求,不会去匹配jsp页面
    /*:匹配所有的请求,包括jsp页面
    -->
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

4.配置springmvc-servlet.xml文件

<!--处理器映射器-->
<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>
<!--创建对象-->
<bean id="/hello" class="org.learn.demon.HelloController"/>

5.创建jsp文件

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
${msg}
</body>
</html>

6.配置Tomcat服务器

添加服务器之后,到工程结构,浏览tomcat打包的war包中有没有lib文件,没有就创建一个,把所有需要的jar包放进去

Spring学习

IOC

基本概念

  1. 控制反转(Inversion of Control,缩写为IoC),面向对象编程的一种设计原则,可以用来减低计算机代码之间的耦合度。最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫依赖查找(Dependency Lookup)。
  2. 通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
  3. IOC思想基于IOC容器完成,IOC容器底层就是对象工厂

Spring提供IOC容器实现两种方式

  1. BeanFactory:IOC容器基本实现,是spring内部的使用接口,不提供开发人员进行使用(加载配置文件的时候不会创建对象,在获取对象才去创建对象)

算法模板

高精度

加法

//初始条件:a:存储第一个大数(正序),b:存储第二个大数(正序),c:存储结果(逆序)
int a[N],b[N],c[N];//1~N,0号位存储数组长度
void g_add(int* A,int* B,int* C){
	C[0] = 1;//数组长度,从第一位开始 
	int t = 0;//保存进位和结果信息 
	for(int i = A[0],j = B[0];i > 0 || j > 0;--i,--j,++C[0]){
		t += i > 0 ? A[i] : 0;
		t += j > 0 ? B[j] : 0;
		C[C[0]] = t % 10;
		t /= 10;
	}
	C[C[0]] = t ? t : C[--C[0]];//如果最高位进位,则将进位信息保存,否则长度-1(循环导致长度+1)
}

减法

//初始条件:a:存储第一个大数(正序),b:存储第二个大数(正序),c:存储结果(逆序),f:确定正负
int a[N],b[N],c[N],f;//1~N,0号位存储数组长度
int g_cmp(int* A,int* B){//A>=B返回1,否则返回0
	if(A[0] != B[0]) return A[0] > B[0];
	for(int i = 1;i <= A[0];++i) if(A[i] != B[i]) return A[i] > B[i];
	return 1;
}
void g_sub(int* A,int* B,int* C){
	C[0] = 1;
	int t = 0;//存储借位和结果信息 
	for(int i = A[0],j = B[0];i > 0 || j > 0;--i,--j,++C[0]){
		t = i > 0 ? A[i] - t : t;
		t -= j > 0 ? B[j] : 0;
		C[C[0]] = (t + 10) % 10;
		t = t < 0 ? 1 : 0;
	}
	while(C[0] > 1 && !C[--C[0]]);//删除前导0
}
int main(){
    ~~~
    if((f = g_cmp(a,b))) g_sub(a,b,c);
    else g_sub(b,a,c);
    cout << (f ? "" : "-");
    ~~~
    return 0;
}

乘法

//初始条件:a:存储第一个大数(正序),b:存储第二个大数(正序),c:存储结果(逆序)
int a[N],b[N],c[2*N];//1~N,0号位存储数组长度
void g_mul(int* A,int* B,int* C){
	C[0] = A[0] + B[0];//长度多一位,方便判断结果为0的情况
	for(int i = A[0];i > 0;--i) for(int j = B[0];j > 0;--j) C[C[0]-i-j+1] += A[i] * B[j];//逆序放置结果
	for(int i = 1;i < C[0]-1;++i){//处理每一位进位
        C[i+1] += C[i] / 10;
        C[i] %= 10;
	}
	while(C[0] > 1 && !C[--C[0]]);//结果为0时删除多余0
}

除法

//初始条件:a:存储第一个大数(正序),b:存储第二个大数(正序),c:存储结果(逆序),r:存储余数(正序)
int a[N],b[N],c[N],r[N];//1~N,0号位存储数组长度
void g_div(int* A,int* B,int* C,int* R){
	if(!g_cmp(A,B)) {//如果B比A大,则直接商0,余数就是A
		C[0] = 1;
		for(int i = 0;i <= A[i];++i) R[i] = A[i];
		return;
	}
	int T[A[0]+1] = {0};//商的结果
	C[0] = A[0] + 1;//商的位数预处理和被除数相同
	for(int i = A[0];i > 0;--i){
		T[++T[0]] = A[A[0]-i+1];
		while(g_cmp(T,B)){
			++C[i];
			g_sub(T,B,R);
			if(!R[R[0]==1]) T[0] = 0;
			else{
				for(int j = R[0];j > 0;--j) T[R[0]-j+1] = R[j];
				T[0] = R[0];
			}
		}
		while(T[1] == 0 && T[0] > 0) --T[0]; 
	}
	while(C[0] > 1 && !C[--C[0]]);
	for(int i = 0;i <= T[0];++i) R[i] = T[i];
	if(T[0] == 0) R[0]= 1;
}

数学

质数筛法

//p:存储质数,idx:p的指针,vis:存储当前元素是否被访问
int p[N],idx,vis[N];
void get_primes(int x){
    for(int i = 2;i <= x;++i){
        if(!vis[i]) p[idx++] = i;
        for(int j = 0;p[j] <= x/i;++j){
            vis[p[j]*i] = 1;
            if(i % p[j] == 0) break;
        }
    }
}

高斯消元

const double eps = 1e-6;//精度判断(是否为0)
double a[N][N];//存储方程组矩阵
int gauss(){
	int r,c;//行,列
	for(c = 0,r = 0;c < n;++c){//系数矩阵第一列开始,遍历到最后一列
		int t = r;//记录当前列绝对值最大值所在行
		for(int i = r;i < n;++i) if(fabs(a[i][c]) > fabs(a[t][c])) t = i;
		if(fabs(a[t][c]) < eps) continue;//如果当前为0,则直接进入下一列,利用eps防止c++小数精度问题
		for(int i = c;i <= n;++i) swap(a[t][i],a[r][i]);//交换当前行与当前列最大值所在的行
		for(int i = n;i >= c;--i) a[r][i] /= a[r][c];//当前行当前列元素置为1,当前行其余元素也要更新,防止影响当前元素,逆序遍历
		for(int i = r+1;i < n;++i)//从下一行开始,更新当前列的下面所有行的值为0,更新当前行下面的所有行
			if(fabs(a[i][c]) > eps)//当前元素不是0
				for(int j = n;j >= c;--j)//逆序计算
					a[i][j] -= a[r][j] * a[i][c];
		++r;//如果当前行列不为0,则计算到这里,行数加一,否则就是当前行的下一列开始计算
	}
	if(r < n){//矩阵不满秩
		for(int i = r;i < n;++i)//判断是否存在系数为0,常s
			if(fabs(a[i][n]) > eps) return 2;//无解
		return 1;//无穷多解
	}
	for(int i = n-1;i >= 0;--i)//最后一行开始
		for(int j = i+1;j < n;++j)//当前行所在对角线的后面所有列
			a[i][n] -= a[i][j] * a[j][n];//存储最后结果(当前行其他列全部消为0)
	return 0;//唯一解
}
//使用方式
int t = gauss();
		if(t == 0) for(int i = 0;i < n;++i) cout << fixed << setprecision(2) << (fabs(a[i][n]) < eps ? 0 : a[i][n]) << endl;//防止输出-0.00
		else if(t == 1) cout << "无穷多解" << endl;
		else cout << "无解" << endl;

快速幂

int qmi(int a,int k,int p){
    int ret = 1;
    while(k){
        if(k & 1) ret = (LL) ret * a % p;
        a = (LL) a * a % p;
        k >>= 1;
    }
    return ret;
}

最大公约数

int gcd(int x,int y){
    return y ? gcd(y,x%y) : x;
}

二分查找

// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;//最左边的结果
        else l = mid + 1;
    }
    return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;//最右边的结果
        else r = mid - 1;
    }
    return l;
}

字符串

读取整行字符

//如果读取该行前有读取其他字符或者换行,则需要多加一个getline(cin,s);读取上一行遗留的换行符
getline(cin,s);//会读取一整行包括空格和换行符,但是会自动删去换行符

分割字符串

//构造原始字符串s的字符串流
stringstream ssin(s);
//以delim作为分割符,分割后的字符串存储到t中
string t;
while(getline(ssin,t,'delim')){...}

基本操作

int h[N],e[N],ne[N],idx;
void add(int a,int b){//a->b
    e[idx] = b;ne[idx] = h[a];h[a] = idx++;
}
memset(h,-1,sizeof h);//初始化头节点为-1
for(int i = h[a];~i;i = ne[i]){...}//遍历邻接表

边多就用for循环,邻接矩阵存储。边少就用堆优化,连接表存储。

Oracle命令

1、查看表中索引

  1. 显示索引名称,索引作用的列
select * from user_ind_columns where table_name='表名';
  1. 显示索引的具体信息(创建时间、类型、内存大小)
select * from all_indexes where table_name='表名';

2、删除序列

delete sequence 序列名;

3、查看存储过程/触发器编译错误信息

select * from SYS.USER_ERRORS where NAME=upper('出错的名称(触发器/存储过程m)');

4、约束条件相关操作

  1. 查看表的约束条件
select * from user_constraints where table_name='表名';
  1. 删除约束条件
alter table 表名 drop constraint 约束条件名;
  1. 失效约束条件
alter table 表名 disable constraint 约束条件名;
  1. 生效约束条件
alter table 表名 enable constraint 约束条件名;

5、查看所有存储过程、触发器、视图、表

select * From user_triggers; --所有触发器
select * From user_procedures; --所有存储过程
select * From user_views; --所有视图
select * From user_tables; --所有表

6、查看当前数据库连接的sid实例

select instance_name from v$instance;

7、查看用户拥有的表空间

select tablespace_name from user_tablespaces;