SpringNVC(三)
十二、验证码(非重点)
屏障,防止暴力破解
12.1 导入jar
<!-- Kaptcha -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
12.2 声明验证码组件
<servlet>
<servlet-name>cap</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
<init-param>
<!-- 图片边框,合法值:yes , no -->
<param-name>kaptcha.border</param-name>
<param-value>no</param-value>
</init-param>
<init-param>
<!-- 验证码长度 -->
<param-name>kaptcha.textproducer.char.length</param-name>
<param-value>4</param-value>
</init-param>
<init-param>
<!-- 文本集合,验证码值从此集合中获取 -->
<param-name>kaptcha.textproducer.char.string</param-name>
<param-value>abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</param-value>
</init-param>
<init-param>
<!--字体颜色 -->
<param-name>kaptcha.background.clear.to</param-name>
<param-value>211,229,237</param-value>
</init-param>
<init-param>
<!-- session.setAttribute("captcha","验证码") -->
<param-name>kaptcha.session.key</param-name>
<param-value>captcha</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>cap</servlet-name>
<url-pattern>/captcha</url-pattern>
</servlet-mapping>
12.3 Page
<img src="${pageContext.request.contextPath}/captcha" style="width:85px" id="cap"/>
<script>
$(function(){
$("#cap").click(function(){
//刷新验证码
path = $(this).attr("src")+"?"+new Date().getTime();
$(this).attr("src",path);
});
});
</script>
十三、REST
13.1 开发风格
是一种开发风格,遵从此风格开发软件,是restful的。
- 每个资源都有自己的标识
http://localhost:8989/xxx/users
http://localhost:8989/xxx/users/1
http://localhost:8989/xxx/users/1/orders
- 每个请求都有明确的动词 ( GET, POST, PUT, DELETE )
GET :http://localhost:8989/xxx/users 查询所有用户
POST:http://localhost:8989/xxx/users 增加一个用户
PUT :http://localhost:8989/xxx/users/1 修改用户1
DELETE :http://localhost:8989/xxx/users/1 删除用户1
GET:http://localhost:8989/xxx/users/1/orders 查询用户1的订单
POST:http://localhost:8989/xxx/users/1/orders 为用户1增加一个订单
13.2 优点
- 看Url就知道要什么
- 看http method就知道干什么
13.3 使用
13.3.1 定义Rest风格的 Controller
@RequestMapping(value="/users",method = RequestMethod.GET)
等价
@GetMapping("/users")
@RestController
public class RestController {
@GetMapping("/users")
public List<User> queryAllUsers(){
System.out.println("get");
List<User> users = ....
return users;
}
@PostMapping("/users")
public String addUser(@RequestBody User user){
System.out.println("Post user :"+user);
return "{status:1}";
}
@PutMapping("/users")
public String updateUser(@RequestBody User user){
System.out.println("Put user" user:"+user);
return "{status:1}";
}
@GetMapping("/users/{id}")
public String queryOneUser(@PathVariable Integer id){//@PathVariable 接收路径中的值
System.out.println("Get user id:"+id);
return "{status:1}";
}
@DeleteMapping("/users/{id}")
public String deleteOneUser(@PathVariable Integer id){//@PathVariable 接收路径中的值
System.out.println("delete user id:"+id);
return "{status:1}";
}
}
13.3.2 Ajax请求
<script>
function putUser(){ // 发送更新请求 (增加请求发送方式也是如此)
var xhr = new XMLHttpRequest();
//定义 put,delete,get,post方式 即可,不用定义_method
xhr.open("put","${pageContext.request.contextPath}/rest04/users");
// 设置请求头
xhr.setRequestHeader("content-type","application/json");
// 设置请求参数
var user = {id:1,NAME:"shine",city:"bj","birth":"2020/12/12","salary":100.5};
xhr.send(JSON.stringify(user));
xhr.onreadystatechange=function(){
if(xhr.readyState==4 && xhr.status==200){
var ret = xhr.responseText;
// 解析json,并输出
console.log(JSON.parse(ret));
}
}
/*$.ajax({
url:'${pageContext.request.contextPath}/rest04/users',
type:'put',
contentType:"application/json",//声明请求参数类型为 json
data:JSON.stringify(user),// 转换js对象成json
success:function(ret){
console.log(JSON.parse(ret));
}
});*/
}
function delUser(){ // 发送删除请求
var xhr = new XMLHttpRequest();
//定义 put,delete,get,post方式 即可,不用定义_method
xhr.open("delete","${pageContext.request.contextPath}/rest04/users/1");
xhr.send();
xhr.onreadystatechange=function(){
if(xhr.readyState==4 && xhr.status==200){
var ret = xhr.responseText;
console.log(JSON.parse(ret));
}
}
}
</script>
十四、跨域请求
14.1为什么会有跨域问题的存在
JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象,即同源政策。
所谓同源是指:协议相同,域名相同,端口相同。
14.2 同源政策的目的
同源策略的目的是为了保证用户信息的安全。防止恶意的网站盗取数据。
设想这样一个情景:A网站是一家银行,用户登录以后,又去浏览其他的网站B,如果网站B可以读取A网站的Cookie,会发生什么问题?
14.3 域
域:协议+IP+端口
比如:http://www.example.com/zw/index.html
协议是:http://
域名是:www.example.com
端口号是:80(默认端口可以省略),
它的同源情况如下:
http://www.example.com/zwxk/manager.html 同源
https://www.example.com/zw/index.html 不同源
http://examle.com/zw/index.html 不同源
http://www.example.com:81zw/index.html 不同源
14.4 Ajax跨域问题
当Ajax跨域请求时,响应会被浏览器拦截,并报错。即浏览器默认不允许ajax跨域得到响应内容。
互相信任的域之间如果需要ajax访问,(比如前后端分离项目中,前端项目和后端项目之间),则需要额外的设置才可正常请求。
14.5 解决方案
允许其他域访问
在被访问方的Controller类上,添加注解
@CrossOrigin("http://localhost:8080") //允许此域发请求访问
public class SysUserController {
....
}
如果要携带Cookie要JSONP跨域
$.ajax({
url:"http://localhost:8080/hello",
dataType:"jsonp",
jsonpCallback:"callback",
success:function (data) {
alert(data);
}
});
JSONP实现跨域原理
<script type="text/javascript">
function abc(msg){
console.info("abc function msg:"+msg);
}
</script>
<script type="text/javascript" src="http://localhost:8080/hello?callback=abc"></script>
十五、SpringMVC执行流程
十六、Spring整合
16.1 整合思路
此时项目中有两个工厂
- DispatcherServlet 启动的springMVC工厂==负责生产C及springMVC自己的系统组件
- ContextLoaderListener 启动的spring工厂==负责生产其他所有组件
- springMVC的工厂会被设置为spring工厂的子工厂,可以随意获取spring工厂中的组件
- 整合过程,就是累加:代码+依赖+配置。然后将service注入给controller即可
16.2 整合技巧
两个工厂不能有彼此侵入,即,生产的组件不能有重合。
<!-- 告知SpringMVC 哪些包中 存在 被注解的类
use-default-filters=true 凡是被 @Controller @Service @Repository注解的类,都会被扫描
use-default-filters=false 默认不扫描包内的任何类, 只扫描include-filter中指定的类
只扫描被@Controller注解的类
-->
<context:component-scan base-package="com.zhj" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 告知Spring
唯独不扫描@Controller注解的类 -->
<context:component-scan base-package="com.zhj" use-default-filters="true">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>