关于三层架构:
springmvc是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合。
springmvc是一个基于mvc模式的web架构。
springmvc用于前后端的数据交互。
SpringMvc工作流程
第一步:发送请求到前端控制器(DispatcherServlet)
第二步:前端控制器请求处理器映射器(HandlerMapping)查找Handler
第三步:处理器映射器返回Handler到前端控制器
第四步:前端控制器调用处理器适配器去执行Handler
第五步:处理器适配器去执行Handler
第六步:Handler执行完成给适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回ModelAndView
ModelAndView是springmvc框架的一个底层对象,包括 Model和view
第八步:前端控制器请求视图解析器去进行视图解析
根据逻辑视图名解析成真正的视图(jsp)
第九步:视图解析器向前端控制器返回View
第十步:前端控制器进行视图渲染
视图渲染将模型数据(在ModelAndView对象中)填充到request域
第十一步:前端控制器向用户响应结果
SpringMvc快速上手
一.SpringMvc的相关配置
1.所需的jar的引入
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
</dependencies>
2.web.xml中的配置
在web.xml中主要配置的是前端控制器,前端控制器的作用是:通过用户的url请求路径查找到匹配该请求的handler,在将用户的请求交由相应的handler处理。
<!-- 配置前端控制器 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>//指定配置文件所在位置,默认在WEB-INF下
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.action</url-pattern> //指定拦截的路径
</servlet-mapping>
3.springmvc.xml的配置
<!-- 配置视图解析器:解析转向页面,prefix:前缀,suffix:后缀
将controller层的返回值进行解析,加上前缀和后缀,就解析成了一个jsp页面,跳转到该页面
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 注解扫描:将扫描配置的包,将符合要求的纳入spring容器 -->
<context:component-scan base-package="cn.fzkj.controller"/>
<!-- 开启注解支持 -->
<mvc:annotation-driven/>
二.RequestMapping注解
使用 @RequestMapping注解映射请求路径,就是将前端的请求交给具体的方法去执行。例如:
前端请求:
<a href="user/login.action">登录</a>
Controller层:
@Controller
@RequestMapping("/user")
public class userController {
@RequestMapping("/login.action")
public String testLogin(){
System.out.println("登录成功");
return "success";
}
}
@RequestMapping("/user")是请求的前缀,主要用于对项目进行划分模块。@RequestMapping("/login.action")是请求的具体映射。SpringMvc会拦截所有请求(不准确),并在Controller对应的类中找符合的映射,交由该方法去处理。
RequestMapping注解的属性
1.value:用于指定请求的url,和path属性的作用相同
@RequestMapping(value="/login.action")
2.method:用于指定请求的方式(GET、POST)
@RequestMapping(value="",method={RequestMethod.GET})
3.params:用于指定请求的参数,要求请求的key和value要和配置的相同
@RequestMapping(value="",method={},params={"username"})//必须传username参数
三.请求参数的绑定
就是前端给后端传递参数
- 第一种:基本类型
前端页面代码
<a href="user/login.action?username=mr">登录</a>
后端代码
@RequestMapping("/login.action")
public String testLogin(String username){ //参数名要和前端传递的参数名保持一致
System.out.println("登录成功");
System.out.println("用户名:"+username);
return "success";
}
- 第二种:实体类型(javabean)
前端页面代码
<form action="user/user.action" method="POST">
姓名:<input type="text" name="username" /><br>
年龄:<input type="text" name="age" /><br>
账户名:<input type="text" name="account.name" /><br>
金额:<input type="text" name="account.money" /><br>
<input type="submit" value="提交"/>
</form>
name属性要和JavaBean的属性名称一致
后端页面代码
@RequestMapping("/user.action")
public String testuser(User user){ //自动封装成JavaBean
System.out.println(user);
return "success";
}
四.注解
1.RequestParam注解
之前说控制层接收的参数名要和表现层传递的参数名保持一致,那如果不一致要怎么办呢?
<a href="user/login.action?username=mr">登录</a>
@RequestMapping("/login.action")
public String testLogin(String name){
System.out.println("登录成功");
System.out.println("用户名:"+username);
return "success";
}
前端传一个名为username的参数,而后端接收的却是name参数,按照之前讲的这样肯定是接收不到的。
RequstParam注解就是解决这个问题的
修改之后的代码
@RequestMapping("/login.action")
public String testLogin(@RequestParam("username") String name){
System.out.println("登录成功");
System.out.println("用户名:"+name);
return "success";
}
RequestParam的参数就是前端传递的参数名,该注解会将接收到的参数保存到后面的变量中(即name中)
要赋值的变量必须紧跟着RequestParam注解且在其后面
2.RequestBody注解
@RequestBody注解用来接收请求体的内容,请求方式必须是POST,GET请求无请求体。
<form action="user/user.action" method="POST">
姓名:<input type="text" name="username" /><br><br>
年龄:<input type="text" name="age" /><br><br>
<input type="submit" value="提交"/>
</form>
@RequestMapping("/user.action")
public String testuser(@RequestBody String body){
System.out.println(body);
return "success";
}
运行结果:
username=mr&age=20
3.PathVariable注解
用于接收url中占位符的值
<a href="/user/testPathVariable/22">testPathVariable</a>
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") String id){
System.out.println(id);
return "success";
}
运行结果
22
五.响应的返回值
1.String类型
@RequestMapping("/login.action")
public String testLogin(@RequestParam("username") String name){
System.out.println("登录成功");
System.out.println("用户名:"+name);
return "success";
}
返回值类型为String,返回值会经过视图解析器解析成为jsp页面,最终显示。
2.void类型
返回值是void类型的方法有三种跳转页面的方式
-
请求转发
-
请求重定向
-
输出流
@RequestMapping("/testVoid.action")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("testVoid方法执行了....");
//1.请求转发(一次请求)
// request.getRequestDispatcher("/WEBINF/jsp/success.jsp").forward(request,response);
//2.请求重定向(两次请求)
// response.sendRedirect(request.getContextPath()+"/index.jsp");
//3.直接向浏览器输出
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("mr");
return;
}
3.ModelAndView对象类型
@RequestMapping("/testModelAndView.action")
public ModelAndView testModelAndView(){
//创建ModelAndView对象
ModelAndView mv = new ModelAndView();
System.out.println("testModelAndView执行了...");
Account a =new Account();
a.setMoney(1000.0);
a.setName("123");
User user = new User();
user.setUsername(456");
user.setAccount(a);
user.setAge(20);
//把user对象存放到mv对象中,同时也会保存到request域中
mv.addObject("user",user);
//设置要跳转的页面,默认经过试图解析器
mv.setViewName("success");
return mv;
}
4.使用forward和redirect关键字进行页面跳转
@RequestMapping("/testGuanjianzi.action")
public String testGuanjianzi() throws IOException {
System.out.println("登录成功1");
//使用forward请求转发
// return "forward:/WEB-INF/jsp/success.jsp";
//redirect重定向
return "redirect:/index.jsp";
}
六.json格式的数据传递
所需的jar包:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
使用ajax进行异步交互
<script src="js/jquery-3.4.1.min.js"></script>
<script>
$(document).ready(function(){
$("#btn").click(function(){
// alert("lala");
$.ajax({
cache:false,
url:"user/testAjax.action",
contentType:"application/json;charset=utf-8",
data:'{"username":"lj","age":20}',
dataType:"json",
success:function(data){ //接收服务器端的响应数据
//data:服务器端响应的数据,json格式的
alert(data.username);
alert(data.age);
},
type:"post"
});
});
});
</script>
Controler层的接收方法:
@ResponseBody //将返回值转换为json格式
@RequestMapping("/testAjax.action")
public User testJson(@RequestBody User user){ //接收请求体
System.out.println(user);
//重新赋值
user.setAge(21);
user.setUsername("xlj");
return user;
}
七.springmvc文件上传
1.springmvc文件上传
<h3>springmvc文件上传</h3>
<form action="user/fileupload.action" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload" />
<input type="submit" value="上传"/>
</form>
@RequestMapping("/fileupload.action")
public String testFileUpLoad(HttpServletRequest request, MultipartFile upload) throws IOException {
System.out.println("springmvc文件上传");
//确定上传的路径
String path = request.getSession().getServletContext().getRealPath("/uploads/");
//判断该路径是否存在
File file = new File(path);
if(!file.exists()){
//创建文件夹
file.mkdirs();
}
//获取上传文件的名称
String filename = upload.getOriginalFilename();
//设置名称为唯一值
String uuid = UUID.randomUUID().toString().replace("-","");
filename = uuid +"_"+ filename;
//文件上传
upload.transferTo(new File(path,filename));
return "success";
}
2.springmvc跨服务器文件上传
@RequestMapping("/fileupload1.action")
public String testFileUpLoad1(MultipartFile upload) throws IOException {
System.out.println("跨服务器文件上传");
//定义上传的服务器路径
String path = "http://localhost:9090/uploads/";
//获取上传文件的名称
String filename = upload.getOriginalFilename();
//设置名称为唯一值
String uuid = UUID.randomUUID().toString().replace("-","");
filename = uuid +"_"+ filename;
//创建客户端对象
Client client = Client.create();
//与图片服务器进行连接
WebResource webResource = client.resource(path+filename);
//上传文件
webResource.put(upload.getBytes());
return "success";
}
八.异常处理
定义异常类:
public class SysException extends Exception {
//提示信息
private String message;
public SysException(String message) {
this.message = message;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
定义异常处理类:
//异常处理器类
public class SysExceptionResolver implements HandlerExceptionResolver {
/**
* 处理异常
* @param request
* @param response
* @param handler
* @param ex:抛出的异常对象
* @return
*/
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
//获取到异常对象
SysException e = null;
if(ex instanceof SysException){
e = (SysException)ex;
}else{
e = new SysException("系统错误");
}
//创建ModelAndView对象
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg",e.getMessage());
mv.setViewName("error");
return mv;
}
}
controller层:
@RequestMapping("/testException.action")
public String testException() throws SysException {
System.out.println("exception执行了...");
try{
int a = 1/0;
}catch (Exception e){
e.printStackTrace();
//向上抛出异常
throw new SysException("捕获到异常");
}
return "success";
}
springmvc.xml配置
<!-- 配置异常处理器 -->
<bean id="sysExceptionResolver" class="cn.fzkj.exception.SysExceptionResolver" />
捕获到的异常都是交由异常处理类(SysExceptionResolver)处理的
九.拦截器
SpringMVC的处理器拦截器类似于Servlet中的过滤器(Filter),用于对处理器进行预处理和后处理。
过滤器和拦截器的区别:
过滤器:是servlet规范中的一部分,任何java web工程都能使用。在url-pattern中配置了/*之后,对所有的访问资源都会拦截。
拦截器:是SpringMvc自己的,只有使用SpringMvc框架的工程才能使用。且只会拦截访问的控制器中的方法。
要自定义拦截器,必须要实现HandlerInterceptor接口。
1.编写拦截器类
2.配置拦截器
拦截器类:
//自定义的拦截器
public class DiyInterceptor implements HandlerInterceptor {
/**
* 预处理
* @param request
* @param response
* @param handler
* @return true:放行
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("预处理执行了...");
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 {
}
}
配置:
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 配置拦截的方法-->
<mvc:mapping path="/user/*"/>
<!--配置不拦截的方法
<mvc:exclude-mapping path=""/>
-->
<!-- 注册拦截器-->
<bean class="cn.fzkj.interceptor.DiyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
持续更新~~~