一、spring 框架简单搭建
有两种方法在本地快速搭建一个 spring 项目(本地环境已经安装好 maven 和 Tomcat);
- 网站搭建 https://start.spring.io/
- 本地搭建 在 idea 新建一个 maven- webapp 项目;
Spring 项目文件目录 MVC
阶段1:
在浏览器打开一个网址,发送一个 web 请求到后端服务器,由 controller 入口解析参数,字段;
阶段2:
service 通过 dao 层获取相应的服务数据,返回给前端;
阶段3:
dao 层为数据访问服务,从 数据库获取数据。
简单服务器演示
@Controller
public class IndexController {
@RequestMapping(path = {"/","/index"}, method = {RequestMethod.GET})
@ResponseBody
public String Index(){
return "Hello Now";
}
@RequestMapping(path = {"profile/{groupId}/{userId}"})
@ResponseBody
public String profile(@PathVariable("userId") int userId, @PathVariable("groupId") String groupId,
@RequestParam(value="type", defaultValue = "1") int type,
@RequestParam(value = "key", required = false) String key){
// return "Profile page of "+userId ;
return String.format("Profile page of %d from %s, t = %d; k = %s",userId,groupId,type,key);
}
}
@Controller
用于标记在一个类上,使用它标记的类就是一个SpringMvc Controller对象,分发处理器会扫描使用该注解的类的方法,并检测该方法是否使用了@RequestMapping注解。
@Controller只是定义了一个控制器类,而使用@RequestMapping注解的方法才是处理请求的处理器。
@RequestMapping
开发者需要在控制器内部为每一个请求动作开发相应的处理方法。org.springframework.web.bind.annotation.RequestMapping 注解类型指示Spring用哪一个类或方法处理请求动作,该注解可用于类和方法。
@RequestMapping可以用来注释一个控制器类,在这种情况下,所有方法都将映射为相对于类级别的请求,表示该控制器处理的所有请求都被映射到value属性所指示的路径下。
@ResponseBody
作用在方法上,表示该方法的返回结果直接写入 HTTP response body 中,一般在异步获取数据时使用【也就是AJAX】;在使用 @RequestMapping后,返回值通常解析为跳转路径,但是加上 @ResponseBody 后返回结果不会被解析为跳转路径,而是直接写入 HTTP response body 中。 比如异步获取 json 数据,加上 @ResponseBody 后,会直接返回 json 数据。
一般网站只用Get和Post,代表获取和更新,html的form仅支持Get和Post
静态和模板文件
静态
默认目录:static/templates
文件:css/js/images
模板文件
默认目录:templates
文件:xxx.vm
待补充
request、response
@RequestMapping(path = {"/request"}, method = {RequestMethod.GET})
@ResponseBody
public String request(Model model, HttpServletResponse response,
HttpServletRequest request,
HttpSession session,
@CookieValue("JSESSIONID") String sessionId){
StringBuilder sb = new StringBuilder();
// 注解获取 Cookie
sb.append("CookieValue" + sessionId + "<br>");
// 请求头获取
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()){
String name = headerNames.nextElement();
sb.append(name + ":" + request.getHeader(name) + "<br>");
}
// 获取 cookie
if (request.getCookies() != null){
for (Cookie cookie : request.getCookies()){
sb.append("Cookie : " + cookie.getName() + "value: " + cookie.getValue() + "<br>");
// sb.append("Cookie domain : " + cookie.getDomain()+ "<br>");
// sb.append("Cookie Comment : " + cookie.getComment()+ "<br>");
// sb.append("Cookie Path : " + cookie.getPath()+ "<br>");
// sb.append("Cookie MaxAge : " + cookie.getMaxAge()+ "<br>");
// sb.append("Cookie secure : " + cookie.getSecure()+ "<br>");
// sb.append("Cookie version : " + cookie.getVersion()+ "<br>");
// sb.append("Cookie class : " + cookie.getClass()+ "<br>");
}
}
sb.append(request.getMethod() + "<br>");
sb.append(request.getPathInfo() + "<br>");
sb.append(request.getQueryString() + "<br>");
sb.append(request.getRequestURL() + "<br>");
response.addHeader("nowcoder","Hello");
response.addCookie(new Cookie("usename","nowcoder"));
return sb.toString();
}
request
参数解析、cookie 读取、 http 请求字段、 文件上传
response
页面内容返回、 cookie 下发、 http 字段设置、headers
基础方法
-
HttpServletResponse
response.addCookie(new Cookie(key, value));
response.addHeader(key, value);
-
HttpServletRequest
request.getHeaderNames();
request.getMethod()
request.getPathInfo()
request.getQueryString()
重定向、异常
重定向
302临时跳转
// @RequestMapping(path = {"/redirect/{code}"},method = {RequestMethod.GET})
// public String redirect302(@PathVariable("code") int code, HttpSession session){
// session.setAttribute("msg"," jump from 302 redirect");
// return "redirect:/";
// }
// 301强制跳转
@RequestMapping(path = {"/redirect/{code}"},method = {RequestMethod.GET})
public RedirectView redirect301(@PathVariable("code") int code, HttpSession session){
session.setAttribute("msg"," jump from 301 redirect");
RedirectView red = new RedirectView("/",true);
if (code == 301){
red.setStatusCode(HttpStatus.MOVED_PERMANENTLY);
}
return red ;
}
可以通过 HttpSession,将信息带回将跳转页。
@RequestMapping(path = {"/","/index"}, method = {RequestMethod.GET})
@ResponseBody
public String Index(HttpSession session){
return "Hello Now"+session.getAttribute("msg");
}
异常捕获
// 异常捕获
@ExceptionHandler()
@ResponseBody
public String error(Exception e){
return "error" + e.getMessage();
}
// 异常抛出
@RequestMapping(path = {"/admin"},method = {RequestMethod.GET})
@ResponseBody
public String admin(@PathParam("key") String key){
if ("admin".equals(key))
return "Hello admin";
throw new IllegalArgumentException("参数错误");
}
Ioc(DI) 依赖注入
简化了对象依赖关系的管理,把面向对象过程中需要执行的如何新建对象、为对象引用赋值等操作交由容器统一管理,使用注解的方式引入。
服务类实例:
1.新建一个 service 类,使用 spring 注解为 Service
@Service
public class WendaService {
public String getMessage(int userId){
return "Hello Message: " + String.valueOf(userId);
}
}
2.在 controller 类中引用,并使用 Autowried 注解
@Autowired是用在JavaBean中的注解,通过byType形式,用来给指定的字段或方法注入所需的外部资源
@Controller
public class SettingController {
@Autowired
private WendaService wendaService;
@RequestMapping(path = {"/setting"},method = {RequestMethod.GET})
@ResponseBody
public String setting(HttpSession session){
return "Setting ok. " + wendaService.getMessage(2);
}
}
AOP 面向切面编程
AOP的理念:就是将分散在各个业务逻辑代码中相同的代码通过横向切割的方式抽取到一个独立的模块中!
日志类切面实例
1.新建一个 日志切面类, 使用 Aspect 注解为切面
@Component 把普通pojo实例化成一个组件到 spring 容器中
@Aspect
@Component
public class LogAspect {
private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);
@Before("execution(* com.nowcoder.controller.*.*(..))")
public void beforeMethod(){
logger.info("before method " + new Date());
}
@Before("execution(* com.nowcoder.controller.*.*(..))")
public void beforeMethodJP(JoinPoint joinPoint){
StringBuilder sb = new StringBuilder();
for (Object arg : joinPoint.getArgs()){
sb.append("arg: "+ arg.toString() + "|");
}
logger.info(sb.toString());
}
@After("execution(* com.nowcoder.controller.*.*(..))")
public void afterMethod(){
logger.info("after method " + new Date());
}
}
@Before("execution(* com.nowcoder.controller..(..))")
注解execution([返回类] [顶层包名].[次级包名].[..包名].[类名].[函数方法](参数))
在包、类名中可通过通配符