SpringMVC入门案例和常用API使用演示
文章目录
SpringMVC入门案例
SpringMVC的创建方式有xml和配置类两种方式
这里只记录实际应用中使用的方式搭建SpringMVC工程
文件结构
步骤概述
- 因为采用父级工程和子工程的方式进行演示,所以此处只对父级pom.xml文件进行修改,添加子工程需要的依赖包以及jdk版本
- 构建配置类WebConfig,扫描Controller层
- 编辑controller层,对页面请求进行处理
- 构建启动类,该启动类继承了AbstractAnnotationConfigDispatcherServletInitializer,并通过其下的三个函数对配置类进行解析
- 编写需要的前端页面
步骤实现
- 父级pom.xml的修改
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dean</groupId>
<artifactId>SpringMvcAPi</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>mvc-viewResolution</module>
</modules>
<packaging>pom</packaging>
<name>SpringMvcAPi</name>
<url>http://maven.apache.org</url>
<!--1、修改父级的pom.xml文件 只需要修改properties和dependencies节点的内容-->
<!--修改版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!--添加所有子工程可能用到的依赖包-->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
</project>
- 构建web配置类WebConfig
@ComponentScan("com.dean.controller")
public class WebConfig {
}
- 编辑前端控制器 controller层
@Controller //将bean注入到Spring容器
@RequestMapping("/user") //配置请求映射,在请求时用来区分不同的controller
public class UserController {
//返回页面有两种写法
//1、返回页面的文件名,作为字符串,框架会调用ModelAndView进行返回视图
//实际请求拼接了/user和/hello 从而找到hello方法
@RequestMapping("/hello")
public String hello()
{
return "/hello.jsp";
}
//2、直接设置返回值为ModelAndView
@RequestMapping("/view")
public ModelAndView view()
{
return new ModelAndView("/view.jsp");
}
}
- 编写启动类
public class WebMvcInit extends AbstractAnnotationConfigDispatcherServletInitializer {
//整合Spring使用的,这里暂不配置
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
//指定SpringMvc的配置类
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
//配置请求映射,这里配置所有请求,即/
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
-
编写前端页面 index(主页)hello(/user/hello请求页面)view(/user/view请求页面)
index
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<%--5、编写前端页面 index主页--%>
<title>主页</title>
</head>
<body>
<h1>
<a href="/user/hello">hello</a>
</h1>
<h1>
<a href="/user/view">view</a>
</h1>
</body>
</html>
hello
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<%--5、编写前端页面 hello--%>
<title>Hello</title>
</head>
<body>
<h1>Hello</h1>
</body>
</html>
view
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<%--5、编写前端页面 view--%>
<title>View</title>
</head>
<body>
<h1>View</h1>
</body>
</html>
常用API
视图解析
视图解析实质上是利用对方法的后置拦截,在返回视图时进行配置视图解析器,使得在controller层返回参数的时候,只需要返回视图名称,而无需返回后缀名等
具体实现
在上述项目的WebConfig类中注入InternalResourceViewResolver
@ComponentScan("com.dean.controller")
public class WebConfig {
//添加视图解析器
@Bean
public InternalResourceViewResolver viewResolver()
{
InternalResourceViewResolver viewResolver=new InternalResourceViewResolver();
//设置视图路径前缀
viewResolver.setPrefix("/");
//设置视图路径的后缀
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
controller层的代码返回值的更改
@Controller //将bean注入到Spring容器
@RequestMapping("/user") //配置请求映射,在请求时用来区分不同的controller
public class UserController {
@RequestMapping("/hello")
public String hello()
{
//配置视图解析器之前
//return "/hello.jsp";
//配置视图解析器后
return "hello";
}
@RequestMapping("/view")
public ModelAndView view()
{
//配置视图解析器之前
//return new ModelAndView("/view.jsp");
//配置视图解析器之后
return new ModelAndView("view");
}
}
视图解析器会使springmvc获取到controller方法的返回值,然后与前缀后缀拼接得到完整的视图路径
但上述的视图解析器配置的是放在根路径下,从外部可以直接访问,在安全性上较差,servlet对此有所改进,将视图放在WEB-INF目录下,在该目录下的视图只能从内部访问,而无法从外部直接访问
改进后的文件结构如下:
改进后的视图解析器代码如下:
@ComponentScan("com.dean.controller")
public class WebConfig {
//添加视图解析器
@Bean
public InternalResourceViewResolver viewResolver()
{
InternalResourceViewResolver viewResolver=
new InternalResourceViewResolver();
//直接放在根目录下不安全,改进版
//设置视图路径前缀
viewResolver.setPrefix("/WEB-INF/view/");
//设置视图路径后缀
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
参数传递(等同于servlet中的request.getAttribute())
在Servlet中参数的传递通过request.getAttribute()方法,返回值是string,使用时需要自行转换
springMvc简化了这一过程,具有自动参数转化功能
基本数据类型 & String类型
主要核心代码在Controller层
@Controller
@RequestMapping("/user")
public class UserController {
//value是请求映射
//method是请求方法 类似servlet的doPost方法
@RequestMapping(value = "/addUser",method = RequestMethod.POST)
public ModelAndView addUser(
//@RequestParam 说明该参数是请求参数
//name 指明参数名称 与表单中标签的名称一致 未指定时默认与形参变量名相同
//required 确定参数是否必须传递 未指定时默认为true
//defaultValue 当参数不是一定要传递时,可以设定参数的默认值
@RequestParam(name="username",required = true) String name,
@RequestParam(required = false,defaultValue = "21") Integer age,
String phone
)
{
System.out.println(name+"\t"+age+"\t"+phone);
return new ModelAndView("success");
}
}
请求页面使用表单完成
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>主页</title>
</head>
<body>
<h1>基本数据类型 & String</h1>
<form action="/user/addUser" method="post">
<p>
<label for="username">username:</label>
<input type="text" id="username" name="username">
</p>
<p>
<label for="age">age:</label>
<input type="text" id="age" name="age">
</p>
<p>
<label for="phone">phone:</label>
<input type="text" id="phone" name="phone">
</p>
<button type="submit">add</button>
</form>
</body>
</html>
对象类型(自动装箱)
当传递的参数是自定义的对象类型时,SpringMVC采用了自动装箱技术,会去自动匹配POJO类型(pojo是简单java对象,即javaBean,只是叫了不同的名字)
对象类型Pet
public class Pet {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Pet{" +
"name='" + name + '\'' +
'}';
}
}
Person类
public class Person {
private String name;
private Integer age;
private Pet pet;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Pet getPet() {
return pet;
}
public void setPet(Pet pet) {
this.pet = pet;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", pet=" + pet +
'}';
}
}
Controller
@Controller
@RequestMapping("/user")
public class UserController {
//对象类型自动装箱
@RequestMapping(value = "/addPerson",method = RequestMethod.POST)
public ModelAndView addPerson(
/*
会去自动找Person类,调用setter方法
*/
Person person
)
{
System.out.println(person);
return new ModelAndView("success");
}
}
前端页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>主页</title>
</head>
<body>
<h1>对象类型 自动装箱</h1>
<form action="/user/addPerson" method="post">
<p>
<label for="name">Person-name:</label>
<input type="text" name="name" id="name">
</p>
<p>
<label for="age">Age:</label>
<input type="text" name="age" id="age">
</p>
<p>
<label for="pet-name">Pet-name:</label>
<input type="text" name="pet.name" id="pet-name">
</p>
<button type="submit">add</button>
</form>
</body>
</html>
日期类型
针对日期类型,主要依靠两个注解
@EnableWebMvc 和 @DateTimeFormat
两步搞定
1、在WebConfig上添加注解@EnableWebMvc
2、在形参或成员变量上添加注解@DateTimeFormat
具体代码如下:
WebConfig
@ComponentScan("com.dean.controller")
@EnableWebMvc //开启转换器 便于将表单提交的String类型的数据转换为Date类型
public class WebConfig {
@Bean
public InternalResourceViewResolver viewResolver()
{
InternalResourceViewResolver resolver=new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/view/");
resolver.setSuffix(".jsp");
return resolver;
}
}
UserController
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(value = "/date",method = RequestMethod.GET)
public ModelAndView getDate(@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss") Date date)
{
System.out.println(date);
return new ModelAndView("success");
}
}
前端页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>主页</title>
</head>
<body>
<h1>日期类型</h1>
<form action="/user/date" method="get">
<p>
<label for="date">Date:</label>
<input type="text" id="date" name="date">
</p>
<button type="submit">submit</button>
</form>
</body>
</html>
参数乱码
在web的启动类处添加过滤器Filter进行编码设置
返回参数(等同于servlet中的request.setAttribute(“key”,value))
在servlet里,通过request.setAttribute()在后端设置参数,在前端页面通过ER表达式获取参数的值显示在界面上
但在SpringMVC中有非常多的方式返回参数,然后在前端页面通过ER表达式进行渲染数据
方式1:ModelAndView+ModelAndView.addObject()
代码如下:
前端页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="false" %>
<%--使用ER表达式 引入taglib--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<%--6、前端页面 返回页面--%>
<title>返回页面</title>
</head>
<body>
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>age</th>
</tr>
</thead>
<tbody>
<c:forEach var="user" items="${users}">
<tr>
<td>${user.id}</td>
<td>${user.name}</td>
<td>${user.age}</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>
前端控制器:
@Controller
@RequestMapping("/user")
public class UserController {
//addObject方式
@RequestMapping("/find-one")
public ModelAndView findOne()
{
//使用list模拟数据库数据
List<User> users=new ArrayList<>();
users.add(new User("1", "小海", 22));
users.add(new User("2", "小白", 18));
users.add(new User("3", "zz", 26));
users.add(new User("4","鲸鱼",28));
ModelAndView mv=new ModelAndView();
//相当于request.setAttribute("users",users);
mv.addObject("users",users);
//设置返回视图
mv.setViewName("userView");
return mv;
}
}
方式2:ModelAndView+Model.addAttribute()
前端页面与上述一致
前端控制器代码如下:
@Controller
@RequestMapping("/user")
public class UserController {
//addAtribute方式
@RequestMapping("/find-two")
public ModelAndView findTwo(Model model)
{
//使用list模拟数据库数据
List<User> users=new ArrayList<>();
users.add(new User("1", "小海", 22));
users.add(new User("2", "小白", 18));
users.add(new User("3", "zz", 26));
users.add(new User("4","鲸鱼",28));
//依然是request.setAttribute("users",users);
model.addAttribute("users",users);
//返回视图
return new ModelAndView("userView","model",model);
}
}
方式3:ModelAndView+Map
前端页面与上述一致
前端控制器代码如下:
@Controller
@RequestMapping("/user")
public class UserController {
//ModelAndView+Map
@RequestMapping("/find-three")
public ModelAndView findThree(Map<String, Object> map)
{
//使用list模拟数据库数据
List<User> users=new ArrayList<>();
users.add(new User("1", "小海", 22));
users.add(new User("2", "小白", 18));
users.add(new User("3", "zz", 26));
users.add(new User("4","鲸鱼",28));
//将数据放入map
map.put("users",users);
//返回视图
return new ModelAndView("userView",map);
}
}
方式4:String+Map
前端页面与之前一致
前端控制器代码如下:
@Controller
@RequestMapping("/user")
public class UserController {
//String+Map
@RequestMapping("/find-four")
public String findFour(Map<String, Object> model)
{
//使用list模拟数据库数据
List<User> users=new ArrayList<>();
users.add(new User("1", "小海", 22));
users.add(new User("2", "小白", 18));
users.add(new User("3", "zz", 26));
users.add(new User("4","鲸鱼",28));
//将数据放入map
model.put("users",users);
return "userView";
}
}
方式5:Web原生对象:传递形参(HttpServletRequest,HttpServletResponse)
前端页面代码同上
前端控制器代码如下:
@Controller
@RequestMapping("/user")
public class UserController {
//Web原生对象 传参
@RequestMapping("/find-web")
public String findWeb(HttpServletRequest req, HttpServletResponse resp)
{
//使用list模拟数据库数据
List<User> users=new ArrayList<>();
users.add(new User("1", "小海", 22));
users.add(new User("2", "小白", 18));
users.add(new User("3", "周周", 26));
users.add(new User("4","鲸鱼",28));
//使用Web原生对象HttpServletRequest设置参数
req.setAttribute("users",users);
return "userView";
}
}
方式6:Web原生对象:创建ServletRequestAttributes
通过自行创建ServletRequestAttributes对象获取原生参数
前端页面代码同上
前端控制器代码如下:
@Controller
@RequestMapping("/user")
public class UserController {
//创建ServletRequestAttributes对象
@RequestMapping("/webObj")
public String webObj()
{
//使用list模拟数据库数据
List<User> users=new ArrayList<>();
users.add(new User("1", "周周", 26));
users.add(new User("2","鲸鱼",28));
users.add(new User("3", "小海", 22));
users.add(new User("4", "小白", 18));
ServletRequestAttributes requestAttributes= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//通过ServletRequestAttributes实例获取参数对象
//ServletRequestAttributes可以获取HttpServletRequest HttpServletResponse HttpSession对象
HttpServletRequest req = requestAttributes.getRequest();
//通过request设置参数
req.setAttribute("users",users);
//返回视图
return "userView";
}
}
JSON数据处理
核心步骤
- pom.xml文件中添加json的依赖包
- WebConfig中添加@EnableWebMvc 并配置不要将静态资源的加载当作请求
- 在controller层添加注解 @ResponseBody 并编写方法进行传递数据
- 在前端页面引入jquery并编写Ajax请求
具体实现
- pom.xml添加的依赖包
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.12.0-rc2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.0-rc2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.0-rc2</version>
</dependency>
- WebConfig代码
@ComponentScan("com.dean.controller")
@EnableWebMvc //一定要添加
public class WebConfig implements WebMvcConfigurer {
//添加默认请求的视图返回 可以没有
//即请求/时 返回index.html页面
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}
//配置静态资源
//使加载静态资源时,不被当作请求处理
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
- Controller层代码
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping(value = "/findUser",method = RequestMethod.POST)
@ResponseBody //帮助使用HttpServletResponse返回数据
//采用形参传参,前端页面设置的参数将会传到后端
public List<User> findUser(User user)
{
//前端Ajax请求的数据
System.out.println(user);
//后端发送的数据
List<User> users=new ArrayList<>();
users.add(new User("1", "周周", 26));
users.add(new User("2", "小海", 22));
users.add(new User("3", "小白", 18));
return users;
}
}
-
前端页面
前端页面会返回一个包含后端传入数据的表格
<!DOCTYPE html>
<html lang="en">
<head>
<!--6、编写前端页面-->
<meta charset="UTF-8">
<title>主页</title>
<!--引入jquery-->
<script src="/static/jquery-2.1.1.js"></script>
</head>
<body>
<h1>Html</h1>
<button onclick=findUser()>findUser</button>
<table id="table">
</table>
<script>
function findUser() {
$.ajax({
url:"/user/findUser",
method:"post",
dataType:"json",
data:{id:4,name:"鲸鱼",age:22},
success:function (data) {
//$('#table').empty(); //清空原表格
$('#table').append("<tr><th>id</th><th>name</th><th>age</th></tr>");
// let html="<tr><th>id</th><th>name</th><th>age</th></tr>";
$.each(data,function (i,item) {
html="<tr>" +
"<td>"+item['id']+"</td>"+
"<td>"+item['name']+"</td>"+
"<td>"+item['age']+"</td>"+
"</tr>"
$('#table').append(html);
});
// $('#table').html(html);
}
})
}
</script>
</body>
</html>
RestFul请求
将前后端分离,在处理请求时,后端只返回数据(即只提供资源)给前端页面,只渲染数据,不再渲染标签
前端和后端设置不同的端口号,部署在不同的服务器上
RestFul的状态转换(GET POST Delete Put)对应着对于资源的CRUD操作
RestFul中有一个重要的概念:幂等性(即无论请求多少次,资源都是相同的)
核心步骤
- 在项目的pom.xml中添加依赖
- 编写Spring MVC的配置类 (核心 @EnableWebMvc)
- 编写前端控制器 UserController,开启同源策略,编写请求 (核心 **@CrossOrigin ** @GetMapping @PostMapping @PutMapping @DeleteMapping 或 @RequestMapping+@ResponseBody )
- 模拟数据,设计响应数据的格式
- 编写启动类
- 使用WebStorm编写前端页面
- 将前端页面部署到nginx上
具体实现
后端
文件结构
-
修改pom.xml
- SpringMvc配置类
@ComponentScan("com.dean.controller")
@EnableWebMvc
public class WebConfig {
}
-
前端控制器
添加的注释
Get请求
@Controller+@ResponseBody版本
//Get请求
//url: /user/1 (查询id=1的用户信息)
//响应类型: application/json
//返回数据:{"id":1,"name":"string","age":int}
@RequestMapping(value = "{id}",method = RequestMethod.GET)
@ResponseBody
public ResultEntity getUserById(@PathVariable(value = "id") String id)
{
//从数据库请求数据
User user=users.get(id);
return new ResultEntity(200,"ok",true,user);
}
@RestController版本
//Get请求
//url: /user/1 (查询id=1的用户信息)
//响应类型: application/json
//返回数据:{"id":1,"name":"string","age":int}
@GetMapping("{id}") //等同于@RequestMapping(value = "{id}",method = RequestMethod.GET)
public ResultEntity getUserById(@PathVariable(value = "id") String id)
{
//从数据库请求数据
User user=users.get(id);
return new ResultEntity(200,"ok",true,user);
}
Post请求
@Controller+@ResponseBody版本
//Post请求
//url: /user 新增一个用户
//参数类型:application/json
//参数: {"id":1,"name":"string","age":int} 自动装箱
//响应类型:application/json
//响应数据:{}
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public ResultEntity addUser(@RequestBody User user)
{
users.put(user.getId(),user);
System.out.println(user);
return new ResultEntity(200,"ok",true,null);
}
@RestController版本
//Post请求
//url: /user 新增一个用户
//参数类型:application/json
//参数: {"id":1,"name":"string","age":int} 自动装箱
//响应类型:application/json
//响应数据:{}
@PostMapping
public ResultEntity addUser(@RequestBody User user)
{
users.put(user.getId(),user);
System.out.println(user);
return new ResultEntity(200,"ok",true,null);
}
Put请求
@Controller+@ResponseBody版本
//Put请求
//url: /user/1 修改id=1的用户信息
//参数类型:application/json
//参数格式:{"name":"string","age":int}
//响应类型:application/json
//响应数据:{}
@RequestMapping(value = "{id}",method = RequestMethod.PUT)
@ResponseBody
public ResultEntity updateUser(@PathVariable String id,@RequestBody User user)
{
user.setId(id);
users.put(id,user);
System.out.println(users);
return new ResultEntity(200,"update success",true,"{}");
}
@RestController版本
//Put请求
//url: /user/1 修改id=1的用户信息
//参数类型:application/json
//参数格式:{"name":"string","age":int}
//响应类型:application/json
//响应数据:{}
@PutMapping("{id}")
public ResultEntity updateUser(@PathVariable String id,@RequestBody User user)
{
user.setId(id);
users.put(id,user);
System.out.println(users);
return new ResultEntity(200,"update success",true,"{}");
}
Delete请求
@Controller+@ResponseBody版本
//Delete请求
//url: /user/1 删除id=1的用户
//响应类型:application/json
//响应数据:{}
@RequestMapping(value = "{id}",method = RequestMethod.DELETE)
@ResponseBody
public ResultEntity delUser(@PathVariable(value = "id") String uid)
{
users.remove(uid);
return new ResultEntity(200,"delete success",true,"{}");
}
@RestController版本
//Delete请求
//url: /user/1 删除id=1的用户
//响应类型:application/json
//响应数据:{}
@DeleteMapping("{id}") //等同于@RequestMapping(value = "{id}",method = RequestMethod.DELETE)
public ResultEntity delUser(@PathVariable(value = "id") String uid)
{
users.remove(uid);
return new ResultEntity(200,"delete success",true,"{}");
}
-
模拟数据User 设计响应数据格式
User
public class User {
private String id;
private String name;
private Integer age;
public User() {
}
public User(String id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
响应数据格式(仿照http的响应数据格式)
/**
* {
* "code":200, 状态码
* "message":"string", 提示信息
* "flag":"boolean", 执行状况
* "data":"object(json)" 数据
* }
*/
public class
ResultEntity {
private Integer code;
private String message;
private Boolean flag;
private Object data;
public ResultEntity() {
}
public ResultEntity(Integer code, String message, Boolean flag, Object data) {
this.code = code;
this.message = message;
this.flag = flag;
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Boolean getFlag() {
return flag;
}
public void setFlag(Boolean flag) {
this.flag = flag;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
- 启动类
public class WebServerInit extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
前端
-
引入vue.js和jquery.js
- 编写前端界面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>主页</title>
<!--引入jquery和vue-->
<script src="./static/vue.js"></script>
<script src="./static/jquery-2.1.1.js"></script>
</head>
<body>
<div id="app">
<!--显示所有用户-->
<table style="width: 500px;text-align: center;border-color: cornflowerblue" border="1">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>age</th>
</tr>
</thead>
<tbody>
<tr v-for="user in users" :key="user.id">
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.age }}</td>
</tr>
</tbody>
</table>
<!--新增用户-->
<div id="add-user">
<p>
<label for="add-user-id">id:</label>
<input type="text" id="add-user-id" v-model="addUser.id">
</p>
<p>
<label for="add-user-name">name:</label>
<input type="text" id="add-user-name" v-model="addUser.name">
</p>
<p>
<label for="add-user-age">age:</label>
<input type="text" id="add-user-age" v-model="addUser.age">
</p>
<button @click="_addUser()">addUser</button>
<button @click="_updateUser()">updateUser</button>
</div>
<hr>
<p>
<label for="del-user-id">id:</label>
<input type="text" id="del-user-id" v-model="addUser.id">
</p>
<button @click="_deleteUser">deleteUser</button>
</div>
<script>
let vm=new Vue({
el:"#app",
data:{
users:[],
addUser:{
id:"",
name:"",
age:""
}
},
//生命钩子
created(){
//查询所有用户
this._findAllUsers();
},
methods:{
//查找所有用户
_findAllUsers(){
let this_=this;
//编写ajax请求
$.ajax({
url:"http://localhost:8090/user/", //请求url
method:"get",
dataType:"json", //返回数据格式
contentType:"application/json", //网页文件的类型和网页编码格式
success:function (resp) {
this_.users=resp.data;
}
})
return null;
},
//新增用户
_addUser(){
let this_=this;
//编写ajax请求
$.ajax({
url:"http://localhost:8090/user/",
method:"post",
data:JSON.stringify(this_.addUser), //将参数对象转换为Json格式
dataType:"json",
contentType:"application/json",
success:function (resp) {
this_._findAllUsers(); //刷新页面
}
})
},
//修改用户
_updateUser(){
let id=this.addUser.id;
let user={
name:this.addUser.name,
age:this.addUser.age
}
let this_=this;
//编写ajax请求
$.ajax({
url:"http://localhost:8090/user/"+id,
method:"put",
data:JSON.stringify(user), //将参数对象转换为Json格式
dataType:"json",
contentType:"application/json",
success:function (resp) {
this_._findAllUsers(); //刷新页面
}
})
},
//删除用户
_deleteUser()
{
let id=this.addUser.id;
let this_=this;
//编写ajax请求
$.ajax({
url:"http://localhost:8090/user/"+id,
method:"delete",
data:JSON.stringify(this_.addUser), //将参数对象转换为Json格式
dataType:"json",
contentType:"application/json",
success:function (resp) {
this_._findAllUsers(); //刷新页面
}
})
}
}
})
</script>
</body>
</html>
-
将页面部署在nginx上
即将页面和static文件复制在nginx的html文件夹里,删除原有的index.html文件
统一异常处理
核心步骤
- controller里模拟抛出异常
- 编写统一异常处理器CustomException
- WebConfig(配置类),WebServerInit(启动类)和之前一致
具体实现
- Controller
@Controller
@RequestMapping("user")
public class UserController {
@RequestMapping("main")
public ModelAndView getMain(String name, Model model)
{
if("admin".equals(name))
{
//模拟抛出异常
throw new RuntimeException("不能使用admin登录");
}
model.addAttribute("name",name);
return new ModelAndView("main");
}
}
- 统一异常处理器CustomException
@ControllerAdvice
public class CustomException {
//指定处理RuntimeException类的异常
@ExceptionHandler(RuntimeException.class)
public ModelAndView exception (Exception e, Model model)
{
System.out.println(e.getMessage());
model.addAttribute("message",e.getMessage());
return new ModelAndView("error");
}
}
拦截器
Filter:过滤器 过滤的是url
intercepter:拦截器 面向方法的代理模式
主要是WebConfig和自定义的拦截器UserInterceptor
- WebConfig
@ComponentScan("com.dean.controller")
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
//添加视图解析器
@Bean
public InternalResourceViewResolver viewResolver()
{
InternalResourceViewResolver viewResolver=new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
//配置静态资源
//相当于xml中的<mvc:default-servlet-handler>
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
//添加拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
//创建一个自定义的拦截器,加入容器
registry.addInterceptor(new UserInterceptor());
}
}
- UserInterceptor
public class UserInterceptor implements HandlerInterceptor {
//controller目标方法之前执行
//适合做权限的控制
//形参Object handler实际指的是目标方法对象
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod method= (HandlerMethod) handler;
//method.getMethod().getName() 获取到目标方法名
System.out.println("目标方法执行前"+method.getMethod().getName());
return true;
}
//controller目标方法成功执行之后执行
//适合做日志的管理
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//modelAndView.getViewName() 获取到返回的页面名
System.out.println("目标方法成功执行之后"+modelAndView.getViewName());
}
//最终方法,目标方法执行结束后(不论是否抛出异常)
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//ex.getMessage() 获取到异常信息
System.out.println("目标方法执行之后"+ex.getMessage());
}
}
Struts2
SpringMvc是基于方法开发的,较快,通过形参传参,可以进行单例开发
Struts2是基于类开发的,较慢,通过类的成员变量传参,无法进行单例开发
虽然很少有人用,但了解还是要了解的
核心步骤
- pom.xml中添加依赖
- 编写配置类web.xml
- 编写核心类Action
- 编写核心文件,配置请求返回视图,struts.xml
- 编写前端页面
具体实现
-
pom.xml中添加依赖
-
编写配置类web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
- 编写核心类Action
public class UserAction {
//基于类的编程 参数通过成员变量传递
public String message;
public void setMessage(String message) {
this.message = message;
}
public String hello()
{
System.out.println(message);
return "SUCCESS";
}
public String login()
{
if("admin".equals(message))
return "ERROR";
return "SUCCESS";
}
}
- 编写核心文件,配置请求返回视图,struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<!-- 请求参数的编码方式 -->
<constant name="struts.i18n.encoding" value="utf-8"/>
<package name="USER" extends="struts-default" namespace="/user"> <!--请求由namespace和name拼接组成-->
<action name="hello" class="com.dean.action.UserAction" method="hello"> <!--和action中的方法对应-->
<result name="SUCCESS">/main.jsp</result> <!--配置返回页面-->
</action>
<action name="login" class="com.dean.action.UserAction" method="login">
<result name="SUCCESS">/main.jsp</result>
<result name="ERROR">/error.jsp</result>
</action>
</package>
</struts>
-
编写前端页面
index首页
成功返回页面
发生错误后返回的页面
本文地址:https://blog.csdn.net/Dean_xiu/article/details/109750409