ssm-day05 springmvc
MVC框架:Spring MVC是一个基于Servlet API构建的Web框架,采用了模型-视图-控制器(MVC)架构。它支持灵活的URL到页面控制器的映射,以及多种视图技术。
作用在表述层,这个框架帮助我们先去接受前端的请求
1.Filter过滤器
2.servlet
在Java中接收前端的请求通常涉及到使用一个Web框架来处理HTTP请求。以下是几种常见的方法和框架,以及如何使用它们来接收前端请求:
1. 使用Servlet API
这是最基础的方法,直接通过Java Servlet API来处理HTTP请求。你需要创建一个类继承
HttpServlet
,然后覆写doGet
或doPost
等方法来处理GET或POST请求。import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/example") public class ExampleServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 处理GET请求 String param = request.getParameter("paramName"); response.getWriter().write("Received parameter: " + param); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 处理POST请求 String param = request.getParameter("paramName"); response.getWriter().write("Received POST parameter: " + param); } }
2. 使用Spring MVC
Spring MVC 是一个流行的MVC框架,它简化了Web应用程序的开发。你可以使用
@Controller
或@RestController
注解来定义控制器,并用@RequestMapping
、@GetMapping
、@PostMapping
等注解来映射请求路径。import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api/example") public class ExampleController { @GetMapping public String handleGet(@RequestParam(value="paramName", defaultValue="defaultValue") String paramName) { return "Received GET parameter: " + paramName; } @PostMapping public String handlePost(@RequestBody String body) { return "Received POST data: " + body; } }
3. 使用Spring Boot
Spring Boot是基于Spring框架的一个快速开发工具,它使得创建独立的、生产级别的Spring应用变得非常简单。你可以使用与Spring MVC相同的方式定义控制器,但Spring Boot提供了更简便的配置方式。
首先,创建一个Spring Boot应用程序:
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
然后定义你的控制器,就像在Spring MVC中一样。
4. 使用JAX-RS (Jersey)
JAX-RS是Java API for RESTful Web Services的缩写,而Jersey是JAX-RS的一个参考实现。你可以使用
@Path
、@GET
、@POST
等注解来定义RESTful服务。import javax.ws.rs.*; import javax.ws.rs.core.Response; @Path("/example") public class ExampleResource { @GET @Produces("text/plain") public Response getExample(@QueryParam("paramName") String paramName) { return Response.ok("Received GET parameter: " + paramName).build(); } @POST @Consumes("application/json") @Produces("text/plain") public Response postExample(String content) { return Response.ok("Received POST data: " + content).build(); } }
5. 使用其他框架
除了上述提到的框架之外,还有许多其他的Java Web框架可以用来处理前端请求,比如Play Framework, Vert.x, Dropwizard等。每个框架都有其特点和优势,选择哪一个取决于你的项目需求和个人偏好。
无论你选择哪个框架,通常都需要配置服务器(如Apache Tomcat, Jetty, 或者内置的Spring Boot服务器)来运行你的应用程序,并且需要设置路由规则来将特定的URL模式映射到相应的处理器上。此外,对于现代Web应用程序,JSON格式的数据交换是非常常见的,因此确保你的应用程序能够正确地序列化和反序列化JSON数据。
在Java Web应用程序中,
Filter
(过滤器)是用于在请求到达Servlet之前或响应返回给客户端之前执行某些预处理或后处理逻辑的组件。过滤器可以用来实现多种功能,比如认证、日志记录、字符编码设置等。要让过滤器接收前端的请求并进行处理,你需要定义一个类来实现javax.servlet.Filter
接口,并在这个类中覆写doFilter
方法。以下是一个简单的例子,展示了如何创建和配置一个过滤器来接收前端的请求:
定义过滤器
import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter("/*") // 这个过滤器将应用于所有URL模式 public class ExampleFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // 初始化过滤器时调用,可在此处加载资源或进行其他初始化操作 } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 在这里处理请求前的逻辑 System.out.println("Before request processing"); // 继续链式调用,传递给下一个过滤器或目标Servlet chain.doFilter(request, response); // 在这里处理响应后的逻辑 System.out.println("After request processing"); } @Override public void destroy() { // 当过滤器被销毁时调用,可用于清理资源 } }
配置过滤器
如果你使用的是基于注解的方式(如上面的例子),那么
@WebFilter
注解会自动注册过滤器。但是,如果你使用的是传统的XML配置方式,你可以在web.xml
文件中定义过滤器:<filter> <filter-name>exampleFilter</filter-name> <filter-class>com.example.ExampleFilter</filter-class> </filter> <filter-mapping> <filter-name>exampleFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
处理特定类型的请求
如果想要针对不同类型的HTTP请求(GET, POST, PUT, DELETE等)或者不同的URL路径应用不同的逻辑,你可以在
doFilter
方法内部添加相应的判断逻辑。例如,检查HttpServletRequest
的方法类型:import javax.servlet.http.HttpServletRequest; // ... @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) req; // 检查请求方法 if ("POST".equalsIgnoreCase(httpRequest.getMethod())) { // 处理POST请求的逻辑 System.out.println("Handling a POST request"); } else if ("GET".equalsIgnoreCase(httpRequest.getMethod())) { // 处理GET请求的逻辑 System.out.println("Handling a GET request"); } // 继续链式调用 chain.doFilter(req, resp); }
获取请求参数
你还可以从
HttpServletRequest
对象中获取请求参数:String paramValue = httpRequest.getParameter("paramName"); System.out.println("Received parameter: " + paramValue);
注意事项
- 顺序:如果你有多个过滤器,它们会按照在
web.xml
中的声明顺序依次被调用。- 性能:过滤器会影响每个请求的处理速度,因此应尽量保持过滤器的处理逻辑高效简洁。
- 安全性:过滤器是实现安全控制的好地方,比如验证用户身份或授权。
通过上述步骤,可以创建一个Java Web过滤器来接收前端的请求,并在请求到达最终的目标Servlet或控制器之前对其进行处理。
原生Servlet API开发代码片段
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String userName = request.getParameter("userName"); System.out.println("userName="+userName); }
解析:
- 方法签名:
doGet
是HttpServlet
类中的一个受保护的方法,它被覆写以处理HTTP GET请求。每当客户端发送一个GET请求到这个Servlet时,就会调用此方法。- 参数:
HttpServletRequest request
:封装了来自客户端的请求信息,包括请求头、请求体、请求参数等。HttpServletResponse response
:用于构建响应并返回给客户端,可以设置响应头、状态码、输出内容等。- 异常:该方法声明抛出
ServletException
和IOException
,这是因为在处理请求或生成响应的过程中可能会发生I/O错误或其他问题。- 实现逻辑:从请求中获取名为
userName
的参数值,并将其打印到控制台。这里使用了request.getParameter("userName")
方法来获取参数值。- 输出:使用
System.out.println
将用户名打印到控制台。在实际生产环境中,通常不会直接打印到控制台,而是会使用日志框架(如Log4j、SLF4J)进行记录。基于SpringMVC开发代码片段
@RequestMapping("/user/login") public String login(@RequestParam("userName") String userName, String password){ log.debug("userName="+userName); // 调用业务逻辑 return "result"; }
解析:
- 注解:
@RequestMapping
是一个Spring MVC的注解,用来映射Web请求到控制器的具体方法。这里的/user/login
表示当收到对/user/login
路径的请求时,应该调用这个login
方法。- 参数:
@RequestParam("userName") String userName
:这是一个Spring MVC提供的注解,用于绑定请求参数到方法参数。如果请求URL中包含?userName=John
,那么userName
变量将被赋值为"John"
。如果没有提供该参数,且没有设置默认值,则会抛出MissingServletRequestParameterException
。String password
:同样,这是另一个请求参数,它将接收URL中的password
参数。注意,在原始代码中有一个拼写错误,应该是String password
而不是Sting password
。- 日志记录:
log.debug("userName="+userName);
使用了一个日志记录器(log
)来记录调试信息。这通常是通过配置日志框架(如Logback、Log4j2)来实现的。debug
级别的日志只有在应用程序的日志级别设置为DEBUG或更低时才会被记录。- 业务逻辑:注释提到“调用业务即可”,这意味着在这个位置应该编写或者调用服务层的代码来执行具体的业务逻辑,例如验证用户登录信息。
- 返回值:
return "result";
这里的字符串"result"
通常指的是视图名称,即Spring MVC将会查找与之对应的视图模板(如JSP页面、Thymeleaf模板等),并将模型数据传递给它以便渲染最终的HTML页面返回给客户端。当然,如果你使用的是RESTful风格的API,你可能会返回JSON或XML格式的数据,而不是视图名称。差异总结
- 框架依赖:原生Servlet API不依赖任何第三方框架,而Spring MVC是基于Spring框架的,提供了更多的特性和更简洁的语法。
- 配置方式:Servlet需要通过
web.xml
文件或使用@WebServlet
注解来配置URL映射;而Spring MVC主要通过注解(如@Controller
、@RequestMapping
)来定义路由。- 参数绑定:在Servlet中,你需要手动从
HttpServletRequest
对象中提取参数;而在Spring MVC中,你可以使用@RequestParam
、@PathVariable
等注解来自动绑定请求参数到方法参数。- 视图解析:Servlet直接操作
HttpServletResponse
来生成响应内容,可能涉及直接写出HTML或JSON;而Spring MVC通常返回一个逻辑视图名称,由视图解析器负责选择合适的视图技术来渲染响应。- 日志记录:在Servlet中,开发者往往直接使用
System.out.println
或引入日志库进行日志记录;而在Spring MVC项目中,通常已经集成了日志框架,可以直接使用日志记录器进行日志管理。这两种方式各有优劣,选择哪一种取决于项目的具体需求和技术栈的选择。对于现代Java Web开发,Spring MVC(或其简化版本Spring Boot)因其丰富的功能和简便的配置而更为流行。
servlet下去得补一下
框架就是在基础上帮我们完成了一些封装,不用花时间在繁琐的基础操作上,专注于写业务
简化Controller层的操作
每个方法称为一个处理器
Handler不是Controller
一个Servlet类直接放在那是不会生效的 除非xml文件配置或者注解配置
要导入的依赖
@RequestMapper做的事情就是把Hander方法的信息存储到HandlerMapper中,即设置对外访问的地址
先按这个走,不用管讲义
替代了web-xml文件
了解内容
项目部署这块回头再看一下尚硅谷的web课
p103讲义上没有 没听懂回头再理解一下
看不懂的归纳一下,就是现在你看到的这个实现在启动的时候会被调用,然后其中一个方法会调用我们以前创建context的方法,所以中间这个方法实际上传入你的iocconfig和你手动创建一样的
进阶注解只能使用在方法上
输出是soup
@ResponseBody这个注解能给前端返回
内部会创建一个ioc容器,把这个配置类指定
必须传但是传错报400异常
属性名必须等于参数名
路径越短,解析效率越高,详细好处在后面RESTFul再说
JSON数据的发出需要用到post方式
JSON数据格式它是js中的一种对象表达形式
对应的实体类是Java中的对象表达
上传JSON格式:
Body->raw JSON
Cookie是Web开发中的一个小文件,它存储在用户的浏览器中,并且可以在用户访问同一网站时被服务器读取。Cookies的主要用途是保存状态信息,以便于网站识别用户和提供个性化服务。以下是对Cookie的详细解析:
1. Cookie的构成
一个Cookie通常由以下几个部分组成:
- 名称(Name):每个Cookie都有一个唯一的名称,用来区分不同的Cookie。
- 值(Value):与名称关联的数据,可以是任意文本字符串。
- 过期时间/有效期(Expires/Max-Age):定义了Cookie的有效期限。如果没有设置这个参数,Cookie将被视为会话Cookie,在浏览器关闭后即失效。
- 路径(Path):指定了哪些页面可以访问该Cookie。默认情况下,创建Cookie的页面及其子路径都可以访问该Cookie。
- 域(Domain):规定了哪些域名下的页面可以访问该Cookie。例如,如果设置了
.example.com
,那么所有子域名如www.example.com
、mail.example.com
等都可以共享该Cookie。- 安全标志(Secure):当设置了这个标志后,Cookie只会在HTTPS连接下发送给服务器,增加了安全性。
- HttpOnly标志:如果设置了这个标志,JavaScript代码将无法通过
document.cookie
接口访问该Cookie,有助于防止XSS攻击。2. Cookie的工作原理
- 当用户访问一个网站时,服务器可以通过HTTP响应头中的
Set-Cookie
字段向客户端发送Cookie。- 浏览器接收到包含
Set-Cookie
头的响应后,会按照其规则存储这些Cookie。- 在后续对同一站点的请求中,浏览器会自动将相关Cookie添加到HTTP请求头中(通常是
Cookie
字段),发送回服务器。- 服务器端可以根据收到的Cookie来识别用户并提供相应服务。
3. Cookie的使用场景
- 保持登录状态:用户登录后,服务器生成一个认证Token并将其作为Cookie发送给客户端,后续请求中携带此Cookie即可维持登录状态。
- 购物车功能:记录用户加入购物车的商品信息,即使关闭浏览器重新打开也能保留这些数据。
- 个性化推荐:根据用户的浏览历史或偏好设置,为用户提供定制化的内容或广告。
- A/B测试:用于跟踪不同版本页面的表现,帮助优化用户体验。
4. Cookie的安全性
虽然Cookie非常有用,但它们也存在一些安全隐患,因此需要采取措施确保安全:
- 设置Secure标志:确保Cookie只能通过HTTPS协议传输,避免在网络传输过程中被窃听。
- 启用HttpOnly标志:防止通过JavaScript访问Cookie,减少XSS攻击的风险。
- 限制Cookie的生命周期:不要设置过长的有效期,尤其是对于包含敏感信息的Cookie。
- 使用加密技术:对Cookie中的重要数据进行加密处理,即使被截获也无法轻易解读。
- 注意跨站请求伪造(CSRF):即使有Cookie存在,也应该实现额外的验证机制,比如要求用户输入验证码或检查Referer头信息。
5. Cookie的局限性
- 大小限制:大多数浏览器对单个Cookie的大小有限制(通常为4KB),并且整个域名下的所有Cookie总和也有上限。
- 数量限制:某些浏览器对每个域名可存储的Cookie数量进行了限制。
- 隐私问题:由于Cookie能够追踪用户的活动,因此可能引发隐私担忧,特别是在第三方Cookie的情况下。
- 不支持无状态协议:RESTful API等设计倾向于无状态,而Cookie则引入了一定的状态管理,这在某些架构中可能是不利的。
综上所述,Cookie是一个强大但需谨慎使用的工具。在现代Web应用中,开发者不仅要了解如何正确地创建和使用Cookie,还要关注其带来的安全性和性能方面的影响。
这张图片展示了一个名为
CookieController.java
的Java类,该类使用了Spring框架来处理HTTP请求。以下是代码的详细解析:1. 控制器注解
@Controller @RequestMapping("/cookie")
@Controller
:这是一个Spring MVC注解,用于标记一个类作为控制器类。@RequestMapping("/cookie")
:这个注解指定该控制器处理所有以/cookie
开头的URL请求。2. 获取Cookie
@ResponseBody public class CookieController { @GetMapping("data") public String data(@CookieValue(value = "cookieName") String value){ System.out.println("value = " + value); return value; } }
@ResponseBody
:这个注解表示该方法返回的内容将直接作为HTTP响应体返回,而不是视图名称。@GetMapping("data")
:这个注解指定该方法处理GET请求,并且请求路径为/cookie/data
。@CookieValue(value = "cookieName") String value
:这个注解用于从请求头中的Cookie中获取名为cookieName
的Cookie值。如果存在这样的Cookie,则将其值绑定到参数value
上;否则,value
将为null
。3. 设置Cookie
@GetMapping("save") public String save(HttpServletResponse response){ Cookie cookie = new Cookie("cookieName", "root"); response.addCookie(cookie); return "ok"; }
@GetMapping("save")
:这个注解指定该方法处理GET请求,并且请求路径为/cookie/save
。HttpServletResponse response
:这是HTTP响应对象,通过它可以设置响应头信息。Cookie cookie = new Cookie("cookieName", "root");
:创建一个新的Cookie对象,名称为cookieName
,值为root
。response.addCookie(cookie);
:将创建的Cookie添加到HTTP响应头中,这样当客户端接收到响应时,浏览器会存储这个Cookie。return "ok";
:返回字符串"ok"
作为响应内容。总结
这段代码展示了如何在Spring MVC中使用
@CookieValue
注解来读取和设置Cookie。具体来说:
data
方法用于读取名为cookieName
的Cookie值,并打印出来。save
方法用于设置一个名为cookieName
、值为root
的Cookie,并将其添加到HTTP响应头中。这种方式非常适合于需要在客户端和服务器之间传递少量数据的情况,例如保持用户登录状态或记录用户的偏好设置等。
本地有cookie的话每次请求都会把cookie通过请求头携带回去
在Web开发中,原生对象(Native Objects)指的是由JavaScript语言本身提供的、内置的对象。这些对象是浏览器环境的一部分,它们提供了对浏览器和操作系统功能的访问接口。理解原生对象及其获取方式对于编写高效、可维护的JavaScript代码至关重要。
1. 原生对象分类
原生对象可以分为以下几类:
- 全局对象(Global Objects):如
Object
、Array
、String
、Number
、Boolean
、Function
等。- 基本包装类型(Primitive Wrapper Objects):如
String
、Number
、Boolean
,用于包装原始数据类型的值。- 错误对象(Error Objects):如
Error
、EvalError
、RangeError
、ReferenceError
、SyntaxError
、TypeError
、URIError
,用于处理不同类型的错误。- 日期和时间对象(Date and Time Objects):如
Date
,用于表示和操作日期和时间。- 正则表达式对象(Regular Expression Object):如
RegExp
,用于定义和使用正则表达式。- 数学对象(Math Object):提供了一组静态属性和方法来进行数学计算。
- JSON对象(JSON Object):用于解析和序列化JSON数据。
- 其他对象(Other Objects):如
Promise
、Map
、Set
、WeakMap
、WeakSet
等,提供了额外的功能和数据结构。2. 获取原生对象的方法
2.1 使用构造函数
大多数原生对象可以通过其构造函数来创建实例。例如:
javascript
let myArray = new Array(); // 创建一个空数组 let myString = new String("Hello World"); // 创建一个字符串对象 let myNumber = new Number(42); // 创建一个数字对象
然而,对于基本包装类型(如
String
、Number
、Boolean
),通常建议直接使用原始值,因为它们在需要时会自动被转换为对应的对象:javascript
let myString = "Hello World"; // 直接使用字符串原始值 let myNumber = 42; // 直接使用数字原始值
2.2 使用字面量语法
对于一些常见的原生对象,如
Array
、Object
、Function
等,可以使用更简洁的字面量语法来创建:javascript
let myArray = []; // 创建一个空数组 let myObject = {}; // 创建一个空对象 let myFunction = function() {}; // 创建一个空函数
2.3 访问全局对象
全局对象可以直接通过其名称来访问,因为它们是在全局作用域中定义的。例如:
javascript
console.log(Math.PI); // 访问数学对象的PI属性 console.log(JSON.stringify({name: "John"})); // 使用JSON对象将对象序列化为字符串
2.4 使用
typeof
运算符
typeof
运算符可以用来检查变量或表达式的类型,它返回一个表示数据类型的字符串。这可以帮助确定一个值是否属于某个特定的原生对象类型:javascript
console.log(typeof {}); // "object" console.log(typeof []); // "object" (注意:数组实际上是对象) console.log(typeof null); // "object" (这是一个历史遗留问题) console.log(typeof "hello"); // "string" console.log(typeof 42); // "number" console.log(typeof true); // "boolean" console.log(typeof undefined); // "undefined" console.log(typeof function(){}); // "function"
2.5 使用
instanceof
运算符
instanceof
运算符用于检查一个对象是否是某个构造函数的实例。这对于确认对象的类型特别有用:javascript
let myArray = []; console.log(myArray instanceof Array); // true
2.6 使用
Object.prototype.toString.call()
这个方法可以用来获得对象的内部
[[Class]]
属性,它可以更准确地判断对象的类型,尤其是对于null
和array
这样的特殊情况:javascript
console.log(Object.prototype.toString.call([])); // "[object Array]" console.log(Object.prototype.toString.call(null)); // "[object Null]"
3. 注意事项
- 性能考虑:使用原始值比使用包装对象更高效,因为包装对象在每次访问时都会创建新的对象实例。
- 避免不必要的构造函数调用:尽量使用字面量语法创建对象和数组,以提高代码的可读性和性能。
- 正确区分类型:了解
typeof
和instanceof
的区别,并根据需要选择合适的方式来检查类型。
共享域就是一种数据间接传递的手段
共享域(Shared Domain)通常指的是多个应用程序或服务之间共享的域名空间,它们可以在相同的域名下运行,并且能够通过该域名互相通信。在Web开发中,共享域可以用于实现跨应用的功能集成、资源共享和统一的身份验证等。以下是对共享域的详细解析:
1. 共享域的概念
- 单个域名下的多应用:共享域意味着多个不同的Web应用程序或服务可以部署在同一域名的不同路径下,或者使用子域名来区分不同的应用。
- 资源和数据共享:在共享域中,各个应用可以通过统一的域名访问共享的静态资源(如图片、CSS、JavaScript文件)和动态资源(如API接口),从而简化了资源管理和跨应用的数据交互。
- 单一登录(SSO, Single Sign-On):用户只需登录一次,就可以访问共享域下的所有应用程序,而不需要再次进行身份验证。
2. 实现共享域的方法
2.1 使用子域名
- 定义:子域名是主域名的一部分,格式为
subdomain.domain.com
。例如,在example.com
下,可以创建app1.example.com
、app2.example.com
等子域名,每个子域名可以托管一个独立的应用程序。- 优点:
- 每个子域名可以有独立的安全策略和配置。
- 便于扩展和管理,适合大型企业级应用。
- 可以利用DNS负载均衡和服务发现机制来优化性能和可用性。
- 缺点:
- 需要额外的DNS配置和SSL证书管理。
- 子域名之间的Cookie默认是隔离的,需要特别设置才能共享。
2.2 使用路径分隔
- 定义:在同一个域名下使用不同的路径来区分不同的应用程序,例如
example.com/app1
、example.com/app2
。这种方式适用于较小规模的应用集成。- 优点:
- 简化了域名管理和SSL证书的配置。
- Cookie和会话信息可以在整个域名下共享,方便实现单一登录。
- 对于SEO友好,因为所有页面都在同一域名下。
- 缺点:
- 所有应用都依赖于同一个域名,如果域名出现问题,所有应用都会受到影响。
- 路径分隔可能导致URL变得复杂,影响用户体验。
2.3 使用反向代理
- 定义:通过反向代理服务器(如Nginx、Apache)将请求路由到不同的后端服务。客户端只需要知道一个统一的入口域名,实际的请求会被转发到相应的后端服务器。
- 优点:
- 提供了灵活性,可以轻松地添加或移除后端服务,而不影响客户端。
- 支持负载均衡和缓存,提高系统的性能和可扩展性。
- 可以实现细粒度的安全控制,如基于路径或请求头的访问限制。
- 缺点:
- 增加了系统复杂性和维护成本。
- 如果反向代理服务器出现故障,可能会影响整个系统的可用性。
3. 共享域中的安全考虑
- 跨站脚本攻击(XSS):确保每个应用都有严格的输入验证和输出编码,防止恶意脚本注入。
- 跨站请求伪造(CSRF):实施CSRF防护措施,如使用CSRF Token,确保请求来自可信来源。
- 跨域资源共享(CORS):正确配置CORS策略,允许或限制特定域名的跨域请求,保护敏感数据。
- Cookie安全:对于共享Cookie,务必设置
HttpOnly
和Secure
标志,防止通过JavaScript访问和传输Cookie。- 权限管理:即使是在共享域内,也应严格控制不同应用之间的权限,避免不必要的数据泄露。
4. 共享域的应用场景
- 微服务架构:在微服务环境中,多个独立的服务可以部署在共享域下,通过统一的入口提供服务。
- 多租户平台:SaaS(软件即服务)平台通常使用共享域来为不同客户提供定制化的应用体验,同时保持系统的统一性和安全性。
- 电子商务网站:大型电商网站可能会将不同的业务模块(如商品展示、购物车、支付等)部署在共享域下,以实现无缝的用户体验。
- 内部协作工具:企业内部的协作工具(如邮件、日历、文档管理等)可以整合到共享域中,方便员工在一个平台上完成多种任务。
5. 实践建议
- 规划域名结构:根据业务需求和技术架构,合理规划域名和子域名的使用,确保清晰易懂。
- 标准化API设计:为共享域内的各个应用定义统一的API规范,促进互操作性和可维护性。
- 持续监控和优化:定期检查共享域的性能和安全性,及时发现并解决问题,保障系统的稳定运行。
- 文档化配置:记录所有的域名配置、SSL证书信息和安全策略,方便团队成员理解和维护。
总之,共享域是一种强大的技术手段,它可以帮助组织实现更高效的应用集成和资源共享。然而,这也带来了额外的安全挑战和管理复杂性,因此在实施时必须谨慎规划和执行。
后面几个接收可能过的有点快,但这块不是重点,再理解就行
响应数据
混合开发模式只能返回html页面给浏览器
动态页面:根据传入的Java·数据动态的展示html内容
常见的有jsp(Javaee里面的)、thymeleaf
共享域下去在尚硅谷的web课程中学一下
我们都有光明的未来!!加油鸭
不要被别人的节奏影响了......
如何从controller跳到一个模板语言
如何响应json数据
快速返回逻辑视图
jsp是视图解析器处理以后才能执行效果
jsp是后台的模板语言,是展示共享域中的数据
重点不是语法,语法特别简单后面可以去了解一下
视图解析器是springMVC的一个组件
@EnableWebMvc相当于整合注解,会帮我们加好经理、秘书和json转换器
WebMvcConfigurer接口用来配置Mvc的组件,会提供springmvc需要组件的方法,简化配置mvc需要的组件,不用使用@Bean去进行组件创建了
配置jsp视图解析器
handler返回视图
这行代码
model.addAttribute("msg", "request data!!");
是Spring MVC框架中用于向模型(Model)添加属性的典型用法。它允许你在控制器层将数据传递给视图层,以便在视图中展示或使用这些数据。下面是对这行代码的详细解析:1.
model
参数
来源:
model
是一个实现了Model
接口的对象,通常是由 Spring MVC 自动注入到控制器方法中的。你可以通过在控制器方法的参数列表中声明Model
类型的参数来获取它。@Controller public class MyController { @RequestMapping("/example") public String handleRequest(Model model) { // 使用model对象 return "viewName"; } }
作用:
model
对象充当了控制器和视图之间的桥梁,用于存储需要传递给视图的数据。它可以看作是一个键值对的集合,其中键是属性名,值是要传递的数据。2.
addAttribute
方法
签名:
Model
接口提供了多个重载版本的addAttribute
方法,但最常用的两个是:
void addAttribute(String attributeName, Object attributeValue)
:将指定名称的属性及其对应的值添加到模型中。void addAttribute(Object attributeValue)
:当只提供一个参数时,Spring会自动为该属性生成一个默认的名称,通常是类名的小写形式(对于JavaBean),或者直接使用“value”作为名称(对于其他类型的对象)。功能:
addAttribute
方法的作用是将数据添加到模型中,使得这些数据可以在视图中访问。具体来说,它会在内部创建一个键值对,其中键是属性名,值是你提供的对象。这个键值对随后会被传递给视图解析器,最终在渲染视图时使用。3. 参数详解
jsp
"msg"
:这是你为要添加的属性指定的名称。在视图中,你可以通过这个名称来引用该属性。例如,在JSP页面中,可以使用表达式语言(EL)${msg}
来输出这个属性的值。<p>${msg}</p>
"request data!!"
:这是你要添加到模型中的实际数据。在这个例子中,它是一个简单的字符串,但在实际应用中,attributeValue
可以是任何Java对象,比如实体类、集合、映射等。4. 完整示例
假设我们有一个名为
MyController
的控制器类,其中包含一个处理HTTP请求的方法handleRequest
。在这个方法中,我们想要向视图传递一条消息,并显示在页面上。@Controller public class MyController { @RequestMapping("/example") public String handleRequest(Model model) { // 向模型中添加一个名为"msg"的属性,其值为"request data!!" model.addAttribute("msg", "request data!!"); // 返回逻辑视图名称,由视图解析器解析为具体的视图资源 return "exampleView"; // 这个名称会被视图解析器解析为 /WEB-INF/views/exampleView.jsp } }
在相应的JSP页面(
exampleView.jsp
)中,你可以这样使用这个属性:jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Example Page</title> </head> <body> <h1>Welcome to the Example Page!</h1> <p>Message from the controller: ${msg}</p> </body> </html>
当你访问
/example
URL 时,服务器端会执行handleRequest
方法,将"msg"
属性添加到模型中,然后返回逻辑视图名称exampleView
。视图解析器会根据配置找到对应的 JSP 文件并进行渲染,最后浏览器会显示包含"request data!!"
消息的页面。5. 其他相关方法
除了
addAttribute
,Model
接口还提供了其他一些有用的方法来管理模型数据:
getAttribute(String attributeName)
:获取模型中指定名称的属性值。containsAttribute(String attributeName)
:检查模型中是否包含指定名称的属性。mergeAttributes(Map<String, ?> attributes)
:将一个Map
中的所有键值对添加到模型中。clear()
:清除模型中的所有属性。6. 总结
model.addAttribute("msg", "request data!!");
这行代码非常简单却非常重要,它展示了如何在Spring MVC中从控制器层向视图层传递数据。通过这种方式,我们可以轻松地将业务逻辑处理的结果呈现给用户,同时保持代码的清晰和模块化。理解并熟练掌握这一机制,对于开发高效、可维护的Web应用程序至关重要。
返回一个逻辑视图名
动态封装共享域中的数据,最后打包成一个html页面返回给前端
在JavaWeb开发中,JSP(JavaServer Pages)和视图解析器是两个非常重要的概念。它们共同作用于将服务器端的数据渲染为客户端可以理解的HTML页面。下面我们将详细讲解JSP的作用、工作原理以及如何与视图解析器配合使用来实现动态内容生成。
1. JSP (JavaServer Pages)
1.1 定义
JSP是一种用于构建动态Web页面的技术,它允许开发者在普通的HTML代码中嵌入Java代码片段。JSP文件通常以
.jsp
扩展名保存,并且可以在其中包含静态的HTML标记、JSP脚本元素(如表达式、声明和脚本段)、JSP指令(如<%@ page %>
、<%@ include %>
、<%@ taglib %>
)以及自定义标签库。1.2 工作原理
当浏览器请求一个JSP页面时,Web容器(如Tomcat)会执行以下步骤:
- 编译:首先,JSP文件会被编译成一个Servlet类。这个过程是一次性的,即只有第一次访问该JSP页面时才会进行编译。之后的请求会直接使用已经编译好的Servlet。
- 执行:编译后的Servlet会在服务器端运行,处理HTTP请求并生成响应内容。在这个过程中,JSP中的Java代码被执行,动态生成HTML或其他格式的内容。
- 发送响应:最后,生成的内容被作为HTTP响应发送回客户端浏览器显示给用户。
1.3 优点
- 易于编写:JSP结合了HTML和Java的优势,使得前端和后端逻辑能够紧密结合,降低了开发难度。
- 可重用性:通过JSP指令和自定义标签库,可以轻松地复用代码和组件,提高开发效率。
- 跨平台:基于Java技术栈,JSP应用可以在任何支持Java的平台上运行。
1.4 缺点
- 性能问题:由于每次请求都需要经过编译和执行的过程,对于高并发场景可能会带来一定的性能开销。不过,现代的Web容器通常会对JSP页面进行缓存优化,以减轻这个问题。
- 维护复杂度:随着项目规模的增长,混合了大量HTML和Java代码的JSP文件可能变得难以维护。为了改善这种情况,推荐采用MVC设计模式,将视图层与业务逻辑分离。
2. 视图解析器
2.1 定义
视图解析器是SpringMVC框架中的一个重要组件,它的主要职责是根据控制器返回的逻辑视图名称,找到对应的物理视图资源(如JSP文件),并将模型数据传递给视图进行渲染。这样做的好处是可以让控制器专注于业务逻辑,而不需要关心具体的视图实现细节。
2.2 类型
SpringMVC提供了多种类型的视图解析器,适用于不同的视图技术。以下是几种常见的视图解析器:
xml
InternalResourceViewResolver
:这是最常用的视图解析器之一,主要用于解析JSP页面。它会将逻辑视图名称映射到Web应用程序内部的资源路径上。例如,如果控制器返回了一个名为“index”的逻辑视图,则InternalResourceViewResolver
会查找/WEB-INF/views/index.jsp
这样的路径。<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean>
xml
UrlBasedViewResolver
:类似于InternalResourceViewResolver
,但它更加通用,可以解析任意类型的视图资源,不仅限于JSP。你还可以配置它来支持Thymeleaf、Freemarker等其他模板引擎。<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean>
BeanNameViewResolver
:这种视图解析器会尝试根据逻辑视图名称查找一个与之同名的Spring Bean。这意味着你可以为每个视图创建一个独立的Bean,并在其中定义更复杂的渲染逻辑。
ContentNegotiatingViewResolver
:用于根据客户端的Accept头信息选择合适的视图类型。这对于RESTful API特别有用,因为它可以根据请求的内容协商机制返回不同格式的数据(如JSON、XML)。2.3 配置示例
假设我们正在使用SpringMVC框架,并希望将所有的JSP页面放置在
/WEB-INF/views/
目录下,那么可以在Spring配置文件中添加如下配置:xml
<!-- Spring MVC配置 --> <mvc:annotation-driven /> <!-- 视图解析器配置 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean>
2.4 使用示例
在控制器中,我们可以简单地返回逻辑视图名称,而不必关心具体的视图实现:
java
@Controller public class HelloController { @RequestMapping("/hello") public String sayHello(Model model) { // 添加模型数据 model.addAttribute("message", "Hello, World!"); // 返回逻辑视图名称 return "hello"; // 这个名称会被视图解析器解析为 /WEB-INF/views/hello.jsp } }
3. JSP与视图解析器的配合
- 逻辑视图名称:控制器方法通常返回一个字符串形式的逻辑视图名称,而不是实际的视图路径。这个名称将由视图解析器负责转换为具体的视图资源。
- 模型数据传递:通过
Model
、ModelMap
或Map
等接口,控制器可以向视图传递需要展示的数据。这些数据将在视图解析器找到正确的视图后,自动注入到视图中供其使用。- 视图渲染:一旦视图解析器确定了具体的视图资源,它就会调用该视图来进行渲染。对于JSP页面来说,这包括执行嵌入的Java代码、处理表达式语言(EL)以及应用自定义标签库等操作,最终生成完整的HTML响应内容。
4. 总结
JSP作为一种动态Web页面技术,提供了强大的功能来生成个性化的内容。而视图解析器则是SpringMVC框架中用于解耦控制器和视图的关键组件。通过合理配置视图解析器,可以使我们的Web应用更加模块化、易于维护,并且能够灵活地适应不同的视图技术。在实际开发中,建议遵循MVC设计模式,将业务逻辑、控制逻辑和表示逻辑分开,从而提高代码的质量和可读性。
转发和重定向实现
默认返回字符串都要找视图
方法的打印输出快捷键好像是soutm
转发使用forward关键字,
重定向使用redirect关键字
重定向可以是项目外的资源
重定向会显示最后一个资源的位置
访问项目下的所有资源都要先写根路径,再写controller里面的路径
在JavaWeb开发中,转发(Forward)和重定向(Redirect)是两种常见的请求处理方式,它们用于控制客户端的请求流程。尽管两者都可以将用户从一个页面导航到另一个页面,但它们的工作机制、应用场景和对浏览器地址栏的影响都有显著差异。以下是关于转发和重定向的详细解析:
1. 转发(Forward)
1.1 定义
转发是在服务器端完成的请求处理过程中的内部跳转。当一个Servlet或JSP页面接收到请求后,它可以选择将请求转发给另一个资源(如另一个Servlet、JSP页面或其他类型的Web组件),而不是直接响应客户端。这个过程对于客户端来说是透明的,即客户端并不知道发生了转发操作。
1.2 工作原理
- 单次请求:转发发生在同一请求-响应周期内,客户端只发送了一次HTTP请求。
- URL不变:由于转发是在服务器端进行的,因此客户端的浏览器地址栏不会发生变化,仍然显示最初的请求URL。
- 共享请求对象:转发过程中,原始的
HttpServletRequest
和HttpServletResponse
对象会被传递给目标资源,这意味着可以在转发链中共享请求参数和属性。1.3 实现方式
通过
RequestDispatcher
接口:这是最常用的方法。你可以使用ServletContext
或ServletRequest
提供的getRequestDispatcher()
方法来获取RequestDispatcher
实例,然后调用其forward()
方法实现转发。// 假设我们有一个名为"target.jsp"的目标页面 RequestDispatcher dispatcher = request.getRequestDispatcher("/target.jsp"); dispatcher.forward(request, response);
通过框架提供的API:如果你使用的是SpringMVC等框架,通常会有更简洁的方式来实现转发,例如返回视图名称字符串或者使用特定的注解。
1.4 优点与适用场景
- 性能更好:因为只有一次HTTP请求,所以转发通常比重定向更快。
- 适合内部逻辑流转:当你需要在一个应用内部的不同组件之间进行逻辑流转时,转发是一个很好的选择。例如,在执行完某些业务逻辑后,将结果页面展示给用户。
- 保持请求上下文:可以保留原始请求的所有信息,包括请求参数和会话数据,这对于构建复杂的Web应用非常有用。
1.5 缺点
- 安全性问题:如果转发的目标资源是受保护的(例如需要登录才能访问),那么必须确保在转发之前已经完成了必要的认证和授权检查,否则可能会导致安全漏洞。
- 不利于SEO:由于URL不变化,这可能会影响搜索引擎优化(SEO),特别是当不同的内容对应相同的URL时。
2. 重定向(Redirect)
2.1 定义
重定向是指服务器告知客户端(通常是浏览器)去访问一个新的URL,而不是直接响应最初的请求。客户端接收到3xx状态码(如302 Found)后,会自动发起新的HTTP请求以访问指定的新URL。对于用户而言,他们会看到浏览器地址栏中的URL发生了变化。
2.2 工作原理
- 两次请求:重定向涉及到两个独立的HTTP请求-响应周期。第一次请求被服务器处理后返回一个重定向响应,客户端根据响应中的新URL发起第二次请求。
- URL变化:浏览器地址栏会更新为新的URL,用户可以看到并记录下这个新的地址。
- 不共享请求对象:由于重定向是通过客户端发起新的请求实现的,因此原始的
HttpServletRequest
和HttpServletResponse
对象不会被传递到新的请求中。任何想要共享的数据都需要通过URL参数或Cookie等方式传递。2.3 实现方式
通过
HttpServletResponse
对象:可以直接使用HttpServletResponse
提供的sendRedirect()
方法来实现重定向。该方法接受一个完整的URL作为参数,并向客户端发送一个302状态码以及Location头信息指向新的URL。// 重定向到"new-target.jsp" response.sendRedirect("new-target.jsp");
通过框架提供的API:类似地,SpringMVC等框架也提供了简单的方式来进行重定向,比如返回带有
redirect:
前缀的字符串。@RequestMapping("/somePath") public String handleRequest() { // 重定向到"/anotherPath" return "redirect:/anotherPath"; }
2.4 优点与适用场景
- 明确的URL映射:重定向可以使每个页面都有唯一的URL,这对于SEO和用户体验都非常有利。
- 跨域访问:重定向可以将用户引导到不同的域名或协议下的资源,而转发只能在同一应用内部进行。
- 清除表单数据:当用户提交表单后,使用重定向可以避免刷新页面时再次提交表单的问题,这种模式被称为POST-REDIRECT-GET (PRG) 模式。
2.5 缺点
- 性能稍差:由于需要额外的HTTP请求,重定向可能会稍微降低性能。
- 数据传递受限:不能直接共享请求对象中的数据,如果需要传递数据,只能通过URL参数或持久化存储(如Session)。
3. 转发 vs 重定向
特性 转发(Forward) 重定向(Redirect) 请求次数 单次请求 两次请求 URL变化 不变 变化 共享请求对象 是 否 适合场景 内部逻辑流转、保持请求上下文 明确的URL映射、跨域访问、清除表单数据 性能 较好 稍差 安全性 需要谨慎处理 更加安全 4. 选择合适的策略
- 内部逻辑流转:如果你的应用逻辑只需要在同一个应用内部的不同组件之间流转,且不需要改变浏览器地址栏中的URL,那么应该优先考虑使用转发。
- 外部链接或跨域访问:当需要将用户引导到不同域名或协议下的资源时,必须使用重定向。
- SEO和用户体验:为了提高搜索引擎排名和提供更好的用户体验,尽量为每个页面分配唯一的URL,这时重定向可能是更好的选择。
- 防止重复提交:对于表单提交后的处理,推荐采用POST-REDIRECT-GET模式,即先处理表单数据,然后重定向到一个GET请求的页面,这样可以避免用户刷新页面时重复提交表单。
综上所述,理解和正确使用转发和重定向对于构建高效、安全和用户体验良好的Web应用程序至关重要。选择合适的方式取决于具体的应用需求和技术要求。
返回json数据
前置通过@EnableWebMvc这个注解给handlerAdapater配好json转换器
直接在handler方法上返回对应的对象
@RequestBody 将请求体中的json数据由经理帮忙转为实体对象赋值
外部传json的话,集合得用@PostMapper方法访问
静态资源处理
静态资源指的是纯html页面、图片等等
静态资源不能放在这个文件夹下,外部访问不了
RESTFul
URI相当于统一资源标识符,里面包括url
请求方式回归动作
路径回归名词
全局异常处理机制
三层架构只要抓住controller层处理就行,service和dao层的异常都可以往上抛
1.某些异常发生我们自己怎么处理 怎么给用户反馈
2.使用注解配置
1.声明全局异常处理类 @RestControllerAdvice(底层实际是AOP
2.加若干个异常处理方法 通过@ExceptionHandler来指定对应的异常就可以了
拦截器使用
过滤器
filter - doFilter
拦截器的前置方法是靠方法的返回值跳出拦截的 返回值是false !后为true走return
迷迷糊糊
参数校验
使用校验注解完成校验
复习很关键!!