java面试准备
JAVA面试准备
1、SSM转Springboot
1、导入依赖,对于ssm中的依赖在springboot依次导入,注意版本问题;
遇到的问题:jdbc和tx的版本问题,导致了事务报错
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
2、目录要保持一致
问题:支付用到的wxpay包路径错误导致无法运行
3、thymeleaf依赖导入问题
因为没有导入依赖所以templates文件夹下的文件无法访问
4、templates文件夹的资源放行问题
spring.resources.static-locations=classpath:/templates/,classpath:/static/
spring.thymeleaf.suffix=.html
注意下面的suffix=.html不加会导致除了index.html可以访问之外其他页面无法访问
2、知识点回顾
Javase: 多线程、jvm、hashmap、网络编程、反射和注解、IO(还没学)
前端:html、css、JS(jQuery、Ajax)、Vue(没学)
javaweb:jsp部分(都没咋学)
Spring: IOC和DI、AOP
Mybatis:动态sql、别名、xml文件中写sql与java代码分离
SpringMvc: dispatchservlet
Boot:没学完
linux基本操作
redis
计算机网络
操作系统
数据结构和算法:剑指Offer
3、零散知识汇总
静态资源过滤
ssm框架中调用静态资源(css、js),需要的web.xml中配置
4、mysql回顾
inner join :连接查询
select
max(score.scor), stu.name
from stu inner join score on stu.id = score.stu_id group by stu.name
上述代码查询该学生的最高科目成绩
max()函数:MySQL MAX()函数返回一组值中的最大值。
max函数 连接查询到的id,也就是那一行的数据并不是max对应的哪一行数据:可能可行的办法:嵌套查询
left join
right join
创建索引
CREATE INDEX indexName ON table_name (column_name)
ALTER table tableName ADD INDEX indexName(columnName)
CREATE TABLE mytable(
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
INDEX [indexName] (username(length))
);
使用索引
EXPLAIN select course from score;
查看索引是否被使用
给属性创建索引之后使用该属性进行查询数据会用的索引
进行查询会大大提升查询速度
mysql事务处理:锁
以innoDB为例:四种隔离级别
分为悲观锁:s、x、is、ix
- 共享锁(S锁、多锁): 事务获得元组的共享锁后,其它事务也只能获得该元组的共享锁,而不能获得排它锁;获得共享锁的事务可以对元组进行读操作。
- 排它锁(X锁,写锁): 事务获得元组的排它锁后,其它事务既不能获得该元组的共享锁,也不能获得排它锁;获得排它锁的事务可以对元组进行写操作。
- 意向共享锁(IS锁): 事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
- 意向排它锁(IX锁): 事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
Mysql InnoDB引擎默认支持行锁,来尽量缩小锁定元组的粒度,行锁分为三级,粒度从小到大依次是:
- 记录锁(Record Lock):单行
- 间隔锁(Gap Lock):一个开区间内的多行
- 防插入锁(Next-Key Lock):一个前开后闭区间内的多行,实际上是记录锁和间隔锁的结合
Mysql乐观锁(MVCC)
乐观锁机制通过在表中添加version字段进行实现。
在Mysql InnoDB引擎中,其会在每行数据中额外添加两个隐藏值来实现MVCC,这两个值一个记录这行数据何时被创建,另外一个记录这行数据何时更新(或者被删除)。在实际操作中,每开启一个新事务,事务的版本号就会递增。
5、mybatis回顾
ssm中配置文件书写
首先是配置文件头:官方文档找
<?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.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/kuang/dao/userMapper.xml"/>
</mappers>
</configuration>
先配置环境:1 事务:JDBC 2 连接池:四个属性driver、url、username、password 3、可能要配需要扫描的mapper.xml
在ssm中的配置
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--扫描所有包,交给spring管理-->
<context:component-scan base-package="com.sdkd"></context:component-scan>
<!--引入加载spring-mvc.xml-->
<import resource="classpath:spring-mvc.xml"></import>
<!--配置druid连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/game_mall?useUnicode=true&characterEncoding=utf-8"></property>
<property name="username" value="root"></property>
<property name="password" value="wangyutai"></property>
</bean>
<!--配置sessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--数据源-->
<property name="dataSource" ref="dataSource"></property>
<!--配置mapper路径-->
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
<!--mybatis配置路径-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
</bean>
<!--绑定mapper与xml的扫描器-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--mapper对应的dao接口的包-->
<property name="basePackage" value="com.sdkd.dao"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
<!--mybatis的事务是jdbc的事务-->
<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>
</beans>
1、比之前多配置了一个扫描器,扫描包交由spring管理
2、因为dao层没有注解,所以也要配置将sqlSessionFactory注入
3、也要配置事务
4、直接配置sqlSessionFactory:数据源、配置mapper路径、mybatis配置路径(这个就是之前的配置文件、里面可以配置mapper直接使用类名)
mapper.xml文件
1、文件头:官方文档
2、
<mapper namespace="对应哪个类">
</mapper>
3、resultmap
<resultMap id="UserMap" type="User">
<!-- id为主键 -->
<id column="id" property="id"/>
<!-- column是数据库表的列名 , property是对应实体类的属性名 -->
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
因为调用sql语句的时候要求实体类和数据库中的属性名一致,万一不一致就会出错,所以用resultmap的方式起别名
4、
<select id="selectUserById" resultMap="UserMap">
select id , name , pwd from user where id = #{id}
</select>
一对多 多对一处理
例子:
<!--
按查询结果嵌套处理
思路:
1. 直接查询出结果,进行结果集的映射
-->
<select id="getStudents2" resultMap="StudentTeacher2" >
select s.id sid, s.name sname , t.name tname
from student s,teacher t
where s.tid = t.id
</select>
<resultMap id="StudentTeacher2" type="Student">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
<!--关联对象property 关联对象在Student实体类中的属性-->
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
多对一:association进行数据关联
property为sql语句中用到的、javaType为相应的类对象
用result 中的property 和 column设置属性对应名:column是数据库中的名
比如多篇文章对应一个人,在文章mapper中用association关联用户
一对多:collection
比如一个用户有多篇文章,在用户的mapper中用collection将post文章进行关联
动态SQL
-
if
<select id="findActiveBlogWithTitleLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> </select> -
choose (when, otherwise) 类似于switch case
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <choose> <when test="title != null"> AND title like #{title} </when> <when test="author != null and author.name != null"> AND author_name like #{author.name} </when> <otherwise> AND featured = 1 </otherwise> </choose> </select> -
trim (where, set)
<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM BLOG <where> <if test="state != null"> state = #{state} </if> <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </where> </select><trim prefix="WHERE" prefixOverrides="AND |OR "> ... </trim><update id="updateAuthorIfNecessary"> update Author <set> <if test="username != null">username=#{username},</if> <if test="password != null">password=#{password},</if> <if test="email != null">email=#{email},</if> <if test="bio != null">bio=#{bio}</if> </set> where id=#{id} </update><trim prefix="SET" suffixOverrides=","> ... </trim> -
foreach
<select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!
提示 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
一级缓存
- 在同一个
SqlSession中, Mybatis 会把执行的方法和参数通过算法生成缓存的键值, 将键值和结果存放在一个 Map 中, 如果后续的键值一样, 则直接从 Map 中获取数据; - 不同的
SqlSession之间的缓存是相互隔离的; - 用一个
SqlSession, 可以通过配置使得在查询前清空缓存; - 任何的 UPDATE, INSERT, DELETE 语句都会清空缓存。
二级缓存
- 二级缓存是Mapper级别的缓存,多个SqlSession类的实例对象操作同一个Mapper配置文件中的sql语句,多个SqlSession类的实例对象可以共用二级缓存,二级缓存是跨SqlSession的。一个Mapper有一个自己的二级缓存区域(按照namespace划分),两个Mapper的namespace如果相同,那么这两个Mapper执行的sql查询会被缓存在同一个二级缓存中。要开启二级缓存需要在配置文件中设置cacheEnabled属性为true。
6、spring
IOC
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
依赖注入
- 依赖注入(Dependency Injection,DI)。
- 依赖 : 指Bean对象的创建依赖于容器 . Bean对象的依赖资源 .
- 注入 : 指Bean对象所依赖的资源 , 由容器来设置和装配
三种注入方式:
- 构造器注入
- set方法注入
- 基于注解的注入:autowired
AOP
-
概念
AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
<!--aop的配置--> <aop:config> <!--切入点 expression:表达式匹配要执行的方法--> <aop:pointcut id="pointcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/> <!--执行环绕; advice-ref执行方法 . pointcut-ref切入点--> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config><!--aop的配置--> <aop:config> <!--第二种方式:使用AOP的标签实现--> <aop:aspect ref="diy"> <aop:pointcut id="diyPonitcut" expression="execution(* com.kuang.service.UserServiceImpl.*(..))"/> <aop:before pointcut-ref="diyPonitcut" method="before"/> <aop:after pointcut-ref="diyPonitcut" method="after"/> </aop:aspect> </aop:config>
注解开发
我们之前都是使用 bean 的标签进行bean注入,但是实际开发中,我们一般都会使用注解!
1、配置扫描哪些包下的注解
<!--指定注解扫描包-->
<context:component-scan base-package="com.kuang.pojo"/>
2、在指定包下编写类,增加注解
@Component("user")
// 相当于配置文件中 <bean id="user" class="当前注解的类"/>
public class User {
public String name = "秦疆";
}
-
属性注入
@Value("秦疆") public String name; @Value("秦疆") public void setName(String name) { this.name = name; }
@Component三个衍生注解
为了更好的进行分层,Spring可以使用其它三个注解,功能一样,目前使用哪一个功能都一样。
- @Controller:web层
- @Service:service层
- @Repository:dao层
Bean的作用域
@scope
- singleton:默认的,Spring会采用单例模式创建这个对象。关闭工厂 ,所有的对象都会销毁。
- prototype:多例模式。关闭工厂 ,所有的对象不会销毁。内部的垃圾回收机制会回收
@Scope("prototype")
@Scope("singleton")
使用注解开发必须配置扫描
<context:annotation-config/>
作用:
-
进行注解驱动注册,从而使注解生效
-
用于激活那些已经在spring容器里注册过的bean上面的注解,也就是显示的向Spring注册
-
如果不扫描包,就需要手动配置bean
-
如果不加注解驱动,则注入的值为null!
代理模式
为什么要学习代理模式,因为AOP的底层机制就是动态代理!
静态代理的好处:
- 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
- 公共的业务由代理来完成 . 实现了业务的分工 ,
- 公共业务发生扩展时变得更加集中和方便 .
缺点 :
- 类多了 , 多了代理类 , 工作量变大了 . 开发效率降低 .
我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理 !
动态代理
-
动态代理的角色和静态代理的一样 .
-
动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
-
动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
-
- 基于接口的动态代理----JDK动态代理
- 基于类的动态代理--cglib
- 现在用的比较多的是 javasist 来生成动态代理 . 百度一下javasist
- 我们这里使用JDK的原生代码来实现,其余的道理都是一样的!
AOP再理解
- 用动态代理的方法创建代理类制造切面,降低程序的冗余
整合mybatis
<!--配置SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--关联Mybatis-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/kuang/dao/*.xml"/>
</bean>
Spring声明式事务
编程式事务管理
- 将事务管理代码嵌到业务方法中来控制事务的提交和回滚
- 缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码
声明式事务管理:tx
- 一般情况下比编程式事务好用。
- 将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。
- 将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。
JDBC事务
<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
配置好事务管理器后我们需要去配置事务的通知
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--配置哪些方法使用什么样的事务,配置事务的传播特性-->
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="search*" propagation="REQUIRED"/>
<tx:method name="get" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
配置AOP
导入aop的头文件!
<!--配置aop织入事务-->
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* com.kuang.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
7、javaweb学习
高难度面试题:
请你谈谈网站是如何进行访问的!
-
输入一个域名;回车
-
检查本机的 C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射;
-
有:直接返回对应的ip地址,这个地址中,有我们需要访问的web程序,可以直接访问
127.0.0.1 www.qinjiang.com -
没有:去DNS服务器找,找到的话就返回,找不到就返回找不到;
-
-
可以配置一下环境变量(可选性)
HTTP
- HTTP(超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上。
http响应:
-
响应状态码
200:请求响应成功 200
3xx:请求重定向
- 重定向:你重新到我给你新位置去;
4xx:找不到资源 404
- 资源不存在;
5xx:服务器代码错误 500 502:网关错误
web.xml配置:指定映射关系
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
ServletContext
- web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用;
重定向和转发
转发是服务器行为,重定向是客户端行为
页面都会实现跳转
不同点
-
请求转发的时候,url不会产生变化
-
重定向时候,url地址栏会发生变化;
解释
假设你去办理某个执照,
重定向:你先去了A局,A局的人说:“这个事情不归我们管,去B局”,然后,你就从A退了出来,自己乘车去了B局。
转发:你先去了A局,A局看了以后,知道这个事情其实应该B局来管,但是他没有把你退回来,而是让你坐一会儿,自己到后面办公室联系了B的人,让他们办好后,送了过来。
cookie和session
cookie
- 客户端技术 (响应,请求)
session
- 服务器技术,利用这个技术,可以保存用户的会话信息? 我们可以把信息或者数据放在Session中!
用户带着cookie访问,服务器一次请求创建一个session
可以对比登陆之后跳转页面不需要重新登录和 好久没登陆,登陆之后不用输入密码
可以设置session过期时间
JSP
和html的区别:
- HTML只给用户提供静态的数据
- JSP页面中可以嵌入JAVA代码,为用户提供动态数据;
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!
JSP最终也会被转换成为一个Java类!
JSP 本质上就是一个Servlet
8、springmvc
dispatchservlet
简要分析执行流程
-
DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
我们假设请求的url为 : http://localhost:8080/SpringMVC/hello
如上url拆分成三部分:
http://localhost:8080服务器域名
SpringMVC部署在服务器上的web站点
hello表示控制器
通过分析,如上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根据视图解析器解析的视图结果,调用具体的视图。
-
最终视图呈现给用户。
总结:
- dispatcherservlet会接受并拦截请求
- dispatcherservlet调用处理器映射handlermapping寻找适配的处理器Handler
- handler根据url查找相应的控制器,并将信息传给dispatcherServlet
- DispatcherServlet调用处理器适配器HandlerAdapter按照规则去执行处理器Handler
- Handler让具体的控制器去执行
- 控制器将信息返回给处理器适配器HandlerAdapter:比如modelandview
- HandlerAdapter将视图逻辑名和模型传递给DispatcherServlet
- DispatcherServlet调用视图解析器解析穿回来的视图名
- 视图解析器传回解析的视图名
- DispacherServlet根据视图解析器解析的结果调用具体的视图
- 视图呈现给用户
配置文件
web.xml
<!--配置disptcherservlet-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
拦截所有请求
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
过滤器
<filter>
<filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
spring-mvc.xml
<!--扫描包-->
<context:component-scan base-package="com.sdkd.controller"></context:component-scan>
<!--过滤静态资源-->
<mvc:default-servlet-handler/>
<!--注解驱动-->
<mvc:annotation-driven>
</mvc:annotation-driven>
接口实现controller
-
编写一个Controller类,ControllerTest1
//定义控制器 //注意点:不要导错包,实现Controller接口,重写方法; public class ControllerTest1 implements Controller { public ModelAndView handleRequest(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws Exception { //返回一个模型视图对象 ModelAndView mv = new ModelAndView(); mv.addObject("msg","Test1Controller"); mv.setViewName("test"); return mv; } } -
编写完毕后,去Spring配置文件中注册请求的bean;name对应请求路径,class对应处理请求的类
<bean name="/t1" class="com.kuang.controller.ControllerTest1"/> -
编写前端test.jsp,注意在WEB-INF/jsp目录下编写,对应我们的视图解析器
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Kuangshen</title> </head> <body> ${msg} </body> </html> -
配置Tomcat运行测试,我这里没有项目发布名配置的就是一个 / ,所以请求不用加项目名,OK!
说明:
-
实现接口Controller定义控制器是较老的办法
-
缺点是:一个控制器中只有一个方法,如果要多个方法则需要定义多个Controller;定义的方式比较麻烦;
使用注解@Controller
-
@Controller注解类型用于声明Spring类的实例是一个控制器(在讲IOC时还提到了另外3个注解);
-
Spring可以使用扫描机制来找到应用程序中所有基于注解的控制器类,为了保证Spring能找到你的控制器,需要在配置文件中声明组件扫描。
<!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 --> <context:component-scan base-package="com.kuang.controller"/> -
增加一个ControllerTest2类,使用注解实现;
//@Controller注解的类会自动添加到Spring上下文中 @Controller public class ControllerTest2{ //映射访问路径 @RequestMapping("/t2") public String index(Model model){ //Spring MVC会自动实例化一个Model对象用于向视图中传值 model.addAttribute("msg", "ControllerTest2"); //返回视图位置 return "test"; } } -
可以发现,我们的两个请求都可以指向一个视图,但是页面结果的结果是不一样的,从这里可以看出视图是被复用的,而控制器与视图之间是弱偶合关系。
ModelAndView
设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面 .
页面 : {视图解析器前缀} + viewName +{视图解析器后缀}
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
无视图解析器转发请求:
@RequestMapping("/rsm/t3")
public String test3(){
//重定向
return "redirect:/index.jsp";
}
有视图解析器
@RequestMapping("/rsm2/t1")
public String test1(){
//转发
return "test";
}
数据显示到前端
第一种 : 通过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
@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
@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";
}
ssm整合
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>
JSON数据交互
JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式,目前使用特别广泛。
在 JavaScript 语言中,一切都是对象。因此,任何JavaScript 支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。看看他的要求和语法格式:
- 对象表示为键值对,数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
JSON 键值对是用来保存 JavaScript 对象的一种方式,和 JavaScript 对象的写法也大同小异,键/值对组合中的键名写在前面并用双引号 "" 包裹,使用冒号 : 分隔,然后紧接着值:
JSON 是 JavaScript 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。
var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的
var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串
JSON 和 JavaScript 对象互转
要实现从JSON字符串转换为JavaScript 对象,使用 JSON.parse() 方法:
var obj = JSON.parse('{"a": "Hello", "b": "World"}');
//结果是 {a: 'Hello', b: 'World'}
要实现从JavaScript 对象转换为JSON字符串,使用 JSON.stringify() 方法:
var json = JSON.stringify({a: 'Hello', b: 'World'});
//结果是 '{"a": "Hello", "b": "World"}'
拦截器编写
编写特定的java类继承InterpretHandler
在spring-mvc配置文件中配置
<!--关于拦截器的配置-->
<mvc:interceptors>
<mvc:interceptor>
<!--/** 包括路径及其子路径-->
<!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-->
<!--/admin/** 拦截的是/admin/下的所有-->
<mvc:mapping path="/**"/>
<!--bean配置的就是拦截器-->
<bean class="com.kuang.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
浙公网安备 33010602011771号