springmvc
目录
- 1.创建基本框架步骤
- 2.@RequestMapping()
- 3.获取请求参数
- 5.SpringMVC视图
- 6.RESTful风格
- 7.处理请求报文和相应报文等
1.创建基本框架步骤
1.创建一个新的maven模板(可以选择webapp骨架,也可以自己后期创建webapp)
2.配置加入打包方式为war包
3.导入所需要依赖
servlet-api
spring-webmvc
thymeleaf-springmvc整合
4.配置web.xml文件
配置springmvc文件位置,同时在resources文件夹下面创建springmvc.xml文件
<!--设置Spring的编码过滤器-->
<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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--设置处理请求方式的过滤器-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--设置SpringMVC的前端控制器-->
<servlet>
<servlet-name>SpringMVC</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>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
5.在webapp目录下新建templates文件夹,在文件夹下新建html文件,写前端页面给控制器发请求
<a th:href="@{/index}">访问index</a>
6.写controller层用于接收请求
1.给controller类加@Controller注解
2.写具体方法
3.返回值为跳转的页面名称
4.方法上加上@RequestMapper,value的属性值为对应的前端请求
@Controller
public class helloController {
@RequestMapping(value = "/")
public String hello(){
return "index";
}
}
6.在springmvc配置文件中扫描controller组件
<context:component-scan base-package="com.tcy.controller"></context:component-scan>
7.在springmvc配置文件中配置视图解析器
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
8.配置tomcat文件,并运行即可
2.@RequestMapping()
@RequestMapping()内部参数,均可设置为数组,当设置为数组时,value和method都是匹配到一个即可,但param必须要全部匹配
2.1 value属性
当请求为多个时候
请求为a,或b或c,都会由这个方法来处理,value的值必须要写
@Controller
public class helloController {
@RequestMapping(
//请求为a,或b或c,都会由这个方法来处理
//只要满足一个就行
value = {“a”,"b","c"}
)
public String hello(){
return "index";
}
}
2.1.1 路径支持ant风格
?:表示任意的单个字符
:表示任意的0个或多个字符
** :表示任意层数的任意目录
注意:在使用时,只能使用/ */xxx的方式
<a th:href="@{/index/**/a}"
地址栏可以为/a/a/a/a/a/b /a
可以保证最后一个a可以被访问到。
2.1.2 restful风格
@RequestMappering("/index/{username}/{password}")
public String text(
@Pathivariable("username") String username,
@Pathvariable("password") Integer password
){
return "success"
}
2.2 method属性
//如果默认没有设置method属性,那么就不以请求方式进行匹配。
2.2.1 form表单问题:
1.form表单默认不能提交put和delete请求,如果写put和delete,那么就会发送默认的get请求。
2.在form表单中如果用get方法来传递参数,那么action内的url?后面的参数是接收不到的,但是表单中的数据可以接收到
<form action=
"${pageContext.request.contextPath }/myServlet?name=lz" method="GET">
<input type="text" name="password"/>
<input type="submit" value="提交"/>
</form>
想当然的结果是
http://localhost:8888/11/myServlet?name=lz&password=123
但真正的url为
http://localhost:8888/11/myServlet?password=123
name=lz就会被覆盖
将method改为
http://localhost:8888/11/myServlet?name=lz
而password参数封装在请求体中传给后台,所以后台既可以得到name的值,也可以得到password的值,都没有问题。
2.2.2 get和post相关问题(涉及面试题):
1.提交请求时,
get提交参数
直接在地址栏拼接请求
参数格式:
?请求参数名=请求参数值
?id=2
post提交参数:
将参数放在请求体中
格式依旧是:
name=value
2.get请求时,url地址的长度是有限制的
这是因为浏览器要对url
进行解析,而解析的时候就要分配内存。对于一个字节流的解析,必须分配buffer
来保存所有要存储的数据。而url
这种东西必须当作一个整体看待,无法一块一块处理,于是就处理一个请求时必须分配一整块足够大的内存。如果url
太长,而并发又很高,就容易挤爆服务器的内存。
3.post和get请求安全问题
无论是GET
请求还是POST
请求,其本质都是不安全的,为什么这样说呢?如果仅仅从GET
请求的参数在地址栏是可见的,POST
是不可见的,那就太肤浅了。 由于HTTP
自己本身是一个明文协议,每个HTTP
请求和返回的数据在网络上都是明文传播,无论是url
、header
还是body
。 只要在网络节点捉包,就能获取完整的数据报文,要防止泄密的唯一手段就是使用HTTPS
(用SSL
协议协商出的密钥加密明文HTTP
数据)。
4.发送编码不同
get只能向服务器发送ASCII字符,而post则可以发送整个ISO 10646中的字符。
5. **POST
**是发送两个请求吗?
或者问:为什么get比post更快
POST
是发送两个请求吗? 上面提到POST
请求可以被分为“请求头”和“请求体”两个部分,那这两部分是一起发送出去呢?还是先发“请求头”,再发“请求体”呢? 在HTTP
协议中并没有明确说明POST
会产生两个数据包。之所以会发两个数据包,则是出于以下考虑:如果服务器先收到“请求头”,则会对其进行校验,如果校验通过,则回复客户端“100 - Continue”,客户端再把”请求体“发给服务器。如果请求被拒了,服务器就回复个400之类的错误,这个交互就终止了。这样做的优点是可以避免浪费带宽传输请求体,但是代价就是会多一次Round Trip。如果刚好请求体的数据也不多,那么一次性全部发给服务器可能反而更好。所以说,这和POST
完全没有关系,只是基于两端的一种优化手段罢了。
post请求的过程:
(1)浏览器请求tcp连接(第一次握手)
(2)服务器答应进行tcp连接(第二次握手)
(3)浏览器确认,并发送post请求头(第三次握手,这个报文比较小,所以http会在此时进行第一次数据发送)
(4)服务器返回100 Continue响应
(5)浏览器发送数据
(6)服务器返回200 OK响应
get请求的过程:
(1)浏览器请求tcp连接(第一次握手)
(2)服务器答应进行tcp连接(第二次握手)
(3)浏览器确认,并发送get请求头和数据(第三次握手,这个报文比较小,所以http会在此时进行第一次数据发送)
(4)服务器返回200 OK响应
什么时候时候用get什么时候用post
查询用get,修改用post
如果提交请求纯粹只是从服务器端获取数据而不是进行其他操作,并且多次提交不会有明显的副作用,应该使用get。比如:搜索引擎的查询(http://www.google.com/search?q=abc)和分页(user.do?page=1)
如果提交这个请求会产生其他操作和影响,就应该使用post。
比如:修改服务器上数据库中的数据;发送一封邮件;删除一个文件等
2.3 param属性
书写格式:
1、username 包含username
2、username=admin username必须为admin
3、!username 不包含username
4、!username=admin username必须不为admin
@RequestMapping(
value = {"/testRequestMapping", "/test"}
,method = {RequestMethod.GET, RequestMethod.POST}
,params = {"username","password!=123456"}
)
public String testRequestMapping(){
return "success";
}
<a th:href="@{/test(username='admin',password=123456)">
测试@RequestMapping的
params属性-->/test</a><br>
thymeleaf语法:
1、thymeleaf如果后面需要拼接参数,两种方式
<a th:href="@{/index?username=admin&password=123456}">
<a th:href="@{/index(username=admin,password=123456)}">
2.4 headers 属性
1、"header":
要求请求映射所匹配的请求必须携带header请求头信息
2、"!header":
要求请求映射所匹配的请求必须不能携带header请求头信息
3、"header=value":
要求请求映射所匹配的请求必须携带header请求头信息且header=value
4、"header!=value":
要求请求映射所匹配的请求必须携带header请求头信息且header!=value
@RequestMapping(
value = {"/hello","/abc"},
method = {RequestMethod.POST, RequestMethod.GET},
//params = {"username","!password","age=20","gender!=女"},
headers = {"Host=localhost:8080"}
)
3.获取请求参数
3.1 注解restful风格获取参数 @Pathvariable
占位符方式
<a th:href="@{/index/admin/123456}">
@RequestMappering("/index/{username}/{password}")
public String text(
@Pathvariable("username") String username,
@Pathvariable("password") Integer password
){
return "success"
}
但是restful风格无法获取键值对的参数,此时就需要用以下其他方式进行获取
3.2 原生servletapi获取键值对参数信息
用servletapi来获取键值对参数信息
<a th:href="@{/index(username=admin,password=123456)}">
@RequestMappering("/index")
public String text(HttpServletRequest request){
String name=request.getParameter("username");
String passeord=reuqest.getParameter("password")
return "success"
}
3.3用控制器的形参来(springmvc提供的方式)获取参数
3.3.1 请求参数和形参同名
<a th:href="@{/index(username=admin,password=123456)}">
@RequestMappering("/index")
public String text(String username,String password){
System.out.print("username为"username+"password为"+password)
return "success"
}
直接用同名的参数传进来
当需要获取复选框中的同名数据时,就需要用String类型的属性来接收
<a th:href="@{/index(username=admin,password=123456,hobby=a,hobby=b,hobby=c)}">
@RequestMappering("/index")
public String text(String username,String password,String hobby){
System.out.print(
"username为"username+
"password为"+password+
"hobby"+Arrays.toString(hobby)
)
return "success"
}
或者使用String[]数组来接收,
@RequestMappering("/index")
public String text(String username,String password,String[] hobby){
System.out.print(
"username为"username+
"password为"+password+
"hobby"+Arrays.toString(hobby);
)
return "success"
}
3.3.2 请求参数和形参不同名 @RequestParam
当请求参数和形参不同名字,则需要用到@RequestParam注解,使用格式:
@RequestParam(
//请求的参数名
value = "userName",
//是否必须要传此参数
//为true则必须要传,
//为flase为如果有则赋值,如果没有则采用默认值
//默认值为true
required = true,
//更改默认的值
defaultValue = "hehe"
)
String username,
3.3.3获取请求头信息@RequestHeader
3.3.4获取cookie信息@CookieValue
public String getParam(
@RequestParam(value = "userName", required = true, defaultValue = "hello") String username,
String password,
@RequestHeader("referer") String referer,
@CookieValue("JSESSIONID") String jsessionId
){
System.out.println("jsessionId:"+jsessionId);
System.out.println("referer:"+referer);
System.out.println("username:"+username+",password:"+password);
return "success";
}
3.3.5通过POJO获取请求参数
可以在控制器方法的形参位置设置一个实体类类型的形参,此时若浏览器传输的请求参数的参数名和实体类中的属性名一致,那么请求参数就会为此属性赋
<form th:action="@{/testpojo}" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
性别:<input type="radio" name="sex" value="男">男<input type="radio"
name="sex" value="女">女<br>
年龄:<input type="text" name="age"><br>
邮箱:<input type="text" name="email"><br>
<input type="submit">
</form>
4.域对象共享数据
4.1使用ServletAPI向request域对象共享数据
@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request){
request.setAttribute("testScope", "hello,servletAPI");
return "success";
}
4.2使用ModelAndView向request域对象共享数据
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
/**
* ModelAndView有Model和View的功能
* Model主要用于向请求域共享数据
* View主要用于设置视图,实现页面跳转
*/
ModelAndView mav = new ModelAndView();
//向请求域共享数据
mav.addObject("testScope", "hello,ModelAndView");
//设置视图,实现页面跳转
mav.setViewName("success");
return mav;
}
4.3使用Model向request域对象共享数据
@RequestMapping("/testModel")
public String testModel(Model model){
model.addAttribute("testScope", "hello,Model");
return "success";
}
4.4使用map向request域对象共享数据
@RequestMapping("/testMap")
public String testMap(Map<String, Object> map){
map.put("testScope", "hello,Map");
return "success";
}
4.5使用ModelMap向request域对象共享数据
@RequestMapping("/testModelMap")
public String testModelMap(ModelMap modelMap){
modelMap.addAttribute("testScope", "hello,ModelMap");
return "success";
}
在前端取出request域的数据
<p th:text="${testScope}"></p>
Model、ModelMap、Map的关系:
Model、ModelMap、Map类型的参数其实本质上都是 BindingAwareModelMap 类型的
4.6、向session域共享数据
@RequestMapping("/testSession")
public String testSession(HttpSession session){
session.setAttribute("testSessionScope", "hello,session");
return "success";
}
取出:
<p th:text="${session.testSessionScope}"></p>
4.7向application域共享数据
@RequestMapping("/testApplication")
public String testApplication(HttpSession session){
ServletContext application = session.getServletContext();
application.setAttribute("testApplicationScope", "hello,application");
return "success";
}
取出:
<p th:text="application.testApplicationScope">
5.SpringMVC视图
视图就是modelandview中的view
5.1 return "/index"
当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被SpringMVC配置文件中所配置
的视图解析器解析,此时在springmvc中配置的是thymeleaf视图解析器,那么如果默认return "/index",
那么就会直接被thymeleaf视图解析,即加上前缀加上后缀,经过渲染以后直接跳转到页面。
5.2 return "forward:/test" 转发视图(服务器内部转发)
如果是forward:格式作为返回值,那么就会将视图转发
return "forward:/test";
5.3 return "redirect:/test" 重定向视图(重新发请求)
return "redirect:/test";
//转发和重定向的区分:
重定向为浏览器给服务器发请求,controllera相应以后发现处理不了,给浏览器返回controllerb的位置,浏览器再次给controllerb发请求。
转发为浏览器给服务器发请求,虽然controllera相应以后处理不了,但是a可以直接找b,b处理完以后,再给浏览器相应,地址栏地址不变。
5.4 视图控制器
当遇到controller方法中,只执行一个跳转命名,那么可以不用在controller层中写方法,直接在springmvc配置文件中配置视图控制器,语法格式如下:
<mvc:view-controller path="/testView" view-name="success"></mvc:view-controller>
相当于:
@RequestMapping("/")
public String protal(){
return "index";
}
5.5处理静态资源
当需要处理静态资源时候,应在springmvc配置文件中开放静态资源的处理
<mvc:default-servlet-handler></mvc:default-servlet-handler>
6.RESTful风格
Representational State Transfer,简称REST。
中文名:表现层状态转移。
一句话描述REST实质:
URL中只使用名词来定位资源,用HTTP协议里的动词(GET、POST、PUT、DELETE)来实现资源的增删改查操作。
面向资源开发,
- 请求方式
GET(SELECT) | 从服务器取出资源(一项或多项) |
---|---|
POST(CREATE) | 在服务器新建一个资源 |
PUT(UPDATE) | 在服务器更新资源(更新完整资源) |
PATCH(UPDATE) | 在服务器更新资源, PATCH更新个别属性 |
DELETE(DELETE) | 从服务器删除资源 |
form表单中实现put和delete请求
1.在web.xml中配置HiddenHttpMethodFilter
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.put请求
<form th:action="@{/user}" method="post">
<input type="hidden" name="_method" value="put">
<input type="submit" value="修改用户信息">
</form>
3.post请求
<form th:action="@{/user}" method="post">
<input type="hidden" name="_method" value="delete">
<input type="submit" value="删除用户信息">
</form>
7.处理请求报文和相应报文等
HttpMessageConverter,报文信息转换器,将请求报文转换为java对象,或将java对象转化为相应报文
@RequsetBody用于将请求体转化为java对象
@ResponseBody用于将java对象转化为响应体
7.1 @RequestBody
@RequestBody可以获取请求体信息,使用@RequestBody注解标识控制器方法的形参,当前请求的请
求体就会为当前注解所标识的形参赋值
@RequestMapping(value = "/index",method = RequestMethod.POST)
public String show1(@RequestBody String s){
System.out.println("请求体为:"+s);
return "index";
}
7.2@ResponseBody
将数据给相应体并且返回给页面原生方式
@RequestMapping("/index")
public void test(HttpServletResponse response){
response.getWriter().print("hello.response");
}
用springmvc方式处理
@RequestMapping("/index")
@ResponseBody
public String test(){
return "hello,Response!";
}
上面是返回一个字符串,
那么怎么返回一个实体类呢?
需要用jackson来处理
@RequestMapping("/json")
@ResponseBody
public Notice json(){
Date date=new Date(2023,4,23);
Time time=new Time(18,14,12);
Notice notice=new Notice("wqe","231asd",date,time);
return notice;
}
操作方式:
1、导入jackson的依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.1</version>
</dependency>
2、SpringMVC的配置文件中设置开启mvc的注解驱动
<!--开启mvc的注解驱动-->
<mvc:annotation-driven />
3、使用@ResponseBody注解标识控制器方法,在方法中,将需要转换为json字符串并响应到浏览器
的java对象作为控制器方法的返回值,此时SpringMVC就可以将此对象直接转换为json字符串并响应到
浏览器
@RequestMapping("/json")
@ResponseBody
public Notice json(){
Date date=new Date(2023,4,23);
Time time=new Time(18,14,12);
Notice notice=new Notice("wqe","231asd",date,time);
return notice;
}
标签:username,return,请求,springmvc,一篇,public,password,梳理,String
From: https://www.cnblogs.com/tcyblogs/p/17379519.html